# Visualization Library

A lightweight C++ OpenGL middleware for 2D/3D graphics

[Home] [Tutorials] [All Classes] [Grouped Classes]

- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

# D:/VL/BuildSystem/VL_DISTRO/Visualization_Library_SDK/src/vlMolecule/Molecule_rendering.cpp

Go to the documentation of this file.

    00001 /**************************************************************************************/
    00002 /*                                                                                    */
    00003 /*  Visualization Library                                                             */
    00004 /*  http://www.visualizationlibrary.com                                               */
    00005 /*                                                                                    */
    00006 /*  Copyright (c) 2005-2010, Michele Bosi                                             */
    00007 /*  All rights reserved.                                                              */
    00008 /*                                                                                    */
    00009 /*  Redistribution and use in source and binary forms, with or without modification,  */
    00010 /*  are permitted provided that the following conditions are met:                     */
    00011 /*                                                                                    */
    00012 /*  - Redistributions of source code must retain the above copyright notice, this     */
    00013 /*  list of conditions and the following disclaimer.                                  */
    00014 /*                                                                                    */
    00015 /*  - Redistributions in binary form must reproduce the above copyright notice, this  */
    00016 /*  list of conditions and the following disclaimer in the documentation and/or       */
    00017 /*  other materials provided with the distribution.                                   */
    00018 /*                                                                                    */
    00019 /*  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND   */
    00020 /*  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED     */
    00021 /*  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE            */
    00022 /*  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR  */
    00023 /*  ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES    */
    00024 /*  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;      */
    00025 /*  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON    */
    00026 /*  ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT           */
    00027 /*  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS     */
    00028 /*  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.                      */
    00029 /*                                                                                    */
    00030 /**************************************************************************************/
    00031
    00032 #include <vlMolecule/Molecule.hpp>
    00033 #include <vlGraphics/GeometryPrimitives.hpp>
    00034 #include <vlGraphics/Text.hpp>
    00035 #include <vlGraphics/Light.hpp>
    00036
    00037 using namespace vl;
    00038
    00039 //-----------------------------------------------------------------------------
    00040 class EffectCache
    00041 {
    00042 public:
    00043   EffectCache(): mLight(new Light(0)) {}
    00044
    00045   void clear() { effects().clear(); }
    00046
    00047   Effect* acquireEffect(const fvec4& color)
    00048   {
    00049     for(unsigned i=0; i<effects().size(); ++i)
    00050     {
    00051       if (effects()[i]->shader()->gocMaterial()->frontDiffuse() == color)
    00052       {
    00053         return effects()[i].get();
    00054       }
    00055     }
    00056
    00057     ref<Effect> fx = new Effect;
    00058     fx->shader()->enable(EN_DEPTH_TEST);
    00059     fx->shader()->enable(EN_CULL_FACE);
    00060     fx->shader()->enable(EN_LIGHTING);
    00061     fx->shader()->setRenderState(mLight.get());
    00062     fx->shader()->gocMaterial()->setDiffuse(color);
    00063     effects().push_back(fx.get());
    00064     return fx.get();
    00065   }
    00066
    00067   const std::vector< ref<Effect> >& effects() const { return mEffects; }
    00068   std::vector< ref<Effect> >& effects() { return mEffects; }
    00069
    00070   const Light* light() const { return mLight.get(); }
    00071   Light* light() { return mLight.get(); }
    00072
    00073 protected:
    00074   std::vector< ref<Effect> > mEffects;
    00075   ref<Light> mLight;
    00076 };
    00077 //-----------------------------------------------------------------------------
    00078 class AtomGeometryCache
    00079 {
    00080 public:
    00081   AtomGeometryCache(): mDetail(1) {}
    00082
    00083   void clear() { mGeometryMap.clear(); }
    00084   const std::map< float, ref<Geometry> >& geometryMap() const { return mGeometryMap; }
    00085   std::map< float, ref<Geometry> >& geometryMap() { return mGeometryMap; }
    00086   Geometry* acquireAtomGeometry(float radius)
    00087   {
    00088     std::map< float, ref<Geometry> >::iterator it = geometryMap().find(radius);
    00089     if (it!=geometryMap().end())
    00090       return it->second.get();
    00091     else
    00092     {
    00093       ref<Geometry> sphere = makeIcosphere( vec3(0,0,0), radius*2.0f, detail() );
    00094       geometryMap()[radius] = sphere;
    00095       return sphere.get();
    00096     }
    00097   }
    00098
    00099   int detail() const { return mDetail; }
    00100   void setDetail(int detail) { mDetail = detail; }
    00101
    00102 protected:
    00103   std::map< float, ref<Geometry> > mGeometryMap;
    00104   int mDetail;
    00105 };
    00106 //-----------------------------------------------------------------------------
    00107 class BondGeometryCache
    00108 {
    00109   class BondKey
    00110   {
    00111   public:
    00112     float height;
    00113     fvec4 col1;
    00114     fvec4 col2;
    00115     ECapsuleCap top_cap;
    00116     ECapsuleCap bottom_cap;
    00117
    00118     BondKey(float h, const fvec4& c1, const fvec4& c2, ECapsuleCap topcap, ECapsuleCap bottomcap): height(h), col1(c1), col2(c2), top_cap(topcap), bottom_cap(bottomcap) {}
    00119     bool operator==(const BondKey& other) const
    00120     {
    00121       return height     == other.height  &&
    00122              col1       == other.col1    &&
    00123              col2       == other.col2    &&
    00124              top_cap    == other.top_cap &&
    00125              bottom_cap == other.bottom_cap;
    00126     }
    00127     bool operator<(const BondKey& other) const
    00128     {
    00129       if (top_cap!=other.top_cap)
    00130         return top_cap<other.top_cap;
    00131       else
    00132       if (bottom_cap!=other.bottom_cap)
    00133         return bottom_cap<other.bottom_cap;
    00134       else
    00135       if (height!=other.height)
    00136         return height<other.height;
    00137       else
    00138       if (col1!=other.col1)
    00139         return col1<other.col1;
    00140       else
    00141         return col2<other.col2;
    00142     }
    00143   };
    00144 public:
    00145   BondGeometryCache(): mDetail(20), mDiameter(0.20f), mQuantization(100.0f) {}
    00146
    00147   void clear() { mGeometryMap.clear(); }
    00148   const std::map< BondKey, ref<Geometry> >& geometryMap() const { return mGeometryMap; }
    00149   std::map< BondKey, ref<Geometry> >& geometryMap() { return mGeometryMap; }
    00150   Geometry* acquireBondGeometry(float length, const fvec4& c1, const fvec4& c2, ECapsuleCap top_cap, ECapsuleCap bottom_cap)
    00151   {
    00152     float quant_lenght = int(length*quantization()) / quantization();
    00153     BondKey key(quant_lenght,c1,c2,top_cap,bottom_cap);
    00154     std::map< BondKey, ref<Geometry> >::iterator it = geometryMap().find( key );
    00155     if (it!=geometryMap().end())
    00156     {
    00157       VL_CHECK(it->first == key)
    00158       return it->second.get();
    00159     }
    00160     else
    00161     {
    00162       ref<Geometry> cylinder = makeCapsule( diameter()/2.0f, quant_lenght+2.0f/quantization(), detail(), top_cap, bottom_cap, c2, c1 );
    00163       cylinder->computeNormals();
    00164       geometryMap()[key] = cylinder;
    00165       return cylinder.get();
    00166     }
    00167   }
    00168
    00169   int detail() const { return mDetail; }
    00170   void setDetail(int detail) { mDetail = detail; }
    00171
    00172   float diameter() const { return mDiameter; }
    00173   void setDiameter(float diameter) { mDiameter = diameter; }
    00174
    00175   float quantization() const { return mQuantization; }
    00176   void setQuantization(float quantization) { mQuantization = quantization; }
    00177
    00178 protected:
    00179   std::map< BondKey, ref<Geometry> > mGeometryMap;
    00180   int mDetail;
    00181   float mDiameter;
    00182   float mQuantization;
    00183 };
    00184 //-----------------------------------------------------------------------------
    00185 void Molecule::prepareForRendering()
    00186 {
    00187   actorTree()->actors()->clear();
    00188   transformTree()->eraseAllChildren();
    00189
    00190   switch(moleculeStyle())
    00191   {
    00192     case MS_Wireframe:    wireframeStyle();    generateRings(); break;
    00193     case MS_BallAndStick: ballAndStickStyle(); generateRings(); break;
    00194     case MS_Sticks:       sticksStyle();       generateRings(); break;
    00195     case MS_AtomsOnly:    atomsStyle();                         break;
    00196   }
    00197   generateAtomLabels();
    00198   transformTree()->computeWorldMatrixRecursive();
    00199 }
    00200 //-----------------------------------------------------------------------------
    00201 void Molecule::generateAtomLabel(const Atom* atom, Transform* tr)
    00202 {
    00203   if (atomLabelTemplate()->font() &&
    00204       showAtomNames()             &&
    00205       atom->visible()             &&
    00206       atom->showAtomName()        )
    00207   {
    00208     ref<Text> text = new Text;
    00209     // text label
    00210     text->setText( atom->atomName().c_str() );
    00211     // text template style
    00212     text->setViewportAlignment( atomLabelTemplate()->viewportAlignment() );
    00213     text->setTextAlignment( atomLabelTemplate()->textAlignment() );
    00214     text->setShadowVector( atomLabelTemplate()->shadowVector() );
    00215     text->setShadowEnabled( atomLabelTemplate()->shadowEnabled() );
    00216     text->setShadowColor( atomLabelTemplate()->shadowColor() );
    00217     text->setOutlineEnabled( atomLabelTemplate()->outlineEnabled() );
    00218     text->setOutlineColor( atomLabelTemplate()->outlineColor() );
    00219     text->setMode( atomLabelTemplate()->mode() );
    00220     text->setMargin( atomLabelTemplate()->margin() );
    00221     text->setKerningEnabled( atomLabelTemplate()->kerningEnabled() );
    00222     text->setFont( atomLabelTemplate()->font() );
    00223     text->setColor( atomLabelTemplate()->color() );
    00224     text->setBorderEnabled( atomLabelTemplate()->borderEnabled() );
    00225     text->setBorderColor( atomLabelTemplate()->borderColor() );
    00226     text->setBackgroundEnabled( atomLabelTemplate()->backgroundEnabled() );
    00227     text->setBackgroundColor( atomLabelTemplate()->backgroundColor() );
    00228     text->setAlignment( atomLabelTemplate()->alignment() );
    00229     // text actor
    00230     ref<Actor> text_act = new Actor( text.get(), mAtomLabelEffect.get(), tr );
    00231     actorTree()->actors()->push_back(text_act.get());
    00232   }
    00233 }
    00234 //-----------------------------------------------------------------------------
    00235 void Molecule::generateAtomLabels()
    00236 {
    00237   for(unsigned i=0; i<atoms().size(); ++i)
    00238   {
    00239     ref<Transform> tr = new Transform(mat4::getTranslation((vec3)atoms()[i]->coordinates()));
    00240     transformTree()->addChild(tr.get());
    00241     generateAtomLabel(atoms()[i].get(), tr.get());
    00242   }
    00243 }
    00244 //-----------------------------------------------------------------------------
    00245 void Molecule::wireframeStyle()
    00246 {
    00247   ref<Geometry> geom = new Geometry;
    00248   ref<ArrayFloat3> points = new ArrayFloat3;
    00249   geom->setVertexArray(points.get());
    00250   ref<ArrayFloat4> colors = new ArrayFloat4;
    00251   geom->setColorArray(colors.get());
    00252   std::vector<fvec3> pt;
    00253   std::vector<fvec4> cols;
    00254   for(unsigned ibond=0; ibond<bonds().size(); ++ibond)
    00255   {
    00256     Bond* b = bond(ibond);
    00257     if (b->visible() && b->atom1()->visible() && b->atom2()->visible())
    00258     {
    00259       fvec4 c1 = b->color();
    00260       fvec4 c2 = b->color();
    00261       if (b->useAtomColors())
    00262       {
    00263         c1 = b->atom1()->color();
    00264         c2 = b->atom2()->color();
    00265       }
    00266       if (c1 == c2)
    00267       {
    00268         pt.push_back( b->atom1()->coordinates() );
    00269         pt.push_back( b->atom2()->coordinates() );
    00270         cols.push_back(c1);
    00271         cols.push_back(c1);
    00272       }
    00273       else
    00274       {
    00275         fvec3 center = (b->atom1()->coordinates() + b->atom2()->coordinates())/2.0f;
    00276         pt.push_back( b->atom1()->coordinates() );
    00277         pt.push_back( center );
    00278         pt.push_back( center );
    00279         pt.push_back( b->atom2()->coordinates() );
    00280         cols.push_back(c1);
    00281         cols.push_back(c1);
    00282         cols.push_back(c2);
    00283         cols.push_back(c2);
    00284       }
    00285     }
    00286   }
    00287   *points = pt;
    00288   *colors = cols;
    00289   geom->drawCalls()->push_back(new DrawArrays(PT_LINES, 0, (int)points->size()));
    00290
    00291   ref<Effect> fx = new Effect;
    00292   fx->shader()->enable(EN_DEPTH_TEST);
    00293   if (smoothLines())
    00294   {
    00295     fx->shader()->enable(EN_BLEND);
    00296     fx->shader()->enable(EN_LINE_SMOOTH);
    00297   }
    00298   if (lineWidth() != 1.0f)
    00299     fx->shader()->gocLineWidth()->set(lineWidth());
    00300
    00301   actorTree()->actors()->push_back( new Actor(geom.get(), fx.get(), NULL) );
    00302 }
    00303 //-----------------------------------------------------------------------------
    00304 void Molecule::atomsStyle()
    00305 {
    00306   EffectCache fx_cache;
    00307   AtomGeometryCache atom_geom_cache;
    00308   atom_geom_cache.setDetail(atomDetail());
    00309   for(unsigned iatom=0; iatom<atoms().size(); ++iatom)
    00310   {
    00311     if (atom(iatom)->visible())
    00312     {
    00313       Effect* fx = fx_cache.acquireEffect(atom(iatom)->color());
    00314       float r = atom(iatom)->radius();
    00315       ref<Geometry> ball = atom_geom_cache.acquireAtomGeometry(r);
    00316       ref<Actor> atom_act = new Actor( ball.get(), fx, new Transform );
    00317       atom_act->transform()->setLocalMatrix( mat4::getTranslation( (vec3)atom(iatom)->coordinates()) );
    00318       transformTree()->addChild(atom_act->transform());
    00319       actorTree()->actors()->push_back( atom_act.get() );
    00320     }
    00321   }
    00322 }
    00323 //-----------------------------------------------------------------------------
    00324 void Molecule::ballAndStickStyle()
    00325 {
    00326   EffectCache fx_cache;
    00327   AtomGeometryCache atom_geom_cache;
    00328   atom_geom_cache.setDetail(atomDetail());
    00329   for(unsigned int iatom=0; iatom<atoms().size(); ++iatom)
    00330   {
    00331     if (atom(iatom)->visible())
    00332     {
    00333       Effect* fx = fx_cache.acquireEffect(atom(iatom)->color());
    00334       float r = atom(iatom)->radius();
    00335       ref<Geometry> ball = atom_geom_cache.acquireAtomGeometry(r);
    00336       ref<Actor> atom_act = new Actor( ball.get(), fx, new Transform );
    00337       atom_act->transform()->setLocalMatrix( mat4::getTranslation( (vec3)atom(iatom)->coordinates()) );
    00338       transformTree()->addChild(atom_act->transform());
    00339       actorTree()->actors()->push_back( atom_act.get() );
    00340     }
    00341   }
    00342
    00343   ref<Effect> fx = new Effect;
    00344   fx->shader()->enable(EN_DEPTH_TEST);
    00345   fx->shader()->enable(EN_CULL_FACE);
    00346   fx->shader()->gocMaterial()->setColorMaterialEnabled(true);
    00347   fx->shader()->gocLightModel()->setTwoSide(false);
    00348   fx->shader()->enable(EN_LIGHTING);
    00349   fx->shader()->setRenderState( fx_cache.light() );
    00350   // fx->shader()->gocPolygonMode()->set(PM_LINE, PM_LINE);
    00351
    00352   BondGeometryCache bond_geom_cache;
    00353   bond_geom_cache.setDetail(bondDetail());
    00354   for(unsigned int ibond=0; ibond<bonds().size(); ++ibond)
    00355   {
    00356     if (bond(ibond)->visible() && bond(ibond)->atom1()->visible() && bond(ibond)->atom2()->visible())
    00357     {
    00358       Bond* b = bond(ibond);
    00359       fvec4 c1 = b->color();
    00360       fvec4 c2 = b->color();
    00361       if (b->useAtomColors())
    00362       {
    00363         c1 = b->atom1()->color();
    00364         c2 = b->atom2()->color();
    00365       }
    00366       float len = (b->atom1()->coordinates() - b->atom2()->coordinates()).length();
    00367       float diam = b->radius()*2.0f;
    00368       bond_geom_cache.setDiameter(diam);
    00369       ref<Geometry> geom = bond_geom_cache.acquireBondGeometry(len,c1,c2,CC_NoCap,CC_NoCap);
    00370       ref<Actor> bond_act = new Actor( geom.get(), fx.get(), new Transform );
    00371       transformTree()->addChild(bond_act->transform());
    00372       fvec3 center = (b->atom1()->coordinates() + b->atom2()->coordinates()) / 2.0f;
    00373       fvec3 direction = (b->atom2()->coordinates() - b->atom1()->coordinates()).normalize();
    00374       fmat4 mat = fmat4::getTranslation(center) * fmat4::getRotation(fvec3(0,1,0), direction);
    00375       bond_act->transform()->setLocalMatrix( (mat4)mat );
    00376       actorTree()->actors()->push_back( bond_act.get() );
    00377     }
    00378   }
    00379 }
    00380 //-----------------------------------------------------------------------------
    00381 void Molecule::sticksStyle()
    00382 {
    00383   ref<Effect> fx = new Effect;
    00384   fx->shader()->enable(EN_DEPTH_TEST);
    00385   fx->shader()->enable(EN_CULL_FACE);
    00386   fx->shader()->gocMaterial()->setColorMaterialEnabled(true);
    00387   fx->shader()->gocLightModel()->setTwoSide(false);
    00388   fx->shader()->enable(EN_LIGHTING);
    00389   fx->shader()->setRenderState( new Light(0) );
    00390   /*fx->shader()->gocPolygonMode()->set(PM_LINE, PM_LINE);*/
    00391
    00392   BondGeometryCache bond_geom_cache;
    00393   bond_geom_cache.setDetail(bondDetail());
    00394   for(unsigned int ibond=0; ibond<bonds().size(); ++ibond)
    00395   {
    00396     if (bond(ibond)->visible() && bond(ibond)->atom1()->visible() && bond(ibond)->atom2()->visible())
    00397     {
    00398       Bond* b = bond(ibond);
    00399       fvec4 c1 = b->color();
    00400       fvec4 c2 = b->color();
    00401       if (b->useAtomColors())
    00402       {
    00403         c1 = b->atom1()->color();
    00404         c2 = b->atom2()->color();
    00405       }
    00406       float len = (b->atom1()->coordinates() - b->atom2()->coordinates()).length();
    00407       float diam = b->radius()*2.0f;
    00408       bond_geom_cache.setDiameter(diam);
    00409       ref<Geometry> geom = bond_geom_cache.acquireBondGeometry(len,c1,c2,CC_RoundedCap,CC_RoundedCap);
    00410       ref<Actor> bond_act = new Actor( geom.get(), fx.get(), new Transform );
    00411       transformTree()->addChild(bond_act->transform());
    00412       fvec3 center = (b->atom1()->coordinates() + b->atom2()->coordinates()) / 2.0f;
    00413       fvec3 direction = (b->atom2()->coordinates() - b->atom1()->coordinates()).normalize();
    00414       fmat4 mat = fmat4::getTranslation(center) * fmat4::getRotation(fvec3(0,1,0), direction);
    00415       bond_act->transform()->setLocalMatrix( (mat4)mat );
    00416       actorTree()->actors()->push_back( bond_act.get() );
    00417     }
    00418   }
    00419 }
    00420 //-----------------------------------------------------------------------------
    00421 void Molecule::generateRings()
    00422 {
    00423   if (!cycles().empty())
    00424   {
    00425     ref<Geometry> geom = new Geometry;
    00426     ref<ArrayFloat3> points = new ArrayFloat3;
    00427     geom->setVertexArray(points.get());
    00428     ref<ArrayFloat4> colors = new ArrayFloat4;
    00429     geom->setColorArray(colors.get());
    00430     std::vector<fvec3> pt;
    00431     std::vector<fvec4> cols;
    00432     for(unsigned icycle=0; icycle<cycles().size(); ++icycle)
    00433     {
    00434       AABB aabb;
    00435       for(unsigned iatom=0; iatom<cycle(icycle).size(); ++iatom)
    00436         aabb += (vec3)cycle(icycle)[iatom]->coordinates();
    00437       fvec3 center = (fvec3)aabb.center();
    00438
    00439       for(unsigned iatom=0; iatom<cycle(icycle).size(); ++iatom)
    00440       {
    00441         int iatom2 = (iatom+1) % cycle(icycle).size();
    00442         fvec3 v1 = cycle(icycle)[iatom ]->coordinates();
    00443         fvec3 v2 = cycle(icycle)[iatom2]->coordinates();
    00444         v1 += (center-v1).normalize() * ringOffset();
    00445         v2 += (center-v2).normalize() * ringOffset();
    00446         pt.push_back( v1 );
    00447         pt.push_back( v2 );
    00448         cols.push_back( aromaticRingColor() );
    00449         cols.push_back( aromaticRingColor() );
    00450       }
    00451     }
    00452     *points = pt;
    00453     *colors = cols;
    00454     geom->drawCalls()->push_back(new DrawArrays(PT_LINES, 0, (int)points->size()));
    00455
    00456     ref<Effect> fx = new Effect;
    00457     fx->shader()->enable(EN_DEPTH_TEST);
    00458
    00459     actorTree()->actors()->push_back( new Actor(geom.get(), fx.get(), NULL) );
    00460   }
    00461 }
    00462 //-----------------------------------------------------------------------------

Visualization Library v2011.05.1142 Reference Documentation
Copyright 2005-2011 Michele Bosi. All rights reserved.
Updated on Thu May 26 2011 22:51:26.
Permission is granted to use this page to write and publish articles regarding Visualization Library.