Visualization Library

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

X:/dropbox/visualizationlibrary/src/vlGraphics/_Extrusions.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/Extrusions.hpp>
00033 #include <vlGraphics/Tessellator.hpp>
00034 #include <vlCore/glsl_math.hpp>
00035 
00036 using namespace vl;
00037 
00038 ref<Geometry> Extrusions::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;
00074   /*if((positionPath()[1]-positionPath()[0]).z() != 0)
00075   {
00076     m = fmat4::getRotation(positionPath()[1]-positionPath()[0], fvec3(0,1,0));
00077   }
00078   else
00079   {*/
00080     m = fmat4::getRotation(fvec3(0,1,0),positionPath()[1]-positionPath()[0]);
00081   //}
00082   
00083   vl::defLogger()->error("positionPath()[1]-positionPath()[0] : " + vl::String::fromDouble((positionPath()[1]-positionPath()[0]).x()) + ";" + 
00084                                                                     vl::String::fromDouble((positionPath()[1]-positionPath()[0]).y()) + ";" + 
00085                                                                     vl::String::fromDouble((positionPath()[1]-positionPath()[0]).z()) + "\n");
00086 
00087   // initialize silhouette on the x/z plane
00088   std::vector<vl::fvec3> projected_sil;
00089   projected_sil.resize(silhouette().size());
00090   for(unsigned i=0; i<silhouette().size(); ++i)
00091   {
00092     projected_sil[i] = m * vl::fvec3(silhouette()[i].x(),0,silhouette()[i].y()) + positionPath()[0];
00093   }
00094 
00095   // initialize plane normals from 1 to n-1 (end points are excluded)
00096   std::vector<fvec3> plane_normals;
00097   plane_normals.resize(positionPath().size());
00098   for(unsigned i=1; i<plane_normals.size()-1; ++i)
00099   {
00100     fvec3 p0 = positionPath()[i-1] - positionPath()[i];
00101     fvec3 p1 = positionPath()[i+1] - positionPath()[i];
00102     p0.normalize();
00103     p1.normalize();
00104     plane_normals[i] = (p1-p0).normalize();
00105   }
00106 
00107   for(unsigned i=1; i<positionPath().size()-1; ++i)
00108   {
00109     for(int j=0; j<(int)silhouette().size(); ++j)
00110     {
00111       fvec3 V = (positionPath()[i] - positionPath()[i-1]).normalize();
00112       const fvec3& P = projected_sil[j];
00113       const fvec3& orig = positionPath()[i];
00114       const fvec3& N = plane_normals [i];
00115       float d = dot(N,orig);
00116       float t = dot(V,N) ? (d-dot(P,N))/dot(V,N) : 0 /*error*/;
00117       // project current projected_sil on next plane along p0->p1 vector
00118       verts.at(j+silhouette().size()*(i-1)) = projected_sil[j] = P + V*t;
00119     }
00120   }
00121 
00122   // rotation
00123   if(!rotationPath().empty())
00124   {
00125     for(unsigned i=1; i<positionPath().size()-1; ++i)
00126     {
00127       fvec3 r = (positionPath()[i+1] - positionPath()[i]).normalize();
00128       fmat4 mat = vl::fmat4::getRotation(rotationPath()[i-1],r);
00129       fvec3 c;
00130       for(int j=0; j<(int)silhouette().size(); ++j)
00131         c += verts.at(j+silhouette().size()*(i-1));
00132       c /= (float)silhouette().size();
00133       for(int j=0; j<(int)silhouette().size(); ++j)
00134         verts.at(j+silhouette().size()*(i-1)) = (mat*(verts.at(j+silhouette().size()*(i-1))-c))+c;
00135     }
00136   }
00137 
00138   // scaling
00139   if(!scalingPath().empty())
00140   {
00141     for(unsigned i=1; i<positionPath().size()-1; ++i)
00142     {
00143       float s = scalingPath()[i-1];
00144       fvec3 c;
00145       for(int j=0; j<(int)silhouette().size(); ++j)
00146         c += verts.at(j+silhouette().size()*(i-1));
00147       c /= (float)silhouette().size();
00148       for(int j=0; j<(int)silhouette().size(); ++j)
00149         verts.at(j+silhouette().size()*(i-1)) = (s*(verts.at(j+silhouette().size()*(i-1))-c))+c;
00150     }
00151   }
00152 
00153   for(unsigned int i = 0; i < silhouettes().size(); ++i)
00154   {
00155     int previousSilhouetteSize = (i == 0) ? 0 : silhouettes().at(i - 1);
00156     int prof_count = silhouetteMode() == SilhouetteClosed ? (int)silhouettes().at(i) : (int)silhouettes().at(i) - 1;
00157     ref<DrawElementsUInt> de = new DrawElementsUInt(PT_QUADS);
00158     geom->drawCalls()->push_back(de.get());
00159     de->indexBuffer()->resize(4 * prof_count * (segments-1));
00160     for(size_t iseg=0; iseg<segments-1; ++iseg)
00161     {
00162       for(int iquad=0; iquad<prof_count; ++iquad)
00163       {
00164         /*if((positionPath()[1]-positionPath()[0]).z() == 0)
00165         {
00166             de->indexBuffer()->at((iquad)*4+iseg*4*prof_count + 0) = (iseg + 0) * (GLuint)silhouette().size() + iquad + previousSilhouetteSize;
00167             de->indexBuffer()->at((iquad)*4+iseg*4*prof_count + 1) = (iseg + 0) * (GLuint)silhouette().size() + (iquad+1)%silhouettes().at(i) + previousSilhouetteSize; // % is used for loop
00168             de->indexBuffer()->at((iquad)*4+iseg*4*prof_count + 2) = (iseg + 1) * (GLuint)silhouette().size() + (iquad+1)%silhouettes().at(i) + previousSilhouetteSize; // % is used for loop
00169             de->indexBuffer()->at((iquad)*4+iseg*4*prof_count + 3) = (iseg + 1) * (GLuint)silhouette().size() + iquad + previousSilhouetteSize;
00170         }
00171         else
00172         {*/
00173             de->indexBuffer()->at((iquad)*4+iseg*4*prof_count + 3) = (iseg + 0) * (GLuint)silhouette().size() + iquad + previousSilhouetteSize;
00174             de->indexBuffer()->at((iquad)*4+iseg*4*prof_count + 2) = (iseg + 0) * (GLuint)silhouette().size() + (iquad+1)%silhouettes().at(i) + previousSilhouetteSize; // % is used for loop
00175             de->indexBuffer()->at((iquad)*4+iseg*4*prof_count + 1) = (iseg + 1) * (GLuint)silhouette().size() + (iquad+1)%silhouettes().at(i) + previousSilhouetteSize; // % is used for loop
00176             de->indexBuffer()->at((iquad)*4+iseg*4*prof_count + 0) = (iseg + 1) * (GLuint)silhouette().size() + iquad + previousSilhouetteSize;
00177         //}
00178       }
00179     }
00180   }
00181 
00182   // bottom/top caps
00183 
00184   size_t tess_bottom_count = 0;
00185   size_t tess_top_count    = 0;
00186 
00187   if(fillBottom())
00188   {
00189     size_t start = verts.size();
00190     Tessellator tessellator;
00191     for(unsigned i=0; i < silhouettes().size(); ++i)
00192         tessellator.contours().push_back(silhouettes().at(i));
00193     for(unsigned i=0; i<silhouette().size(); ++i)
00194       tessellator.contourVerts().push_back((dvec3)verts[i]);
00195     tessellator.setWindingRule(vl::TW_TESS_WINDING_NONZERO);
00196     tessellator.tessellate();
00197     for(unsigned i=0; i<tessellator.tessellatedTris().size(); ++i)
00198       verts.push_back(tessellator.tessellatedTris()[i]);
00199     if (tessellator.tessellatedTris().size())
00200       geom->drawCalls()->push_back( new DrawArrays(PT_TRIANGLES, start, tessellator.tessellatedTris().size()) );
00201     tess_bottom_count = tessellator.tessellatedTris().size();
00202   }
00203   if(fillTop())
00204   {
00205     size_t start = verts.size();
00206     Tessellator tessellator;
00207     for(int i=silhouettes().size() - 1; i >= 0; --i)
00208         tessellator.contours().push_back(silhouettes().at(i));
00209     for(unsigned i=0; i < silhouette().size(); ++i)
00210       tessellator.contourVerts().push_back((dvec3)verts[verts.size()-i-1-tess_bottom_count]);
00211     tessellator.setWindingRule(vl::TW_TESS_WINDING_ODD);
00212     tessellator.tessellate();
00213     for(unsigned i=0; i<tessellator.tessellatedTris().size(); ++i)
00214       verts.push_back(tessellator.tessellatedTris()[i]);
00215     if (tessellator.tessellatedTris().size())
00216       geom->drawCalls()->push_back( new DrawArrays(PT_TRIANGLES, start, tessellator.tessellatedTris().size()) );
00217     tess_top_count = tessellator.tessellatedTris().size();
00218   }
00219 
00220   ref<ArrayFloat3> vert_array = new ArrayFloat3;
00221   if(compatibilityProfile)
00222     geom->setVertexArray( vert_array.get() );
00223   else
00224     geom->setVertexAttribArray(VA_Position, vert_array.get());
00225   vert_array->initFrom(verts);
00226 
00227   if (!colorPath().empty())
00228   {
00229     ref<ArrayFloat4> col_array = new ArrayFloat4;
00230     if(compatibilityProfile)
00231       geom->setColorArray(col_array.get());
00232     else
00233       geom->setVertexAttribArray(VA_Color, col_array.get());
00234     col_array->resize(geom->vertexArray()->size());
00235     int offs = 0;
00236     for(size_t iseg=0; iseg<segments; ++iseg)
00237     {
00238       for(unsigned j=0; j<silhouette().size(); ++j, ++offs)
00239         col_array->at(offs) = colorPath()[iseg];
00240     }
00241     if (fillBottom())
00242     {
00243       for(unsigned j=0; j<tess_bottom_count; ++j, ++offs)
00244         col_array->at(offs) = colorPath()[0];
00245     }
00246     if (fillTop())
00247     {
00248       for(unsigned j=0; j<tess_top_count; ++j, ++offs)
00249         col_array->at(offs) = colorPath().back();
00250     }
00251   }
00252 
00253   if (!smooth())
00254     geom->convertDrawCallToDrawArrays();
00255 
00256   geom->computeNormals();
00257 
00258   return geom;
00259 }

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