Visualization Library

A lightweight C++ OpenGL middleware for 2D/3D graphics
[Home] [Tutorials] [All Classes] [Grouped Classes]

X:/dropbox/visualizationlibrary/src/vlGraphics/Extrusion.cpp

Go to the documentation of this file.
00001 /**************************************************************************************/
00002 /*                                                                                    */
00003 /*  Visualization Library                                                             */
00004 /*  http://www.visualizationlibrary.org                                               */
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 <vlGraphics/Extrusion.hpp>
00033 #include <vlGraphics/Tessellator.hpp>
00034 #include <vlCore/glsl_math.hpp>
00035 
00036 using namespace vl;
00037 
00038 ref<Geometry> Extrusion::extrude(bool compatibilityProfile)
00039 {
00040   if (silhouette().empty())
00041   {
00042     Log::error("Extrusion::extrude(): no silhouette defined.\n");
00043     return NULL;
00044   }
00045   if (positionPath().empty())
00046   {
00047     Log::error("Extrusion::extrude() needs at least a non empty positionPath().\n");
00048     return NULL;
00049   }
00050   if (!scalingPath().empty() && scalingPath().size() != positionPath().size()-2)
00051   {
00052     Log::error("Extrusion::extrude(): scalingPath() must have the same number of control points as positionPath().\n");
00053     return NULL;
00054   }
00055   if (!rotationPath().empty() && rotationPath().size() != positionPath().size()-2)
00056   {
00057     Log::error("Extrusion::extrude(): rotationPath() must have the same number of control points as positionPath().\n");
00058     return NULL;
00059   }
00060   if (!colorPath().empty() && colorPath().size() != positionPath().size()-2)
00061   {
00062     Log::error("Extrusion::extrude(): colorPath() must have the same number of control points as positionPath().\n");
00063     return NULL;
00064   }
00065 
00066   ref<Geometry> geom = new Geometry;
00067 
00068   size_t segments = positionPath().size()-2;
00069 
00070   std::vector<fvec3> verts;
00071   verts.resize( silhouette().size() * segments );
00072 
00073   vl::fmat4 m = fmat4::getRotation(fvec3(0,1,0),positionPath()[1]-positionPath()[0]);
00074 
00075   // initialize silhouette on the x/z plane
00076   std::vector<vl::fvec3> projected_sil;
00077   projected_sil.resize(silhouette().size());
00078   for(unsigned i=0; i<silhouette().size(); ++i)
00079   {
00080     projected_sil[i] = m * vl::fvec3(silhouette()[i].x(),0,silhouette()[i].y()) + positionPath()[0];
00081   }
00082 
00083   // initialize plane normals from 1 to n-1 (end points are excluded)
00084   std::vector<fvec3> plane_normals;
00085   plane_normals.resize(positionPath().size());
00086   for(unsigned i=1; i<plane_normals.size()-1; ++i)
00087   {
00088     fvec3 p0 = positionPath()[i-1] - positionPath()[i];
00089     fvec3 p1 = positionPath()[i+1] - positionPath()[i];
00090     p0.normalize();
00091     p1.normalize();
00092     plane_normals[i] = (p1-p0).normalize();
00093   }
00094 
00095   for(unsigned i=1; i<positionPath().size()-1; ++i)
00096   {
00097     for(int j=0; j<(int)silhouette().size(); ++j)
00098     {
00099       fvec3 V = (positionPath()[i] - positionPath()[i-1]).normalize();
00100       const fvec3& P = projected_sil[j];
00101       const fvec3& orig = positionPath()[i];
00102       const fvec3& N = plane_normals [i];
00103       float d = dot(N,orig);
00104       float t = dot(V,N) ? (d-dot(P,N))/dot(V,N) : 0 /*error*/;
00105       // project current projected_sil on next plane along p0->p1 vector
00106       verts.at(j+silhouette().size()*(i-1)) = projected_sil[j] = P + V*t;
00107     }
00108   }
00109 
00110   // rotation
00111   if(!rotationPath().empty())
00112   {
00113     for(unsigned i=1; i<positionPath().size()-1; ++i)
00114     {
00115       fvec3 r = (positionPath()[i+1] - positionPath()[i]).normalize();
00116       fmat4 mat = vl::fmat4::getRotation(rotationPath()[i-1],r);
00117       fvec3 c;
00118       for(int j=0; j<(int)silhouette().size(); ++j)
00119         c += verts.at(j+silhouette().size()*(i-1));
00120       c /= (float)silhouette().size();
00121       for(int j=0; j<(int)silhouette().size(); ++j)
00122         verts.at(j+silhouette().size()*(i-1)) = (mat*(verts.at(j+silhouette().size()*(i-1))-c))+c;
00123     }
00124   }
00125 
00126   // scaling
00127   if(!scalingPath().empty())
00128   {
00129     for(unsigned i=1; i<positionPath().size()-1; ++i)
00130     {
00131       float s = scalingPath()[i-1];
00132       fvec3 c;
00133       for(int j=0; j<(int)silhouette().size(); ++j)
00134         c += verts.at(j+silhouette().size()*(i-1));
00135       c /= (float)silhouette().size();
00136       for(int j=0; j<(int)silhouette().size(); ++j)
00137         verts.at(j+silhouette().size()*(i-1)) = (s*(verts.at(j+silhouette().size()*(i-1))-c))+c;
00138     }
00139   }
00140 
00141   int prof_count = silhouetteMode() == SilhouetteClosed ? (int)silhouette().size() : (int)silhouette().size()-1;
00142   ref<DrawElementsUInt> de = new DrawElementsUInt(PT_QUADS);
00143   geom->drawCalls()->push_back(de.get());
00144   de->indexBuffer()->resize(4 * prof_count * (segments-1));
00145   for(size_t iseg=0; iseg<segments-1; ++iseg)
00146   {
00147     for(int iquad=0; iquad<prof_count; ++iquad)
00148     {
00149       de->indexBuffer()->at(iquad*4+iseg*4*prof_count + 3) = (iseg + 0) * (GLuint)silhouette().size() + iquad;
00150       de->indexBuffer()->at(iquad*4+iseg*4*prof_count + 2) = (iseg + 0) * (GLuint)silhouette().size() + (iquad+1)%silhouette().size();
00151       de->indexBuffer()->at(iquad*4+iseg*4*prof_count + 1) = (iseg + 1) * (GLuint)silhouette().size() + (iquad+1)%silhouette().size();
00152       de->indexBuffer()->at(iquad*4+iseg*4*prof_count + 0) = (iseg + 1) * (GLuint)silhouette().size() + iquad;
00153     }
00154   }
00155 
00156   // bottom/top caps
00157 
00158   size_t tess_bottom_count = 0;
00159   size_t tess_top_count    = 0;
00160 
00161   if(fillBottom())
00162   {
00163     size_t start = verts.size();
00164     Tessellator tessellator;
00165     tessellator.contours().push_back((int)silhouette().size());
00166     for(unsigned i=0; i<silhouette().size(); ++i)
00167       tessellator.contourVerts().push_back((dvec3)verts[i]);
00168     tessellator.setWindingRule(vl::TW_TESS_WINDING_NONZERO);
00169     tessellator.tessellate();
00170     for(unsigned i=0; i<tessellator.tessellatedTris().size(); ++i)
00171       verts.push_back(tessellator.tessellatedTris()[i]);
00172     if (tessellator.tessellatedTris().size())
00173       geom->drawCalls()->push_back( new DrawArrays(PT_TRIANGLES, start, tessellator.tessellatedTris().size()) );
00174     tess_bottom_count = tessellator.tessellatedTris().size();
00175   }
00176   if(fillTop())
00177   {
00178     size_t start = verts.size();
00179     Tessellator tessellator;
00180     tessellator.contours().push_back(silhouette().size());
00181     for(unsigned i=0; i<silhouette().size(); ++i)
00182       tessellator.contourVerts().push_back((dvec3)verts[verts.size()-i-1-tess_bottom_count]);
00183     tessellator.setWindingRule(vl::TW_TESS_WINDING_NONZERO);
00184     tessellator.tessellate();
00185     for(unsigned i=0; i<tessellator.tessellatedTris().size(); ++i)
00186       verts.push_back(tessellator.tessellatedTris()[i]);
00187     if (tessellator.tessellatedTris().size())
00188       geom->drawCalls()->push_back( new DrawArrays(PT_TRIANGLES, start, tessellator.tessellatedTris().size()) );
00189     tess_top_count = tessellator.tessellatedTris().size();
00190   }
00191 
00192   ref<ArrayFloat3> vert_array = new ArrayFloat3;
00193   if(compatibilityProfile)
00194     geom->setVertexArray( vert_array.get() );
00195   else
00196     geom->setVertexAttribArray(VA_Position, vert_array.get());
00197   vert_array->initFrom(verts);
00198 
00199   if (!colorPath().empty())
00200   {
00201     ref<ArrayFloat4> col_array = new ArrayFloat4;
00202     if(compatibilityProfile)
00203       geom->setColorArray(col_array.get());
00204     else
00205       geom->setVertexAttribArray(VA_Color, col_array.get());
00206     col_array->resize(geom->vertexArray()->size());
00207     int offs = 0;
00208     for(size_t iseg=0; iseg<segments; ++iseg)
00209     {
00210       for(unsigned j=0; j<silhouette().size(); ++j, ++offs)
00211         col_array->at(offs) = colorPath()[iseg];
00212     }
00213     if (fillBottom())
00214     {
00215       for(unsigned j=0; j<tess_bottom_count; ++j, ++offs)
00216         col_array->at(offs) = colorPath()[0];
00217     }
00218     if (fillTop())
00219     {
00220       for(unsigned j=0; j<tess_top_count; ++j, ++offs)
00221         col_array->at(offs) = colorPath().back();
00222     }
00223   }
00224 
00225   if (!smooth())
00226     geom->convertDrawCallToDrawArrays();
00227 
00228   geom->computeNormals();
00229 
00230   return geom;
00231 }

Visualization Library 2011.09.1160 Reference Documentation
Copyright 2005-2011 Michele Bosi. All rights reserved.
Updated on Thu May 2 2013 13:40:36.
Permission is granted to use this page to write and publish articles regarding Visualization Library.