# Visualization Library

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

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

- Main Page
- Related Pages
- Namespaces
- Classes
- Files

- File List
- File Members

# D:/VL/BuildSystem/VL_DISTRO/Visualization_Library_SDK/src/vlGraphics/Geometry.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/Geometry.hpp>
    00033 #include <vlGraphics/OpenGLContext.hpp>
    00034 #include <vlGraphics/DoubleVertexRemover.hpp>
    00035 #include <vlGraphics/MultiDrawElements.hpp>
    00036 #include <vlGraphics/DrawRangeElements.hpp>
    00037 #include <cmath>
    00038 #include <algorithm>
    00039
    00040 using namespace vl;
    00041
    00042 //-----------------------------------------------------------------------------
    00043 // Geometry
    00044 //-----------------------------------------------------------------------------
    00045 Geometry::Geometry()
    00046 {
    00047   VL_DEBUG_SET_OBJECT_NAME()
    00048   mVertexAttribArrays.setAutomaticDelete(false);
    00049   mTexCoordArrays.setAutomaticDelete(false);
    00050   mDrawCalls.setAutomaticDelete(false);
    00051 }
    00052 //-----------------------------------------------------------------------------
    00053 Geometry::~Geometry()
    00054 {
    00055 }
    00056 //-----------------------------------------------------------------------------
    00057 void Geometry::computeBounds_Implementation()
    00058 {
    00059   const ArrayAbstract* coords = vertexArray() ? vertexArray() : vertexAttribArray(vl::VA_Position) ? vertexAttribArray(vl::VA_Position)->data() : NULL;
    00060
    00061   if (coords == NULL)
    00062   {
    00063     Log::debug("Geometry::computeBounds_Implementation() failed! No vertex buffer present!\n");
    00064     return;
    00065   }
    00066
    00067   if (coords->size() == 0)
    00068   {
    00069     Log::debug("Geometry::computeBounds_Implementation() failed! No vertices present in the local buffer! Did you forget to call setBoundingBox() and setBoundingSphere()?\n");
    00070     return;
    00071   }
    00072
    00073   AABB aabb;
    00074   for(int i=0; i<drawCalls()->size(); ++i)
    00075   {
    00076     for(IndexIterator iit = drawCalls()->at(i)->indexIterator(); iit.hasNext(); iit.next())
    00077     {
    00078       aabb += coords->getAsVec3( iit.index() );
    00079     }
    00080   }
    00081
    00082   real radius = 0, r = 0;
    00083   vec3 center = aabb.center();
    00084   for(int i=0; i<drawCalls()->size(); ++i)
    00085   {
    00086     for(IndexIterator iit = drawCalls()->at(i)->indexIterator(); iit.hasNext(); iit.next())
    00087     {
    00088       r = (coords->getAsVec3(iit.index()) - center).lengthSquared();
    00089       if (r > radius)
    00090         radius = r;
    00091     }
    00092   }
    00093
    00094   setBoundingBox( aabb );
    00095   setBoundingSphere( Sphere(center, radius) );
    00096 }
    00097 //-----------------------------------------------------------------------------
    00098 ref<Geometry> Geometry::deepCopy() const
    00099 {
    00100   ref<Geometry> geom = new Geometry;
    00101   geom->deepCopyFrom(*this);
    00102   return geom;
    00103 }
    00104 //-----------------------------------------------------------------------------
    00105 Geometry& Geometry::deepCopyFrom(const Geometry& other)
    00106 {
    00107   // copy the base class Renderable
    00108   super::operator=(other);
    00109
    00110   // copy Geometry
    00111   mVertexArray         = other.mVertexArray         ? other.mVertexArray->clone().get()         : NULL;
    00112   mNormalArray         = other.mNormalArray         ? other.mNormalArray->clone().get()         : NULL;
    00113   mColorArray          = other.mColorArray          ? other.mColorArray->clone().get()          : NULL;
    00114   mSecondaryColorArray = other.mSecondaryColorArray ? other.mSecondaryColorArray->clone().get() : NULL;
    00115   mFogCoordArray       = other.mFogCoordArray       ? other.mFogCoordArray->clone().get()       : NULL;
    00116
    00117   mTexCoordArrays.resize( other.mTexCoordArrays.size() );
    00118   for(int i=0; i<mTexCoordArrays.size(); ++i)
    00119     mTexCoordArrays[i] = new TextureArray(other.mTexCoordArrays[i]->mTextureSampler, other.mTexCoordArrays[i]->mTexCoordArray ? other.mTexCoordArrays[i]->mTexCoordArray->clone().get() : NULL);
    00120
    00121   // custom arrays
    00122   mVertexAttribArrays.resize( other.mVertexAttribArrays.size() );
    00123   for(int i=0; i<mVertexAttribArrays.size(); ++i)
    00124   {
    00125     mVertexAttribArrays[i] = new VertexAttribInfo;
    00126     mVertexAttribArrays[i]->setNormalize( other.mVertexAttribArrays[i]->normalize() );
    00127     mVertexAttribArrays[i]->setInterpretation( other.mVertexAttribArrays[i]->interpretation() );
    00128     mVertexAttribArrays[i]->setAttribLocation( other.mVertexAttribArrays[i]->attribLocation() );
    00129     mVertexAttribArrays[i]->setData( other.mVertexAttribArrays[i]->data() ? other.mVertexAttribArrays[i]->data()->clone().get() : NULL );
    00130   }
    00131
    00132   // primitives
    00133   mDrawCalls.clear();
    00134   for(int i=0; i<other.mDrawCalls.size(); ++i)
    00135     mDrawCalls.push_back( other.mDrawCalls[i]->clone().get() );
    00136
    00137   return *this;
    00138 }
    00139 //-----------------------------------------------------------------------------
    00140 ref<Geometry> Geometry::shallowCopy() const
    00141 {
    00142   ref<Geometry> geom = new Geometry;
    00143   geom->shallowCopyFrom(*this);
    00144   return geom;
    00145 }
    00146 //-----------------------------------------------------------------------------
    00147 Geometry& Geometry::shallowCopyFrom(const Geometry& other)
    00148 {
    00149   // copy the base class Renderable
    00150   super::operator=(other);
    00151
    00152   // copy Geometry attributes
    00153   mVertexArray = other.mVertexArray;
    00154   mNormalArray = other.mNormalArray;
    00155   mColorArray = other.mColorArray;
    00156   mSecondaryColorArray = other.mSecondaryColorArray;
    00157   mFogCoordArray = other.mFogCoordArray;
    00158   mTexCoordArrays = other.mTexCoordArrays;
    00159   mVertexAttribArrays = other.mVertexAttribArrays;
    00160   mDrawCalls = other.mDrawCalls;
    00161
    00162   return *this;
    00163 }
    00164 //-----------------------------------------------------------------------------
    00165 void Geometry::setVertexArray(ArrayAbstract* data)
    00166 {
    00167   // if one of this checks fail read the OpenGL Programmers Guide or the Reference Manual
    00168   // to see what "size" and "type" are allowed for glVertexPointer
    00169   VL_CHECK( !data || (data->glSize() >=2 && data->glSize()<=4) )
    00170
    00171   mVertexArray = data;
    00172 }
    00173 //-----------------------------------------------------------------------------
    00174 void Geometry::setNormalArray(ArrayAbstract* data)
    00175 {
    00176   // if one of this checks fail read the OpenGL Programmers Guide or the Reference Manual
    00177   // to see what "size" and "type" are allowed for glNormalPointer
    00178   VL_CHECK( !data || data->glSize() == 3 )
    00179   VL_CHECK( !data || (data->glType() == GL_BYTE||
    00180                       data->glType() == GL_SHORT ||
    00181                       data->glType() == GL_INT ||
    00182                       data->glType() == GL_FLOAT ||
    00183                       data->glType() == GL_DOUBLE) );
    00184
    00185   mNormalArray = data;
    00186 }
    00187 //-----------------------------------------------------------------------------
    00188 void Geometry::setColorArray(ArrayAbstract* data)
    00189 {
    00190   // if one of this checks fail read the OpenGL Programmers Guide or the Reference Manual
    00191   // to see what "size" and "type" are allowed for glColorPointer
    00192   VL_CHECK( !data || (data->glSize() >=3 && data->glSize()<=4) )
    00193   VL_CHECK( !data || (data->glType() == GL_BYTE ||
    00194                       data->glType() == GL_SHORT ||
    00195                       data->glType() == GL_INT ||
    00196                       data->glType() == GL_UNSIGNED_BYTE ||
    00197                       data->glType() == GL_UNSIGNED_SHORT ||
    00198                       data->glType() == GL_UNSIGNED_INT ||
    00199                       data->glType() == GL_FLOAT ||
    00200                       data->glType() == GL_DOUBLE) );
    00201
    00202   mColorArray = data;
    00203 }
    00204 //-----------------------------------------------------------------------------
    00205 void Geometry::setSecondaryColorArray(ArrayAbstract* data)
    00206 {
    00207   // if one of this checks fail read the OpenGL Programmers Guide or the Reference Manual
    00208   // to see what "size" and "type" are allowed for glSecondaryColorPointer
    00209   VL_CHECK( !data || (data->glSize() >=3 && data->glSize()<=4) )
    00210   VL_CHECK( !data || (data->glType() == GL_BYTE ||
    00211                       data->glType() == GL_SHORT ||
    00212                       data->glType() == GL_INT ||
    00213                       data->glType() == GL_UNSIGNED_BYTE ||
    00214                       data->glType() == GL_UNSIGNED_SHORT ||
    00215                       data->glType() == GL_UNSIGNED_INT ||
    00216                       data->glType() == GL_FLOAT ||
    00217                       data->glType() == GL_DOUBLE) );
    00218
    00219   mSecondaryColorArray = data;
    00220 }
    00221 //-----------------------------------------------------------------------------
    00222 void Geometry::setFogCoordArray(ArrayAbstract* data)
    00223 {
    00224   // if one of this checks fail read the OpenGL Programmers Guide or the Reference Manual
    00225   // to see what "size" and "type" are allowed for glFogCoordPointer
    00226   VL_CHECK( !data || (data->glSize() == 1) )
    00227   VL_CHECK( !data || (data->glType() == GL_FLOAT || data->glType() == GL_DOUBLE) );
    00228
    00229   mFogCoordArray = data;
    00230 }
    00231 //-----------------------------------------------------------------------------
    00232 void Geometry::setTexCoordArray(int tex_unit, ArrayAbstract* data)
    00233 {
    00234   // if one of this checks fail read the OpenGL Programmers Guide or the Reference Manual
    00235   // to see what "size" and "type" are allowed for glTexCoordPointer
    00236   VL_CHECK( !data || (data->glSize() == 1 || data->glSize() == 2 || data->glSize() == 3 || data->glSize() == 4) )
    00237   VL_CHECK( !data || (data->glType() == GL_FLOAT  ||
    00238                       data->glType() == GL_DOUBLE ||
    00239                       data->glType() == GL_SHORT  ||
    00240                       data->glType() == GL_INT) );
    00241
    00242   VL_CHECK(tex_unit<VL_MAX_TEXTURE_UNITS);
    00243
    00244   for(int i=0; i<mTexCoordArrays.size(); ++i)
    00245   {
    00246     if (mTexCoordArrays.at(i)->mTextureSampler == tex_unit)
    00247     {
    00248       if (data)
    00249         mTexCoordArrays.at(i)->mTexCoordArray = data;
    00250       else
    00251         mTexCoordArrays.erase(i,1); // removes if NULL
    00252       return;
    00253     }
    00254   }
    00255   if (data)
    00256     mTexCoordArrays.push_back(new TextureArray(tex_unit,data));
    00257 }
    00258 //-----------------------------------------------------------------------------
    00259 void Geometry::clearArrays(bool clear_draw_calls)
    00260 {
    00261   mVertexArray = NULL;
    00262   mNormalArray = NULL;
    00263   mColorArray = NULL;
    00264   mSecondaryColorArray = NULL;
    00265   mFogCoordArray = NULL;
    00266   mTexCoordArrays.clear();
    00267   mVertexAttribArrays.clear();
    00268   if (clear_draw_calls)
    00269     mDrawCalls.clear();
    00270 }
    00271 //-----------------------------------------------------------------------------
    00272 bool Geometry::flipNormals()
    00273 {
    00274   ArrayAbstract* normarr = normalArray() ? normalArray() : vertexAttribArray(vl::VA_Normal) ? vertexAttribArray(vl::VA_Normal)->data() : NULL;
    00275
    00276   if (normarr)
    00277   {
    00278     ArrayFloat3* norm3f = normarr->as<ArrayFloat3>();
    00279     if (norm3f)
    00280     {
    00281       for(u32 i=0; i<norm3f->size(); ++i)
    00282       {
    00283         norm3f->at(i) = -norm3f->at(i);
    00284       }
    00285       return true;
    00286     }
    00287   }
    00288   return false;
    00289 }
    00290 //-----------------------------------------------------------------------------
    00291 void Geometry::convertToVertexAttribs()
    00292 {
    00293   std::map<int, ref<ArrayAbstract> > attrib_map;
    00294
    00295   if (vertexArray())
    00296   {
    00297     attrib_map[VA_Position] = vertexArray();
    00298     setVertexArray(NULL);
    00299   }
    00300
    00301   if (normalArray())
    00302   {
    00303     attrib_map[VA_Normal] = normalArray();
    00304     setNormalArray(NULL);
    00305   }
    00306
    00307   if (colorArray())
    00308   {
    00309     attrib_map[VA_Color] = colorArray();
    00310     setColorArray(NULL);
    00311   }
    00312
    00313   // Texture coordinates starting from VA_TexCoord0
    00314   for(int i=0; i<mTexCoordArrays.size(); i++)
    00315   {
    00316     attrib_map[VA_TexCoord0+i] = mTexCoordArrays[i]->mTexCoordArray;
    00317   }
    00318   mTexCoordArrays.clear();
    00319
    00320   // Secondary color and fog are packed right after the texture coordinates
    00321   int index = VA_TexCoord0 + mTexCoordArrays.size();
    00322   if (secondaryColorArray())
    00323   {
    00324     attrib_map[index++] = secondaryColorArray();
    00325     setSecondaryColorArray(NULL);
    00326   }
    00327
    00328   if (fogCoordArray())
    00329   {
    00330     attrib_map[index++] = fogCoordArray();
    00331     setFogCoordArray(NULL);
    00332   }
    00333
    00334   // copy over the collected attributes
    00335   // note: we override eventual existing vertex attributes if they are in busy positions, the other are left where they are
    00336   for(std::map<int, ref<ArrayAbstract> >::iterator it=attrib_map.begin(); it != attrib_map.end(); ++it)
    00337   {
    00338     if (vertexAttribArray(it->first) != NULL)
    00339       Log::warning( Say("Geometry::convertToVertexAttribs(): vertex attrib index #%n is already in use, it will be overwritten.\n") << it->first );
    00340     setVertexAttribArray(it->first, it->second.get());
    00341   }
    00342
    00343 }
    00344 //-----------------------------------------------------------------------------
    00345 void Geometry::computeNormals(bool verbose)
    00346 {
    00347   // Retrieve vertex position array
    00348   ArrayAbstract* posarr = vertexArray() ? vertexArray() : vertexAttribArray(vl::VA_Position) ? vertexAttribArray(vl::VA_Position)->data() : NULL;
    00349   if (!posarr || posarr->size() == 0)
    00350   {
    00351     Log::warning("Geometry::computeNormals() failed: no vertices found!\n");
    00352     return;
    00353   }
    00354
    00355   ref<ArrayFloat3> norm3f = new ArrayFloat3;
    00356   norm3f->resize( posarr->size() );
    00357
    00358   // Install the normal array
    00359   if (vertexArray())
    00360     setNormalArray( norm3f.get() );
    00361   else
    00362     setVertexAttribArray(VA_Normal, norm3f.get());
    00363
    00364   // zero the normals
    00365   for(u32 i=0; i<norm3f->size(); ++i)
    00366     (*norm3f)[i] = 0;
    00367
    00368   // iterate all draw calls
    00369   for(int prim=0; prim<(int)drawCalls()->size(); prim++)
    00370   {
    00371     // iterate all triangles, if present
    00372     for(TriangleIterator trit = mDrawCalls[prim]->triangleIterator(); trit.hasNext(); trit.next())
    00373     {
    00374       u32 a = trit.a();
    00375       u32 b = trit.b();
    00376       u32 c = trit.c();
    00377
    00378       if (verbose)
    00379       if (a == b || b == c || c == a)
    00380       {
    00381         Log::warning( Say("Geometry::computeNormals(): skipping degenerate triangle %n %n %n\n") << a << b << c );
    00382         continue;
    00383       }
    00384
    00385       VL_CHECK( a < posarr->size() )
    00386       VL_CHECK( b < posarr->size() )
    00387       VL_CHECK( c < posarr->size() )
    00388
    00389       vec3 n, v0, v1, v2;
    00390
    00391       v0 = posarr->getAsVec3(a);
    00392       v1 = posarr->getAsVec3(b);
    00393       v2 = posarr->getAsVec3(c);
    00394
    00395       if (verbose)
    00396       if (v0 == v1 || v1 == v2 || v2 == v0)
    00397       {
    00398         Log::warning("Geometry::computeNormals(): skipping degenerate triangle (same vertex coodinate).\n");
    00399         continue;
    00400       }
    00401
    00402       v1 -= v0;
    00403       v2 -= v0;
    00404
    00405       n = cross(v1, v2);
    00406       n.normalize();
    00407       if (verbose)
    00408       if ( fabs(1.0f - n.length()) > 0.1f )
    00409       {
    00410         Log::warning("Geometry::computeNormals(): skipping degenerate triangle (normalization failed).\n");
    00411         continue;
    00412       }
    00413
    00414       (*norm3f)[a] += (fvec3)n;
    00415       (*norm3f)[b] += (fvec3)n;
    00416       (*norm3f)[c] += (fvec3)n;
    00417     }
    00418   }
    00419
    00420   // normalize the normals
    00421   for(int i=0; i<(int)norm3f->size(); ++i)
    00422     (*norm3f)[i].normalize();
    00423 }
    00424 //-----------------------------------------------------------------------------
    00425 void Geometry::deleteBufferObject()
    00426 {
    00427   if (!Has_BufferObject)
    00428     return;
    00429
    00430   for(int i=0; i<(int)drawCalls()->size(); ++i)
    00431     drawCalls()->at(i)->deleteBufferObject();
    00432
    00433   if (mVertexArray)
    00434     mVertexArray->bufferObject()->deleteBufferObject();
    00435
    00436   if (mNormalArray)
    00437     mNormalArray->bufferObject()->deleteBufferObject();
    00438
    00439   if (mColorArray)
    00440     mColorArray->bufferObject()->deleteBufferObject();
    00441
    00442   if (mSecondaryColorArray)
    00443     mSecondaryColorArray->bufferObject()->deleteBufferObject();
    00444
    00445   if (mFogCoordArray)
    00446     mFogCoordArray->bufferObject()->deleteBufferObject();
    00447
    00448   for (int i=0; i<mTexCoordArrays.size(); ++i)
    00449     mTexCoordArrays[i]->mTexCoordArray->bufferObject()->deleteBufferObject();
    00450
    00451   for(int i=0; i<vertexAttribArrays()->size(); ++i)
    00452     if ( vertexAttribArrays()->at(i)->data() )
    00453       vertexAttribArrays()->at(i)->data()->bufferObject()->deleteBufferObject();
    00454 }
    00455 //-----------------------------------------------------------------------------
    00456 void Geometry::updateDirtyBufferObject(EBufferObjectUpdateMode mode)
    00457 {
    00458   if (!Has_BufferObject)
    00459     return;
    00460
    00461   bool force_update = (mode & BUF_ForceUpdate) != 0;
    00462
    00463   if ( mVertexArray && (mVertexArray->isBufferObjectDirty() || force_update) )
    00464     mVertexArray->updateBufferObject(mode);
    00465
    00466   if ( mNormalArray && (mNormalArray->isBufferObjectDirty() || force_update) )
    00467     mNormalArray->updateBufferObject(mode);
    00468
    00469   if ( mColorArray && (mColorArray->isBufferObjectDirty() || force_update) )
    00470     mColorArray->updateBufferObject(mode);
    00471
    00472   if ( mSecondaryColorArray && (mSecondaryColorArray->isBufferObjectDirty() || force_update) )
    00473     mSecondaryColorArray->updateBufferObject(mode);
    00474
    00475   if ( mFogCoordArray && (mFogCoordArray->isBufferObjectDirty() || force_update) )
    00476     mFogCoordArray->updateBufferObject(mode);
    00477
    00478   for(int i=0; i<mTexCoordArrays.size(); ++i)
    00479   {
    00480     if ( mTexCoordArrays[i]->mTexCoordArray->isBufferObjectDirty() || force_update )
    00481       mTexCoordArrays[i]->mTexCoordArray->updateBufferObject(mode);
    00482   }
    00483
    00484   for(int i=0; i<vertexAttribArrays()->size(); ++i)
    00485     if ( vertexAttribArrays()->at(i)->data() && (vertexAttribArrays()->at(i)->data()->isBufferObjectDirty() || force_update) )
    00486       vertexAttribArrays()->at(i)->data()->updateBufferObject(mode);
    00487
    00488   for(int i=0; i<drawCalls()->size(); ++i)
    00489     drawCalls()->at(i)->updateDirtyBufferObject(mode);
    00490 }
    00491 //-----------------------------------------------------------------------------
    00492 void Geometry::render_Implementation(const Actor*, const Shader*, const Camera*, OpenGLContext* gl_context) const
    00493 {
    00494   VL_CHECK_OGL()
    00495
    00496   // bind Vertex Attrib Set
    00497
    00498   bool vbo_on = Has_BufferObject && isBufferObjectEnabled() && !isDisplayListEnabled();
    00499   gl_context->bindVAS(this, vbo_on, false);
    00500
    00501   // actual draw
    00502
    00503   for(int i=0; i<(int)drawCalls()->size(); i++)
    00504     if (drawCalls()->at(i)->isEnabled())
    00505       drawCalls()->at(i)->render( vbo_on );
    00506
    00507   VL_CHECK_OGL()
    00508 }
    00509 //-----------------------------------------------------------------------------
    00510 void Geometry::transform(const mat4& m, bool normalize)
    00511 {
    00512   ArrayAbstract* posarr = vertexArray() ? vertexArray() : vertexAttribArray(vl::VA_Position) ? vertexAttribArray(vl::VA_Position)->data() : NULL;
    00513   if (posarr)
    00514     posarr->transform(m);
    00515
    00516   ArrayAbstract* normarr = normalArray() ? normalArray() : vertexAttribArray(vl::VA_Normal) ? vertexAttribArray(vl::VA_Normal)->data() : NULL;
    00517   if (normarr)
    00518   {
    00519     mat4 nmat = m.as3x3().invert().transpose();
    00520     normarr->transform(nmat);
    00521     if (normalize)
    00522       normarr->normalize();
    00523   }
    00524 }
    00525 //-----------------------------------------------------------------------------
    00526 void Geometry::setVertexAttribArray(const VertexAttribInfo& info)
    00527 {
    00528   for(int i=0; i<vertexAttribArrays()->size(); ++i)
    00529   {
    00530     VL_CHECK(vertexAttribArrays()->at(i))
    00531     if (vertexAttribArrays()->at(i)->attribLocation() == info.attribLocation())
    00532     {
    00533       *vertexAttribArrays()->at(i) = info;
    00534       return;
    00535     }
    00536   }
    00537   mVertexAttribArrays.push_back( new VertexAttribInfo(info) );
    00538 }
    00539 //-----------------------------------------------------------------------------
    00540 const VertexAttribInfo* Geometry::vertexAttribArray(unsigned int attrib_location) const
    00541 {
    00542   for(int i=0; i<vertexAttribArrays()->size(); ++i)
    00543     if (vertexAttribArrays()->at(i)->attribLocation() == attrib_location)
    00544       return vertexAttribArrays()->at(i);
    00545   return NULL;
    00546 }
    00547 //-----------------------------------------------------------------------------
    00548 VertexAttribInfo* Geometry::vertexAttribArray(unsigned int attrib_location)
    00549 {
    00550   for(int i=0; i<vertexAttribArrays()->size(); ++i)
    00551     if (vertexAttribArrays()->at(i)->attribLocation() == attrib_location)
    00552       return vertexAttribArrays()->at(i);
    00553   return NULL;
    00554 }
    00555 //-----------------------------------------------------------------------------
    00556 DrawCall* Geometry::mergeTriangleStrips()
    00557 {
    00558   ArrayAbstract* posarr = vertexArray() ? vertexArray() : vertexAttribArray(vl::VA_Position) ? vertexAttribArray(vl::VA_Position)->data() : NULL;
    00559
    00560   if (!posarr)
    00561     return NULL;
    00562
    00563   std::vector< ref<DrawElementsBase> > de_vector;
    00564   std::vector<u32> indices;
    00565
    00566   // collect DrawElementsUInt
    00567   for(int i=drawCalls()->size(); i--; )
    00568   {
    00569     ref<DrawElementsBase> deb = cast<DrawElementsBase>( drawCalls()->at(i) );
    00570     if (deb && deb->primitiveType() == PT_TRIANGLE_STRIP)
    00571     {
    00572       // preserve order
    00573       de_vector.push_back( deb );
    00574       drawCalls()->eraseAt(i);
    00575     }
    00576   }
    00577   // preseve rendering order
    00578   std::reverse(de_vector.begin(), de_vector.end());
    00579
    00580   // generate new strip
    00581   indices.reserve( posarr->size()*2 );
    00582   for(u32 i=0; i<de_vector.size(); ++i)
    00583   {
    00584     u32 index_count = 0;
    00585     for(IndexIterator it=de_vector[i]->indexIterator(); it.hasNext(); it.next(), ++index_count)
    00586       indices.push_back(it.index());
    00587
    00588     if (index_count == 0)
    00589       continue;
    00590
    00591     // odd -> even
    00592     if ( index_count % 2 )
    00593       indices.push_back( indices.back() );
    00594
    00595     // concatenate next strip inserting degenerate triangles
    00596     if ( i != de_vector.size()-1 )
    00597     {
    00598       // grab the first two indices of the next draw call
    00599       IndexIterator it = de_vector[i+1]->indexIterator();
    00600       int A = it.index();
    00601       it.next();
    00602       int B = it.index();
    00603
    00604       if (A == -1 || B == -1)
    00605         continue;
    00606
    00607       indices.push_back( indices.back() );
    00608       indices.push_back(A);
    00609       indices.push_back(A);
    00610       indices.push_back(B);
    00611     }
    00612   }
    00613
    00614   if (indices.size())
    00615   {
    00616     ref<DrawElementsUInt> draw_elems = new DrawElementsUInt(PT_TRIANGLE_STRIP);
    00617     draw_elems->indexBuffer()->resize(indices.size());
    00618     memcpy(draw_elems->indexBuffer()->ptr(), &indices[0], sizeof(indices[0])*indices.size());
    00619     drawCalls()->push_back(draw_elems.get());
    00620     return draw_elems.get();
    00621   }
    00622   else
    00623     return NULL;
    00624 }
    00625 //-----------------------------------------------------------------------------
    00626 void Geometry::mergeDrawCallsWithPrimitiveRestart(EPrimitiveType primitive_type)
    00627 {
    00628   u32 total_index_count = 0;
    00629   std::vector< ref<DrawCall> > mergendo_calls;
    00630   for( u32 i=drawCalls()->size(); i--; )
    00631   {
    00632     if (drawCalls()->at(i)->primitiveType() == primitive_type)
    00633     {
    00634       int index_count = drawCalls()->at(i)->countIndices();
    00635       VL_CHECK(index_count >= 0);
    00636       total_index_count += index_count;
    00637       // insert at the head to preserve the primitive rendering order
    00638       mergendo_calls.push_back( drawCalls()->at(i) );
    00639       drawCalls()->eraseAt(i);
    00640     }
    00641   }
    00642   // preseve rendering order
    00643   std::reverse(mergendo_calls.begin(), mergendo_calls.end());
    00644
    00645   Log::debug( Say("%n draw calls will be merged using primitive restart.\n") << mergendo_calls.size() );
    00646
    00647   if (mergendo_calls.empty())
    00648     return;
    00649
    00650 #ifndef NDEBUG
    00651   ArrayAbstract* posarr = vertexArray() ? vertexArray() : vertexAttribArray(vl::VA_Position) ? vertexAttribArray(vl::VA_Position)->data() : NULL;
    00652 #endif
    00653
    00654   ref<DrawElementsUInt> de_prim_restart = new DrawElementsUInt(primitive_type);
    00655   // make space for all the indices plus the primitive restart markers.
    00656   de_prim_restart->indexBuffer()->resize(total_index_count + mergendo_calls.size()-1);
    00657   GLuint* index = de_prim_restart->indexBuffer()->begin();
    00658   // merge draw calls using primitive restart!
    00659   for( u32 i=0; i<mergendo_calls.size(); ++i )
    00660   {
    00661     for( IndexIterator it = mergendo_calls[i]->indexIterator(); it.hasNext(); it.next(), ++index )
    00662     {
    00663       *index = it.index();
    00664       VL_CHECK(*index < posarr->size());
    00665     }
    00666     if ( i != mergendo_calls.size() -1 )
    00667     {
    00668       *index = DrawElementsUInt::primitive_restart_index;
    00669       ++index;
    00670     }
    00671   }
    00672   VL_CHECK( index == de_prim_restart->indexBuffer()->end() )
    00673
    00674   // enable primitive restart!
    00675   de_prim_restart->setPrimitiveRestartEnabled(true);
    00676
    00677   drawCalls()->push_back( de_prim_restart.get() );
    00678 }
    00679 //-----------------------------------------------------------------------------
    00680 void Geometry::mergeDrawCallsWithMultiDrawElements(EPrimitiveType primitive_type)
    00681 {
    00682   u32 total_index_count = 0;
    00683   std::vector< ref<DrawCall> > mergendo_calls;
    00684   std::vector<GLsizei> count_vector;
    00685   for( u32 i=drawCalls()->size(); i--; )
    00686   {
    00687     if (drawCalls()->at(i)->primitiveType() == primitive_type)
    00688     {
    00689       int index_count = drawCalls()->at(i)->countIndices();
    00690       VL_CHECK(index_count >= 0);
    00691       total_index_count += index_count;
    00692       count_vector.push_back( index_count );
    00693       mergendo_calls.push_back( drawCalls()->at(i) );
    00694       drawCalls()->eraseAt(i);
    00695     }
    00696   }
    00697   // preseve rendering order
    00698   std::reverse(mergendo_calls.begin(), mergendo_calls.end());
    00699   std::reverse(count_vector.begin(), count_vector.end());
    00700
    00701   Log::debug( Say("%n draw calls will be merged using MultiDrawElements.\n") << mergendo_calls.size() );
    00702
    00703   if (mergendo_calls.empty())
    00704     return;
    00705
    00706 #ifndef NDEBUG
    00707   ArrayAbstract* posarr = vertexArray() ? vertexArray() : vertexAttribArray(vl::VA_Position) ? vertexAttribArray(vl::VA_Position)->data() : NULL;
    00708 #endif
    00709
    00710   ref<MultiDrawElementsUInt> de_multi = new MultiDrawElementsUInt(primitive_type);
    00711   // make space for all the indices plus the primitive restart markers.
    00712   de_multi->indexBuffer()->resize(total_index_count);
    00713   GLuint* index = de_multi->indexBuffer()->begin();
    00714   // merge draw calls using primitive restart!
    00715   for( u32 i=0; i<mergendo_calls.size(); ++i )
    00716   {
    00717     for( IndexIterator it = mergendo_calls[i]->indexIterator(); it.hasNext(); it.next(), ++index )
    00718     {
    00719       *index = it.index();
    00720       VL_CHECK(*index < posarr->size());
    00721     }
    00722   }
    00723   VL_CHECK( index == de_multi->indexBuffer()->end() )
    00724
    00725   // Specify primitive boundaries. This must be done last!
    00726   de_multi->setCountVector( count_vector );
    00727
    00728   drawCalls()->push_back( de_multi.get() );
    00729 }
    00730 //-----------------------------------------------------------------------------
    00731 void Geometry::mergeDrawCallsWithTriangles(EPrimitiveType primitive_type)
    00732 {
    00733   u32 triangle_count = 0;
    00734   std::vector< ref<DrawCall> > mergendo_calls;
    00735   for( u32 i=drawCalls()->size(); i--; )
    00736   {
    00737     const DrawCall& dc = *drawCalls()->at(i);
    00738
    00739     // ignore primitives that cannot be triangulated
    00740     switch(dc.primitiveType())
    00741     {
    00742     case PT_TRIANGLES:
    00743     case PT_TRIANGLE_STRIP:
    00744     case PT_TRIANGLE_FAN:
    00745     case PT_QUADS:
    00746     case PT_QUAD_STRIP:
    00747     case PT_POLYGON:
    00748       break;
    00749     default:
    00750       continue;
    00751     }
    00752
    00753     if (primitive_type == PT_UNKNOWN || dc.primitiveType() == primitive_type || dc.primitiveType() == PT_TRIANGLES)
    00754     {
    00755       triangle_count += dc.countTriangles();
    00756       // insert at the head to preserve the primitive rendering order
    00757       mergendo_calls.insert( mergendo_calls.begin(), drawCalls()->at(i) );
    00758       drawCalls()->eraseAt(i);
    00759     }
    00760   }
    00761   // preseve rendering order
    00762   std::reverse(mergendo_calls.begin(), mergendo_calls.end());
    00763
    00764   if (mergendo_calls.empty())
    00765     return;
    00766
    00767   // if there was one single PT_TRIANGLES draw calls then we are done.
    00768   if ( mergendo_calls.size() == 1 && mergendo_calls[0]->primitiveType() == PT_TRIANGLES )
    00769   {
    00770     drawCalls()->push_back( mergendo_calls[0].get() );
    00771     return;
    00772   }
    00773
    00774 #ifndef NDEBUG
    00775   ArrayAbstract* posarr = vertexArray() ? vertexArray() : vertexAttribArray(vl::VA_Position) ? vertexAttribArray(vl::VA_Position)->data() : NULL;
    00776 #endif
    00777
    00778   ref<DrawElementsUInt> de = new DrawElementsUInt;
    00779   ArrayUInt1& index_buffer = *de->indexBuffer();
    00780   index_buffer.resize( triangle_count * 3 );
    00781   u32 idx = 0;
    00782   for(u32 i=0; i<mergendo_calls.size(); ++i)
    00783   {
    00784     for(TriangleIterator it = mergendo_calls[i]->triangleIterator(); it.hasNext(); it.next(), idx+=3)
    00785     {
    00786       VL_CHECK( idx+2 < index_buffer.size() );
    00787
    00788       index_buffer[idx+0] = it.a();
    00789       index_buffer[idx+1] = it.b();
    00790       index_buffer[idx+2] = it.c();
    00791
    00792       // some sanity checks since we are here...
    00793       VL_CHECK( it.a() < (int)posarr->size() && it.b() < (int)posarr->size() && it.c() < (int)posarr->size() );
    00794       VL_CHECK( it.a() >= 0 && it.b() >= 0 && it.c() >= 0 );
    00795     }
    00796   }
    00797   VL_CHECK( idx == index_buffer.size() );
    00798   drawCalls()->push_back(de.get());
    00799 }
    00800 //-----------------------------------------------------------------------------
    00801 void Geometry::fixTriangleWinding()
    00802 {
    00803   ArrayAbstract* posarr = vertexArray() ? vertexArray() : vertexAttribArray(vl::VA_Position) ? vertexAttribArray(vl::VA_Position)->data() : NULL;
    00804
    00805   ArrayAbstract* normarr = normalArray() ? normalArray() : vertexAttribArray(vl::VA_Normal) ? vertexAttribArray(vl::VA_Normal)->data() : NULL;
    00806
    00807   // fixing the triangle winding requires normals
    00808   if ( normarr == NULL || posarr == NULL )
    00809     return;
    00810
    00811   u32 triangle_count = 0;
    00812   std::vector< ref<DrawCall> > mergendo_calls;
    00813   for( u32 i=drawCalls()->size(); i--; )
    00814   {
    00815     const DrawCall& dc = *drawCalls()->at(i);
    00816
    00817     // ignore primitives that cannot be triangulated
    00818     switch(dc.primitiveType())
    00819     {
    00820     case PT_TRIANGLES:
    00821     case PT_TRIANGLE_STRIP:
    00822     case PT_TRIANGLE_FAN:
    00823     case PT_QUADS:
    00824     case PT_QUAD_STRIP:
    00825     case PT_POLYGON:
    00826       break;
    00827     default:
    00828       continue;
    00829     }
    00830
    00831     triangle_count += dc.countTriangles();
    00832     // insert at the head to preserve the primitive rendering order
    00833     mergendo_calls.insert( mergendo_calls.begin(), drawCalls()->at(i) );
    00834     drawCalls()->eraseAt(i);
    00835   }
    00836   // preseve rendering order
    00837   std::reverse(mergendo_calls.begin(), mergendo_calls.end());
    00838
    00839   ref<DrawElementsUInt> de = new DrawElementsUInt;
    00840   ArrayUInt1& index_buffer = *de->indexBuffer();
    00841   index_buffer.resize( triangle_count * 3 );
    00842   u32 idx = 0;
    00843   for(u32 i=0; i<mergendo_calls.size(); ++i)
    00844   {
    00845     for(TriangleIterator it = mergendo_calls[i]->triangleIterator(); it.hasNext(); it.next(), idx+=3)
    00846     {
    00847       VL_CHECK( idx+2 < index_buffer.size() );
    00848
    00849       vec3 p0 = posarr->getAsVec3(it.a());
    00850       vec3 p1 = posarr->getAsVec3(it.b());
    00851       vec3 p2 = posarr->getAsVec3(it.c());
    00852       p1 = (p1 - p0).normalize();
    00853       p2 = (p2 - p0).normalize();
    00854       vec3 n1 = vl::cross(p1, p2);
    00855
    00856       vec3 v0 = normarr->getAsVec3(it.a());
    00857       vec3 v1 = normarr->getAsVec3(it.b());
    00858       vec3 v2 = normarr->getAsVec3(it.c());
    00859       vec3 n2 = (v0+v1+v2).normalize();
    00860
    00861       if (dot(n1, n2) > 0)
    00862       {
    00863         index_buffer[idx+0] = it.a();
    00864         index_buffer[idx+1] = it.b();
    00865         index_buffer[idx+2] = it.c();
    00866       }
    00867       else
    00868       {
    00869         index_buffer[idx+0] = it.a();
    00870         index_buffer[idx+1] = it.c();
    00871         index_buffer[idx+2] = it.b();
    00872       }
    00873
    00874       // some sanity checks since we are here...
    00875       VL_CHECK( it.a() < (int)posarr->size() && it.b() < (int)posarr->size() && it.c() < (int)posarr->size() );
    00876       VL_CHECK( it.a() >= 0 && it.b() >= 0 && it.c() >= 0 );
    00877     }
    00878   }
    00879   VL_CHECK( idx == index_buffer.size() );
    00880   drawCalls()->push_back(de.get());
    00881 }
    00882 //-----------------------------------------------------------------------------
    00883 void Geometry::regenerateVertices(const std::vector<u32>& map_new_to_old)
    00884 {
    00885   VertexMapper mapper;
    00886
    00887   if (vertexArray())
    00888     setVertexArray( mapper.regenerate( vertexArray(), map_new_to_old ).get() );
    00889
    00890   if (normalArray())
    00891     setNormalArray( mapper.regenerate( normalArray(), map_new_to_old ).get() );
    00892
    00893   if (colorArray())
    00894     setColorArray( mapper.regenerate( colorArray(), map_new_to_old ).get() );
    00895
    00896   if (secondaryColorArray())
    00897     setSecondaryColorArray( mapper.regenerate( secondaryColorArray(), map_new_to_old ).get() );
    00898
    00899   if (fogCoordArray())
    00900     setFogCoordArray( mapper.regenerate( fogCoordArray(), map_new_to_old ).get() );
    00901
    00902   for(int itex=0; itex<VL_MAX_TEXTURE_UNITS; ++itex)
    00903     if (texCoordArray(itex))
    00904       setTexCoordArray( itex, mapper.regenerate( texCoordArray(itex), map_new_to_old ).get() );
    00905
    00906   for(int i=0; i<vertexAttribArrays()->size(); ++i)
    00907     vertexAttribArrays()->at(i)->setData( mapper.regenerate(vertexAttribArrays()->at(i)->data(), map_new_to_old ).get() );
    00908 }
    00909 //-----------------------------------------------------------------------------
    00910 void Geometry::convertDrawCallToDrawArrays()
    00911 {
    00912   ArrayAbstract* posarr = vertexArray() ? vertexArray() : vertexAttribArray(vl::VA_Position) ? vertexAttribArray(vl::VA_Position)->data() : NULL;
    00913
    00914   // generate mapping
    00915   std::vector<u32> map_new_to_old;
    00916   map_new_to_old.reserve( posarr ? (posarr->size() * 3) : (1024 * 64) );
    00917
    00918   for(int i=drawCalls()->size(); i--; )
    00919   {
    00920     int start = (int)map_new_to_old.size();
    00921     for(IndexIterator it=drawCalls()->at(i)->indexIterator(); it.hasNext(); it.next())
    00922       map_new_to_old.push_back(it.index());
    00923     int count = (int)map_new_to_old.size() - start;
    00924
    00925     // substitute with DrawArrays
    00926     ref<DrawArrays> da = new vl::DrawArrays( drawCalls()->at(i)->primitiveType(), start, count, drawCalls()->at(i)->instances() );
    00927     drawCalls()->erase(i,1);
    00928     drawCalls()->push_back(da.get());
    00929   }
    00930
    00931   regenerateVertices(map_new_to_old);
    00932 }
    00933 //-----------------------------------------------------------------------------
    00934 void Geometry::triangulateDrawCalls()
    00935 {
    00936   // converts PT_QUADS, PT_QUADS_STRIP and PT_POLYGON into PT_TRIANGLES
    00937   for( int idraw=this->drawCalls()->size(); idraw--; )
    00938   {
    00939     DrawCall* dc = this->drawCalls()->at(idraw);
    00940     switch(dc->primitiveType())
    00941     {
    00942     case PT_QUADS:
    00943     case PT_QUAD_STRIP:
    00944     case PT_POLYGON:
    00945       break;
    00946     default:
    00947       continue;
    00948     }
    00949
    00950     u32 tri_count = dc->countTriangles();
    00951
    00952     ref<DrawElementsUInt> triangles = new DrawElementsUInt(PT_TRIANGLES, dc->instances());
    00953     triangles->indexBuffer()->resize( tri_count*3 );
    00954     unsigned int* ptr = triangles->indexBuffer()->begin();
    00955     for( TriangleIterator it = dc->triangleIterator(); it.hasNext(); ++it, ptr+=3 )
    00956     {
    00957       ptr[0] = it.a();
    00958       ptr[1] = it.b();
    00959       ptr[2] = it.c();
    00960     }
    00961     VL_CHECK( ptr == triangles->indexBuffer()->end() )
    00962     // substitute the draw call
    00963     (*drawCalls())[idraw] = triangles;
    00964   }
    00965 }
    00966 //-----------------------------------------------------------------------------
    00967 void Geometry::shrinkDrawCalls()
    00968 {
    00969 #ifndef NDEBUG
    00970   ArrayAbstract* posarr = vertexArray() ? vertexArray() : vertexAttribArray(vl::VA_Position) ? vertexAttribArray(vl::VA_Position)->data() : NULL;
    00971   VL_CHECK(posarr);
    00972 #endif
    00973
    00974   for( int idraw=this->drawCalls()->size(); idraw--; )
    00975   {
    00976     ref<DrawCall> dc = this->drawCalls()->at(idraw);
    00977
    00978     unsigned int restart_idx = dc->primitiveRestartIndex();
    00979     bool restart_on = dc->primitiveRestartEnabled();
    00980
    00981     // find max index
    00982     int max_idx = -1;
    00983     int idx_count = 0;
    00984     for( vl::IndexIterator it = dc->indexIterator(); it.hasNext(); it.next(), ++idx_count )
    00985     {
    00986       // skip primitive restart indices
    00987       if (restart_on && it.index() == (int)restart_idx)
    00988         continue;
    00989       else
    00990         max_idx = it.index() > max_idx ? it.index() : max_idx;
    00991     }
    00992
    00993     // can use UByte
    00994     if ( max_idx < 0xFF || (max_idx == 0xFF && !restart_on) )
    00995     {
    00996       if (dc->isOfType(DrawElementsBase::Type()))
    00997       {
    00998         ref<DrawElementsUByte> de = new DrawElementsUByte( dc->primitiveType(), dc->instances() );
    00999         // prim restart
    01000         de->setPrimitiveRestartEnabled( dc->primitiveRestartEnabled() );
    01001         // base vertex
    01002         de->setBaseVertex( dc->as<DrawElementsBase>()->baseVertex() );
    01003         // regenerate indices
    01004         de->indexBuffer()->resize( idx_count );
    01005         u32 i=0;
    01006         for( vl::IndexIterator it = dc->indexIterator(); it.hasNext(); ++it, ++i )
    01007         {
    01008           // skip primitive restart indices
    01009           if (restart_on && it.index() == (int)restart_idx)
    01010             de->indexBuffer()->at(i) = DrawElementsUByte::primitive_restart_index;
    01011           else
    01012           {
    01013             VL_CHECK( it.index() >= 0 && it.index() < (int)posarr->size() );
    01014             de->indexBuffer()->at(i) = (DrawElementsUByte::index_type)it.index();
    01015           }
    01016         }
    01017         VL_CHECK( i == de->indexBuffer()->size() );
    01018         // substitute new draw call
    01019         (*drawCalls())[idraw] = de;
    01020       }
    01021       else
    01022       if (dc->isOfType(DrawRangeElementsBase::Type()))
    01023       {
    01024         ref<DrawRangeElementsUByte> de = new DrawRangeElementsUByte( dc->primitiveType(), dc->instances() );
    01025         // prim restart
    01026         de->setPrimitiveRestartEnabled( dc->primitiveRestartEnabled() );
    01027         // base vertex
    01028         de->setBaseVertex( dc->as<DrawRangeElementsBase>()->baseVertex() );
    01029         // range
    01030         de->setRangeStart( dc->as<DrawRangeElementsBase>()->rangeStart() );
    01031         de->setRangeEnd( dc->as<DrawRangeElementsBase>()->rangeEnd() );
    01032         // regenerate indices
    01033         de->indexBuffer()->resize( idx_count );
    01034         u32 i=0;
    01035         for( vl::IndexIterator it = dc->indexIterator(); it.hasNext(); ++it, ++i )
    01036         {
    01037           // skip primitive restart indices
    01038           if (restart_on && it.index() == (int)restart_idx)
    01039             de->indexBuffer()->at(i) = DrawRangeElementsUByte::primitive_restart_index;
    01040           else
    01041             de->indexBuffer()->at(i) = (DrawRangeElementsUByte::index_type)it.index();
    01042         }
    01043         VL_CHECK( i == de->indexBuffer()->size() );
    01044         // substitute new draw call
    01045         (*drawCalls())[idraw] = de;
    01046       }
    01047       else
    01048       if (dc->isOfType(MultiDrawElementsBase::Type()))
    01049       {
    01050         ref<MultiDrawElementsUByte> de = new MultiDrawElementsUByte( dc->primitiveType() );
    01051         // regenerate indices
    01052         de->indexBuffer()->resize( idx_count );
    01053         u32 i=0;
    01054         for( vl::IndexIterator it = dc->indexIterator(); it.hasNext(); ++it, ++i )
    01055         {
    01056           // skip primitive restart indices
    01057           if (restart_on && it.index() == (int)restart_idx)
    01058             de->indexBuffer()->at(i) = DrawElementsUByte::primitive_restart_index;
    01059           else
    01060             de->indexBuffer()->at(i) = (MultiDrawElementsUByte::index_type)it.index();
    01061         }
    01062         VL_CHECK( i == de->indexBuffer()->size() );
    01063         // prim restart
    01064         de->setPrimitiveRestartEnabled( dc->primitiveRestartEnabled() );
    01065         // base vertex
    01066         de->setBaseVertices( dc->as<MultiDrawElementsBase>()->baseVertices() );
    01067         // count vector
    01068         de->setCountVector( dc->as<MultiDrawElementsBase>()->countVector() );
    01069         // substitute new draw call
    01070         (*drawCalls())[idraw] = de;
    01071       }
    01072     } // can use UByte
    01073     else
    01074     // can use UShort
    01075     if ( max_idx < 0xFFFF || (max_idx == 0xFFFF && !restart_on) )
    01076     {
    01077       if (dc->isOfType(DrawElementsBase::Type()))
    01078       {
    01079         ref<DrawElementsUShort> de = new DrawElementsUShort( dc->primitiveType(), dc->instances() );
    01080         // prim restart
    01081         de->setPrimitiveRestartEnabled( dc->primitiveRestartEnabled() );
    01082         // base vertex
    01083         de->setBaseVertex( dc->as<DrawElementsBase>()->baseVertex() );
    01084         // regenerate indices
    01085         de->indexBuffer()->resize( idx_count );
    01086         u32 i=0;
    01087         for( vl::IndexIterator it = dc->indexIterator(); it.hasNext(); ++it, ++i )
    01088         {
    01089           // skip primitive restart indices
    01090           if (restart_on && it.index() == (int)restart_idx)
    01091             de->indexBuffer()->at(i) = DrawElementsUShort::primitive_restart_index;
    01092           else
    01093           {
    01094             VL_CHECK( it.index() >= 0 && it.index() < (int)posarr->size() );
    01095             de->indexBuffer()->at(i) = (DrawElementsUShort::index_type)it.index();
    01096           }
    01097         }
    01098         VL_CHECK( i == de->indexBuffer()->size() );
    01099         // substitute new draw call
    01100         (*drawCalls())[idraw] = de;
    01101       }
    01102       else
    01103       if (dc->isOfType(DrawRangeElementsBase::Type()))
    01104       {
    01105         ref<DrawRangeElementsUShort> de = new DrawRangeElementsUShort( dc->primitiveType(), dc->instances() );
    01106         // prim restart
    01107         de->setPrimitiveRestartEnabled( dc->primitiveRestartEnabled() );
    01108         // base vertex
    01109         de->setBaseVertex( dc->as<DrawRangeElementsBase>()->baseVertex() );
    01110         // range
    01111         de->setRangeStart( dc->as<DrawRangeElementsBase>()->rangeStart() );
    01112         de->setRangeEnd( dc->as<DrawRangeElementsBase>()->rangeEnd() );
    01113         // regenerate indices
    01114         de->indexBuffer()->resize( idx_count );
    01115         u32 i=0;
    01116         for( vl::IndexIterator it = dc->indexIterator(); it.hasNext(); ++it, ++i )
    01117         {
    01118           // skip primitive restart indices
    01119           if (restart_on && it.index() == (int)restart_idx)
    01120             de->indexBuffer()->at(i) = DrawRangeElementsUShort::primitive_restart_index;
    01121           else
    01122             de->indexBuffer()->at(i) = (DrawRangeElementsUShort::index_type)it.index();
    01123         }
    01124         VL_CHECK( i == de->indexBuffer()->size() );
    01125         // substitute new draw call
    01126         (*drawCalls())[idraw] = de;
    01127       }
    01128       else
    01129       if (dc->isOfType(MultiDrawElementsBase::Type()))
    01130       {
    01131         ref<MultiDrawElementsUShort> de = new MultiDrawElementsUShort( dc->primitiveType() );
    01132         // regenerate indices
    01133         de->indexBuffer()->resize( idx_count );
    01134         u32 i=0;
    01135         for( vl::IndexIterator it = dc->indexIterator(); it.hasNext(); ++it, ++i )
    01136         {
    01137           // skip primitive restart indices
    01138           if (restart_on && it.index() == (int)restart_idx)
    01139             de->indexBuffer()->at(i) = DrawElementsUShort::primitive_restart_index;
    01140           else
    01141             de->indexBuffer()->at(i) = (MultiDrawElementsUShort::index_type)it.index();
    01142         }
    01143         VL_CHECK( i == de->indexBuffer()->size() );
    01144         // prim restart
    01145         de->setPrimitiveRestartEnabled( dc->primitiveRestartEnabled() );
    01146         // base vertex
    01147         de->setBaseVertices( dc->as<MultiDrawElementsBase>()->baseVertices() );
    01148         // count vector
    01149         de->setCountVector( dc->as<MultiDrawElementsBase>()->countVector() );
    01150         // substitute new draw call
    01151         (*drawCalls())[idraw] = de;
    01152       }
    01153     } // can use UShort
    01154
    01155   } // for()
    01156 }
    01157 //-----------------------------------------------------------------------------
    01158 void Geometry::makeGLESFriendly()
    01159 {
    01160   // converts legacy vertex arrays into generic vertex attributes
    01161 #if defined(VL_OPENGL_ES2)
    01162   convertToVertexAttribs();
    01163 #endif
    01164
    01165   // converts quads and polygons into triangles
    01166   triangulateDrawCalls();
    01167
    01168   // use short or byte instead of int
    01169   shrinkDrawCalls();
    01170
    01171   // check primitive type is supported by OpenGL ES
    01172   for(int i=0; i<drawCalls()->size(); ++i)
    01173   {
    01174     DrawCall* dc = drawCalls()->at(i);
    01175     // check supported primitive types
    01176     switch(dc->primitiveType())
    01177     {
    01178     case GL_POINTS:
    01179     case GL_LINE_STRIP:
    01180     case GL_LINE_LOOP:
    01181     case GL_LINES:
    01182     case GL_TRIANGLE_STRIP:
    01183     case GL_TRIANGLE_FAN:
    01184     case GL_TRIANGLES:
    01185       break;
    01186
    01187     case PT_QUADS:
    01188     case PT_QUAD_STRIP:
    01189     case PT_POLYGON:
    01190     case PT_LINES_ADJACENCY:
    01191     case PT_LINE_STRIP_ADJACENCY:
    01192     case PT_TRIANGLES_ADJACENCY:
    01193     case PT_TRIANGLE_STRIP_ADJACENCY:
    01194     case PT_PATCHES:
    01195       dc->setEnabled(false);
    01196       Log::error("Geometry::makeGLESFriendly(): primitive type illegal under GLES, draw call disabled.\n");
    01197       break;
    01198
    01199     default:
    01200       VL_TRAP();
    01201       break;
    01202     }
    01203   }
    01204 }
    01205 //-----------------------------------------------------------------------------
    01206 bool Geometry::sortVertices()
    01207 {
    01208   ArrayAbstract* posarr = vertexArray() ? vertexArray() : vertexAttribArray(vl::VA_Position) ? vertexAttribArray(vl::VA_Position)->data() : NULL;
    01209
    01210   if (!posarr)
    01211   {
    01212     Log::warning("Geometry::sortVertices() failed. No vertices found.\n");
    01213     return false;
    01214   }
    01215
    01216   // supports only DrawElements* and generates DrawElementsUInt
    01217
    01218   std::vector< ref<DrawElementsUInt> > de_u32_set;
    01219
    01220   // collect DrawElements
    01221   for(int i=0; i<drawCalls()->size(); ++i)
    01222   {
    01223     DrawCall* dc = drawCalls()->at(i);
    01224     if (dc->primitiveRestartEnabled())
    01225     {
    01226       Log::error("Geometry::sortVertices() does not support DrawCalls with primitive restart enabled.\n");
    01227       return false;
    01228     }
    01229
    01230     DrawElementsUInt*   de_u32 = dc->as<DrawElementsUInt>();
    01231     DrawElementsUShort* de_u16 = dc->as<DrawElementsUShort>();
    01232     DrawElementsUByte*  de_u8  = dc->as<DrawElementsUByte>();
    01233     if (de_u32)
    01234     {
    01235       ref<DrawElementsUInt> de = new DrawElementsUInt(de_u32->primitiveType(), de_u32->instances());
    01236       de_u32_set.push_back(de);
    01237       de->indexBuffer()->resize( de_u32->indexBuffer()->size() );
    01238       for(unsigned int j=0; j<de_u32->indexBuffer()->size(); ++j)
    01239         de->indexBuffer()->at(j) = de_u32->indexBuffer()->at(j) + de_u32->baseVertex(); // bake base vertex
    01240     }
    01241     else
    01242     if(de_u16)
    01243     {
    01244       ref<DrawElementsUInt> de = new DrawElementsUInt(de_u16->primitiveType(), de_u16->instances());
    01245       de_u32_set.push_back(de);
    01246       de->indexBuffer()->resize( de_u16->indexBuffer()->size() );
    01247       for(unsigned int j=0; j<de_u16->indexBuffer()->size(); ++j)
    01248         de->indexBuffer()->at(j) = de_u16->indexBuffer()->at(j) + de_u16->baseVertex(); // bake base vertex
    01249     }
    01250     else
    01251     if(de_u8)
    01252     {
    01253       ref<DrawElementsUInt> de = new DrawElementsUInt(de_u8->primitiveType(), de_u8->instances());
    01254       de_u32_set.push_back(de);
    01255       de->indexBuffer()->resize( de_u8->indexBuffer()->size() );
    01256       for(unsigned int j=0; j<de_u8->indexBuffer()->size(); ++j)
    01257         de->indexBuffer()->at(j) = de_u8->indexBuffer()->at(j) + de_u8->baseVertex(); // bake base vertex
    01258     }
    01259     else
    01260     {
    01261       Log::error("Geometry::sortVertices() supports only DrawElements* draw calls.\n");
    01262       return false;
    01263     }
    01264   }
    01265
    01266   // erase all draw calls
    01267   drawCalls()->clear();
    01268
    01269   // reset tables
    01270   std::vector<u32> map_new_to_old;
    01271   map_new_to_old.resize( posarr->size() );
    01272   memset(&map_new_to_old[0], 0xFF, map_new_to_old.size()*sizeof(map_new_to_old[0])); // fill with 0xFF for debugging
    01273
    01274   std::vector<u32> map_old_to_new;
    01275   map_old_to_new.resize( posarr->size() );
    01276   memset(&map_old_to_new[0], 0xFF, map_old_to_new.size()*sizeof(map_old_to_new[0])); // fill with 0xFF for debugging
    01277
    01278   std::vector<u32> used;
    01279   used.resize( posarr->size() );
    01280   memset(&used[0], 0, used.size()*sizeof(used[0]));
    01281
    01282   // assign new vertex indices in order of appearence
    01283   u32 new_idx = 0;
    01284   for(u32 i=0; i<de_u32_set.size(); ++i)
    01285   {
    01286     ArrayUInt1* index_buffer = de_u32_set[i]->indexBuffer();
    01287     for(u32 idx=0; idx<index_buffer->size(); ++idx)
    01288     {
    01289       if (!used[index_buffer->at(idx)])
    01290       {
    01291         const DrawElementsUInt::index_type& old_idx = index_buffer->at(idx);
    01292         map_new_to_old[new_idx] = old_idx;
    01293         map_old_to_new[old_idx] = new_idx;
    01294         used[old_idx] = 1;
    01295         ++new_idx;
    01296       }
    01297     }
    01298   }
    01299
    01300   // regenerate vertices
    01301   regenerateVertices(map_new_to_old);
    01302
    01303   // regenerate draw calls
    01304   for(u32 i=0; i<de_u32_set.size(); ++i)
    01305   {
    01306     drawCalls()->push_back(de_u32_set[i].get());
    01307     ArrayUInt1* index_buffer = de_u32_set[i]->indexBuffer();
    01308     for(u32 j=0; j<index_buffer->size(); ++j)
    01309     {
    01310       index_buffer->at(j) = map_old_to_new[index_buffer->at(j)];
    01311     }
    01312   }
    01313
    01314   return true;
    01315 }
    01316 //-----------------------------------------------------------------------------
    01317 void Geometry::colorizePrimitives()
    01318 {
    01319   ArrayAbstract* posarr = vertexArray() ? vertexArray() : vertexAttribArray(vl::VA_Position) ? vertexAttribArray(vl::VA_Position)->data() : NULL;
    01320
    01321   if (!posarr)
    01322     return;
    01323
    01324   ref<ArrayFloat4> col = new vl::ArrayFloat4;
    01325   col->resize( posarr->size() );
    01326
    01327   if (vertexArray())
    01328     setColorArray( col.get() );
    01329   else
    01330     setVertexAttribArray( vl::VA_Color, col.get() );
    01331
    01332   for(int i=0; i<drawCalls()->size(); ++i)
    01333   {
    01334     fvec4 c;
    01335     c.r() = rand()%100 / 99.0f;
    01336     c.g() = rand()%100 / 99.0f;
    01337     c.b() = rand()%100 / 99.0f;
    01338     c.a() = 1.0f;
    01339
    01340     for(IndexIterator it=drawCalls()->at(i)->indexIterator(); it.hasNext(); it.next())
    01341       col->at( it.index() ) = c;
    01342   }
    01343 }
    01344 //-----------------------------------------------------------------------------
    01345 void Geometry::computeTangentSpace(
    01346   u32 vert_count,
    01347   const fvec3 *vertex,
    01348   const fvec3* normal,
    01349   const fvec2 *texcoord,
    01350   const DrawCall* prim,
    01351   fvec3 *tangent,
    01352   fvec3 *bitangent )
    01353 {
    01354   std::vector<fvec3> tan1;
    01355   std::vector<fvec3> tan2;
    01356   tan1.resize(vert_count);
    01357   tan2.resize(vert_count);
    01358
    01359   for ( TriangleIterator trit = prim->triangleIterator(); trit.hasNext(); trit.next() )
    01360   {
    01361     unsigned int tri[] = { trit.a(), trit.b(), trit.c() };
    01362
    01363     VL_CHECK(tri[0] < vert_count );
    01364     VL_CHECK(tri[1] < vert_count );
    01365     VL_CHECK(tri[2] < vert_count );
    01366
    01367     const fvec3& v1 = vertex[tri[0]];
    01368     const fvec3& v2 = vertex[tri[1]];
    01369     const fvec3& v3 = vertex[tri[2]];
    01370
    01371     const fvec2& w1 = texcoord[tri[0]];
    01372     const fvec2& w2 = texcoord[tri[1]];
    01373     const fvec2& w3 = texcoord[tri[2]];
    01374
    01375     float x1 = v2.x() - v1.x();
    01376     float x2 = v3.x() - v1.x();
    01377     float y1 = v2.y() - v1.y();
    01378     float y2 = v3.y() - v1.y();
    01379     float z1 = v2.z() - v1.z();
    01380     float z2 = v3.z() - v1.z();
    01381
    01382     float s1 = w2.x() - w1.x();
    01383     float s2 = w3.x() - w1.x();
    01384     float t1 = w2.y() - w1.y();
    01385     float t2 = w3.y() - w1.y();
    01386
    01387     float r = 1.0F / (s1 * t2 - s2 * t1);
    01388     fvec3 sdir((t2 * x1 - t1 * x2) * r, (t2 * y1 - t1 * y2) * r, (t2 * z1 - t1 * z2) * r);
    01389     fvec3 tdir((s1 * x2 - s2 * x1) * r, (s1 * y2 - s2 * y1) * r, (s1 * z2 - s2 * z1) * r);
    01390
    01391     tan1[tri[0]] += sdir;
    01392     tan1[tri[1]] += sdir;
    01393     tan1[tri[2]] += sdir;
    01394
    01395     tan2[tri[0]] += tdir;
    01396     tan2[tri[1]] += tdir;
    01397     tan2[tri[2]] += tdir;
    01398   }
    01399
    01400   for ( u32 a = 0; a < vert_count; a++)
    01401   {
    01402     const fvec3& n = normal[a];
    01403     const fvec3& t = tan1[a];
    01404
    01405     // Gram-Schmidt orthogonalize
    01406     tangent[a] = (t - n * dot(n, t)).normalize();
    01407
    01408     if ( bitangent )
    01409     {
    01410       // Calculate handedness
    01411       float w = (dot(cross(n, t), tan2[a]) < 0.0F) ? -1.0F : 1.0F;
    01412       bitangent[a] = cross( n, tangent[a] ) * w;
    01413     }
    01414   }
    01415 }
    01416 //-----------------------------------------------------------------------------

Visualization Library v2011.09.1162 Reference Documentation
Copyright 2005-2011 Michele Bosi. All rights reserved.
Updated on Thu Jan 26 2012 00:43:38.
Permission is granted to use this page to write and publish articles regarding Visualization Library.