00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
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
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
00108 super::operator=(other);
00109
00110
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
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
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
00150 super::operator=(other);
00151
00152
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
00168
00169 VL_CHECK( !data || (data->glSize() >=2 && data->glSize()<=4) )
00170
00171 mVertexArray = data;
00172 }
00173
00174 void Geometry::setNormalArray(ArrayAbstract* data)
00175 {
00176
00177
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
00191
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
00208
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
00225
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
00235
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);
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 setBufferObjectDirty(true);
00262 mVertexArray = NULL;
00263 mNormalArray = NULL;
00264 mColorArray = NULL;
00265 mSecondaryColorArray = NULL;
00266 mFogCoordArray = NULL;
00267 mTexCoordArrays.clear();
00268 mVertexAttribArrays.clear();
00269 if (clear_draw_calls)
00270 mDrawCalls.clear();
00271 }
00272
00273 bool Geometry::flipNormals()
00274 {
00275 ArrayAbstract* normarr = normalArray() ? normalArray() : vertexAttribArray(vl::VA_Normal) ? vertexAttribArray(vl::VA_Normal)->data() : NULL;
00276
00277 if (normarr)
00278 {
00279 ArrayFloat3* norm3f = normarr->as<ArrayFloat3>();
00280 if (norm3f)
00281 {
00282 for(u32 i=0; i<norm3f->size(); ++i)
00283 {
00284 norm3f->at(i) = -norm3f->at(i);
00285 }
00286 return true;
00287 }
00288 }
00289 return false;
00290 }
00291
00292 void Geometry::convertToVertexAttribs()
00293 {
00294 std::map<int, ref<ArrayAbstract> > attrib_map;
00295
00296 if (vertexArray())
00297 {
00298 attrib_map[VA_Position] = vertexArray();
00299 setVertexArray(NULL);
00300 }
00301
00302 if (normalArray())
00303 {
00304 attrib_map[VA_Normal] = normalArray();
00305 setNormalArray(NULL);
00306 }
00307
00308 if (colorArray())
00309 {
00310 attrib_map[VA_Color] = colorArray();
00311 setColorArray(NULL);
00312 }
00313
00314
00315 for(int i=0; i<mTexCoordArrays.size(); i++)
00316 {
00317 attrib_map[VA_TexCoord0+i] = mTexCoordArrays[i]->mTexCoordArray;
00318 }
00319 mTexCoordArrays.clear();
00320
00321
00322 int index = VA_TexCoord0 + mTexCoordArrays.size();
00323 if (secondaryColorArray())
00324 {
00325 attrib_map[index++] = secondaryColorArray();
00326 setSecondaryColorArray(NULL);
00327 }
00328
00329 if (fogCoordArray())
00330 {
00331 attrib_map[index++] = fogCoordArray();
00332 setFogCoordArray(NULL);
00333 }
00334
00335
00336
00337 for(std::map<int, ref<ArrayAbstract> >::iterator it=attrib_map.begin(); it != attrib_map.end(); ++it)
00338 {
00339 if (vertexAttribArray(it->first) != NULL)
00340 Log::warning( Say("Geometry::convertToVertexAttribs(): vertex attrib index #%n is already in use, it will be overwritten.\n") << it->first );
00341 setVertexAttribArray(it->first, it->second.get());
00342 }
00343
00344 }
00345
00346 void Geometry::computeNormals(bool verbose)
00347 {
00348
00349 ArrayAbstract* posarr = vertexArray() ? vertexArray() : vertexAttribArray(vl::VA_Position) ? vertexAttribArray(vl::VA_Position)->data() : NULL;
00350 if (!posarr || posarr->size() == 0)
00351 {
00352 Log::warning("Geometry::computeNormals() failed: no vertices found!\n");
00353 return;
00354 }
00355
00356 ref<ArrayFloat3> norm3f = new ArrayFloat3;
00357 norm3f->resize( posarr->size() );
00358
00359
00360 if (vertexArray())
00361 setNormalArray( norm3f.get() );
00362 else
00363 setVertexAttribArray(VA_Normal, norm3f.get());
00364
00365
00366 for(u32 i=0; i<norm3f->size(); ++i)
00367 (*norm3f)[i] = 0;
00368
00369
00370 for(int prim=0; prim<(int)drawCalls()->size(); prim++)
00371 {
00372
00373 for(TriangleIterator trit = mDrawCalls[prim]->triangleIterator(); trit.hasNext(); trit.next())
00374 {
00375 u32 a = trit.a();
00376 u32 b = trit.b();
00377 u32 c = trit.c();
00378
00379 if (verbose)
00380 if (a == b || b == c || c == a)
00381 {
00382 Log::warning( Say("Geometry::computeNormals(): skipping degenerate triangle %n %n %n\n") << a << b << c );
00383 continue;
00384 }
00385
00386 VL_CHECK( a < posarr->size() )
00387 VL_CHECK( b < posarr->size() )
00388 VL_CHECK( c < posarr->size() )
00389
00390 vec3 n, v0, v1, v2;
00391
00392 v0 = posarr->getAsVec3(a);
00393 v1 = posarr->getAsVec3(b);
00394 v2 = posarr->getAsVec3(c);
00395
00396 if (verbose)
00397 if (v0 == v1 || v1 == v2 || v2 == v0)
00398 {
00399 Log::warning("Geometry::computeNormals(): skipping degenerate triangle (same vertex coodinate).\n");
00400 continue;
00401 }
00402
00403 v1 -= v0;
00404 v2 -= v0;
00405
00406 n = cross(v1, v2);
00407 n.normalize();
00408 if (verbose)
00409 if ( fabs(1.0f - n.length()) > 0.1f )
00410 {
00411 Log::warning("Geometry::computeNormals(): skipping degenerate triangle (normalization failed).\n");
00412 continue;
00413 }
00414
00415 (*norm3f)[a] += (fvec3)n;
00416 (*norm3f)[b] += (fvec3)n;
00417 (*norm3f)[c] += (fvec3)n;
00418 }
00419 }
00420
00421
00422 for(int i=0; i<(int)norm3f->size(); ++i)
00423 (*norm3f)[i].normalize();
00424 }
00425
00426 void Geometry::deleteBufferObject()
00427 {
00428 if (!Has_BufferObject)
00429 return;
00430
00431 for(int i=0; i<(int)drawCalls()->size(); ++i)
00432 drawCalls()->at(i)->deleteBufferObject();
00433
00434 if (mVertexArray)
00435 mVertexArray->bufferObject()->deleteBufferObject();
00436
00437 if (mNormalArray)
00438 mNormalArray->bufferObject()->deleteBufferObject();
00439
00440 if (mColorArray)
00441 mColorArray->bufferObject()->deleteBufferObject();
00442
00443 if (mSecondaryColorArray)
00444 mSecondaryColorArray->bufferObject()->deleteBufferObject();
00445
00446 if (mFogCoordArray)
00447 mFogCoordArray->bufferObject()->deleteBufferObject();
00448
00449 for (int i=0; i<mTexCoordArrays.size(); ++i)
00450 mTexCoordArrays[i]->mTexCoordArray->bufferObject()->deleteBufferObject();
00451
00452 for(int i=0; i<vertexAttribArrays()->size(); ++i)
00453 if ( vertexAttribArrays()->at(i)->data() )
00454 vertexAttribArrays()->at(i)->data()->bufferObject()->deleteBufferObject();
00455 }
00456
00457 void Geometry::updateDirtyBufferObject(EBufferObjectUpdateMode mode)
00458 {
00459 if (!Has_BufferObject)
00460 return;
00461
00462 bool force_update = (mode & BUF_ForceUpdate) != 0;
00463
00464 if ( mVertexArray && (mVertexArray->isBufferObjectDirty() || force_update) )
00465 mVertexArray->updateBufferObject(mode);
00466
00467 if ( mNormalArray && (mNormalArray->isBufferObjectDirty() || force_update) )
00468 mNormalArray->updateBufferObject(mode);
00469
00470 if ( mColorArray && (mColorArray->isBufferObjectDirty() || force_update) )
00471 mColorArray->updateBufferObject(mode);
00472
00473 if ( mSecondaryColorArray && (mSecondaryColorArray->isBufferObjectDirty() || force_update) )
00474 mSecondaryColorArray->updateBufferObject(mode);
00475
00476 if ( mFogCoordArray && (mFogCoordArray->isBufferObjectDirty() || force_update) )
00477 mFogCoordArray->updateBufferObject(mode);
00478
00479 for(int i=0; i<mTexCoordArrays.size(); ++i)
00480 {
00481 if ( mTexCoordArrays[i]->mTexCoordArray->isBufferObjectDirty() || force_update )
00482 mTexCoordArrays[i]->mTexCoordArray->updateBufferObject(mode);
00483 }
00484
00485 for(int i=0; i<vertexAttribArrays()->size(); ++i)
00486 if ( vertexAttribArrays()->at(i)->data() && (vertexAttribArrays()->at(i)->data()->isBufferObjectDirty() || force_update) )
00487 vertexAttribArrays()->at(i)->data()->updateBufferObject(mode);
00488
00489 for(int i=0; i<drawCalls()->size(); ++i)
00490 drawCalls()->at(i)->updateDirtyBufferObject(mode);
00491 }
00492
00493 void Geometry::render_Implementation(const Actor*, const Shader*, const Camera*, OpenGLContext* gl_context) const
00494 {
00495 VL_CHECK_OGL()
00496
00497
00498
00499 bool vbo_on = Has_BufferObject && isBufferObjectEnabled() && !isDisplayListEnabled();
00500 gl_context->bindVAS(this, vbo_on, false);
00501
00502
00503
00504 for(int i=0; i<(int)drawCalls()->size(); i++)
00505 if (drawCalls()->at(i)->isEnabled())
00506 drawCalls()->at(i)->render( vbo_on );
00507
00508 VL_CHECK_OGL()
00509 }
00510
00511 void Geometry::transform(const mat4& m, bool normalize)
00512 {
00513 ArrayAbstract* posarr = vertexArray() ? vertexArray() : vertexAttribArray(vl::VA_Position) ? vertexAttribArray(vl::VA_Position)->data() : NULL;
00514 if (posarr)
00515 posarr->transform(m);
00516
00517 ArrayAbstract* normarr = normalArray() ? normalArray() : vertexAttribArray(vl::VA_Normal) ? vertexAttribArray(vl::VA_Normal)->data() : NULL;
00518 if (normarr)
00519 {
00520 mat4 nmat = m.as3x3().invert().transpose();
00521 normarr->transform(nmat);
00522 if (normalize)
00523 normarr->normalize();
00524 }
00525 }
00526
00527 void Geometry::setVertexAttribArray(const VertexAttribInfo& info)
00528 {
00529 for(int i=0; i<vertexAttribArrays()->size(); ++i)
00530 {
00531 VL_CHECK(vertexAttribArrays()->at(i))
00532 if (vertexAttribArrays()->at(i)->attribLocation() == info.attribLocation())
00533 {
00534 *vertexAttribArrays()->at(i) = info;
00535 return;
00536 }
00537 }
00538 mVertexAttribArrays.push_back( new VertexAttribInfo(info) );
00539 }
00540
00541 const VertexAttribInfo* Geometry::vertexAttribArray(unsigned int attrib_location) const
00542 {
00543 for(int i=0; i<vertexAttribArrays()->size(); ++i)
00544 if (vertexAttribArrays()->at(i)->attribLocation() == attrib_location)
00545 return vertexAttribArrays()->at(i);
00546 return NULL;
00547 }
00548
00549 VertexAttribInfo* Geometry::vertexAttribArray(unsigned int attrib_location)
00550 {
00551 for(int i=0; i<vertexAttribArrays()->size(); ++i)
00552 if (vertexAttribArrays()->at(i)->attribLocation() == attrib_location)
00553 return vertexAttribArrays()->at(i);
00554 return NULL;
00555 }
00556
00557 DrawCall* Geometry::mergeTriangleStrips()
00558 {
00559 ArrayAbstract* posarr = vertexArray() ? vertexArray() : vertexAttribArray(vl::VA_Position) ? vertexAttribArray(vl::VA_Position)->data() : NULL;
00560
00561 if (!posarr)
00562 return NULL;
00563
00564 std::vector< ref<DrawElementsBase> > de_vector;
00565 std::vector<u32> indices;
00566
00567
00568 for(int i=drawCalls()->size(); i--; )
00569 {
00570 ref<DrawElementsBase> deb = cast<DrawElementsBase>( drawCalls()->at(i) );
00571 if (deb && deb->primitiveType() == PT_TRIANGLE_STRIP)
00572 {
00573
00574 de_vector.push_back( deb );
00575 drawCalls()->eraseAt(i);
00576 }
00577 }
00578
00579 std::reverse(de_vector.begin(), de_vector.end());
00580
00581
00582 indices.reserve( posarr->size()*2 );
00583 for(u32 i=0; i<de_vector.size(); ++i)
00584 {
00585 u32 index_count = 0;
00586 for(IndexIterator it=de_vector[i]->indexIterator(); it.hasNext(); it.next(), ++index_count)
00587 indices.push_back(it.index());
00588
00589 if (index_count == 0)
00590 continue;
00591
00592
00593 if ( index_count % 2 )
00594 indices.push_back( indices.back() );
00595
00596
00597 if ( i != de_vector.size()-1 )
00598 {
00599
00600 IndexIterator it = de_vector[i+1]->indexIterator();
00601 int A = it.index();
00602 it.next();
00603 int B = it.index();
00604
00605 if (A == -1 || B == -1)
00606 continue;
00607
00608 indices.push_back( indices.back() );
00609 indices.push_back(A);
00610 indices.push_back(A);
00611 indices.push_back(B);
00612 }
00613 }
00614
00615 if (indices.size())
00616 {
00617 ref<DrawElementsUInt> draw_elems = new DrawElementsUInt(PT_TRIANGLE_STRIP);
00618 draw_elems->indexBuffer()->resize(indices.size());
00619 memcpy(draw_elems->indexBuffer()->ptr(), &indices[0], sizeof(indices[0])*indices.size());
00620 drawCalls()->push_back(draw_elems.get());
00621 return draw_elems.get();
00622 }
00623 else
00624 return NULL;
00625 }
00626
00627 void Geometry::mergeDrawCallsWithPrimitiveRestart(EPrimitiveType primitive_type)
00628 {
00629 u32 total_index_count = 0;
00630 std::vector< ref<DrawCall> > mergendo_calls;
00631 for( u32 i=drawCalls()->size(); i--; )
00632 {
00633 if (drawCalls()->at(i)->primitiveType() == primitive_type)
00634 {
00635 int index_count = drawCalls()->at(i)->countIndices();
00636 VL_CHECK(index_count >= 0);
00637 total_index_count += index_count;
00638
00639 mergendo_calls.push_back( drawCalls()->at(i) );
00640 drawCalls()->eraseAt(i);
00641 }
00642 }
00643
00644 std::reverse(mergendo_calls.begin(), mergendo_calls.end());
00645
00646 Log::debug( Say("%n draw calls will be merged using primitive restart.\n") << mergendo_calls.size() );
00647
00648 if (mergendo_calls.empty())
00649 return;
00650
00651 #ifndef NDEBUG
00652 ArrayAbstract* posarr = vertexArray() ? vertexArray() : vertexAttribArray(vl::VA_Position) ? vertexAttribArray(vl::VA_Position)->data() : NULL;
00653 #endif
00654
00655 ref<DrawElementsUInt> de_prim_restart = new DrawElementsUInt(primitive_type);
00656
00657 de_prim_restart->indexBuffer()->resize(total_index_count + mergendo_calls.size()-1);
00658 GLuint* index = de_prim_restart->indexBuffer()->begin();
00659
00660 for( u32 i=0; i<mergendo_calls.size(); ++i )
00661 {
00662 for( IndexIterator it = mergendo_calls[i]->indexIterator(); it.hasNext(); it.next(), ++index )
00663 {
00664 *index = it.index();
00665 VL_CHECK(*index < posarr->size());
00666 }
00667 if ( i != mergendo_calls.size() -1 )
00668 {
00669 *index = DrawElementsUInt::primitive_restart_index;
00670 ++index;
00671 }
00672 }
00673 VL_CHECK( index == de_prim_restart->indexBuffer()->end() )
00674
00675
00676 de_prim_restart->setPrimitiveRestartEnabled(true);
00677
00678 drawCalls()->push_back( de_prim_restart.get() );
00679 }
00680
00681 void Geometry::mergeDrawCallsWithMultiDrawElements(EPrimitiveType primitive_type)
00682 {
00683 u32 total_index_count = 0;
00684 std::vector< ref<DrawCall> > mergendo_calls;
00685 std::vector<GLsizei> count_vector;
00686 for( u32 i=drawCalls()->size(); i--; )
00687 {
00688 if (drawCalls()->at(i)->primitiveType() == primitive_type)
00689 {
00690 int index_count = drawCalls()->at(i)->countIndices();
00691 VL_CHECK(index_count >= 0);
00692 total_index_count += index_count;
00693 count_vector.push_back( index_count );
00694 mergendo_calls.push_back( drawCalls()->at(i) );
00695 drawCalls()->eraseAt(i);
00696 }
00697 }
00698
00699 std::reverse(mergendo_calls.begin(), mergendo_calls.end());
00700 std::reverse(count_vector.begin(), count_vector.end());
00701
00702 Log::debug( Say("%n draw calls will be merged using MultiDrawElements.\n") << mergendo_calls.size() );
00703
00704 if (mergendo_calls.empty())
00705 return;
00706
00707 #ifndef NDEBUG
00708 ArrayAbstract* posarr = vertexArray() ? vertexArray() : vertexAttribArray(vl::VA_Position) ? vertexAttribArray(vl::VA_Position)->data() : NULL;
00709 #endif
00710
00711 ref<MultiDrawElementsUInt> de_multi = new MultiDrawElementsUInt(primitive_type);
00712
00713 de_multi->indexBuffer()->resize(total_index_count);
00714 GLuint* index = de_multi->indexBuffer()->begin();
00715
00716 for( u32 i=0; i<mergendo_calls.size(); ++i )
00717 {
00718 for( IndexIterator it = mergendo_calls[i]->indexIterator(); it.hasNext(); it.next(), ++index )
00719 {
00720 *index = it.index();
00721 VL_CHECK(*index < posarr->size());
00722 }
00723 }
00724 VL_CHECK( index == de_multi->indexBuffer()->end() )
00725
00726
00727 de_multi->setCountVector( count_vector );
00728
00729 drawCalls()->push_back( de_multi.get() );
00730 }
00731
00732 void Geometry::mergeDrawCallsWithTriangles(EPrimitiveType primitive_type)
00733 {
00734 u32 triangle_count = 0;
00735 std::vector< ref<DrawCall> > mergendo_calls;
00736 for( u32 i=drawCalls()->size(); i--; )
00737 {
00738 const DrawCall& dc = *drawCalls()->at(i);
00739
00740
00741 switch(dc.primitiveType())
00742 {
00743 case PT_TRIANGLES:
00744 case PT_TRIANGLE_STRIP:
00745 case PT_TRIANGLE_FAN:
00746 case PT_QUADS:
00747 case PT_QUAD_STRIP:
00748 case PT_POLYGON:
00749 break;
00750 default:
00751 continue;
00752 }
00753
00754 if (primitive_type == PT_UNKNOWN || dc.primitiveType() == primitive_type || dc.primitiveType() == PT_TRIANGLES)
00755 {
00756 triangle_count += dc.countTriangles();
00757
00758 mergendo_calls.insert( mergendo_calls.begin(), drawCalls()->at(i) );
00759 drawCalls()->eraseAt(i);
00760 }
00761 }
00762
00763 std::reverse(mergendo_calls.begin(), mergendo_calls.end());
00764
00765 if (mergendo_calls.empty())
00766 return;
00767
00768
00769 if ( mergendo_calls.size() == 1 && mergendo_calls[0]->primitiveType() == PT_TRIANGLES )
00770 {
00771 drawCalls()->push_back( mergendo_calls[0].get() );
00772 return;
00773 }
00774
00775 #ifndef NDEBUG
00776 ArrayAbstract* posarr = vertexArray() ? vertexArray() : vertexAttribArray(vl::VA_Position) ? vertexAttribArray(vl::VA_Position)->data() : NULL;
00777 #endif
00778
00779 ref<DrawElementsUInt> de = new DrawElementsUInt;
00780 ArrayUInt1& index_buffer = *de->indexBuffer();
00781 index_buffer.resize( triangle_count * 3 );
00782 u32 idx = 0;
00783 for(u32 i=0; i<mergendo_calls.size(); ++i)
00784 {
00785 for(TriangleIterator it = mergendo_calls[i]->triangleIterator(); it.hasNext(); it.next(), idx+=3)
00786 {
00787 VL_CHECK( idx+2 < index_buffer.size() );
00788
00789 index_buffer[idx+0] = it.a();
00790 index_buffer[idx+1] = it.b();
00791 index_buffer[idx+2] = it.c();
00792
00793
00794 VL_CHECK( it.a() < (int)posarr->size() && it.b() < (int)posarr->size() && it.c() < (int)posarr->size() );
00795 VL_CHECK( it.a() >= 0 && it.b() >= 0 && it.c() >= 0 );
00796 }
00797 }
00798 VL_CHECK( idx == index_buffer.size() );
00799 drawCalls()->push_back(de.get());
00800 }
00801
00802 void Geometry::fixTriangleWinding()
00803 {
00804 ArrayAbstract* posarr = vertexArray() ? vertexArray() : vertexAttribArray(vl::VA_Position) ? vertexAttribArray(vl::VA_Position)->data() : NULL;
00805
00806 ArrayAbstract* normarr = normalArray() ? normalArray() : vertexAttribArray(vl::VA_Normal) ? vertexAttribArray(vl::VA_Normal)->data() : NULL;
00807
00808
00809 if ( normarr == NULL || posarr == NULL )
00810 return;
00811
00812 u32 triangle_count = 0;
00813 std::vector< ref<DrawCall> > mergendo_calls;
00814 for( u32 i=drawCalls()->size(); i--; )
00815 {
00816 const DrawCall& dc = *drawCalls()->at(i);
00817
00818
00819 switch(dc.primitiveType())
00820 {
00821 case PT_TRIANGLES:
00822 case PT_TRIANGLE_STRIP:
00823 case PT_TRIANGLE_FAN:
00824 case PT_QUADS:
00825 case PT_QUAD_STRIP:
00826 case PT_POLYGON:
00827 break;
00828 default:
00829 continue;
00830 }
00831
00832 triangle_count += dc.countTriangles();
00833
00834 mergendo_calls.insert( mergendo_calls.begin(), drawCalls()->at(i) );
00835 drawCalls()->eraseAt(i);
00836 }
00837
00838 std::reverse(mergendo_calls.begin(), mergendo_calls.end());
00839
00840 ref<DrawElementsUInt> de = new DrawElementsUInt;
00841 ArrayUInt1& index_buffer = *de->indexBuffer();
00842 index_buffer.resize( triangle_count * 3 );
00843 u32 idx = 0;
00844 for(u32 i=0; i<mergendo_calls.size(); ++i)
00845 {
00846 for(TriangleIterator it = mergendo_calls[i]->triangleIterator(); it.hasNext(); it.next(), idx+=3)
00847 {
00848 VL_CHECK( idx+2 < index_buffer.size() );
00849
00850 vec3 p0 = posarr->getAsVec3(it.a());
00851 vec3 p1 = posarr->getAsVec3(it.b());
00852 vec3 p2 = posarr->getAsVec3(it.c());
00853 p1 = (p1 - p0).normalize();
00854 p2 = (p2 - p0).normalize();
00855 vec3 n1 = vl::cross(p1, p2);
00856
00857 vec3 v0 = normarr->getAsVec3(it.a());
00858 vec3 v1 = normarr->getAsVec3(it.b());
00859 vec3 v2 = normarr->getAsVec3(it.c());
00860 vec3 n2 = (v0+v1+v2).normalize();
00861
00862 if (dot(n1, n2) > 0)
00863 {
00864 index_buffer[idx+0] = it.a();
00865 index_buffer[idx+1] = it.b();
00866 index_buffer[idx+2] = it.c();
00867 }
00868 else
00869 {
00870 index_buffer[idx+0] = it.a();
00871 index_buffer[idx+1] = it.c();
00872 index_buffer[idx+2] = it.b();
00873 }
00874
00875
00876 VL_CHECK( it.a() < (int)posarr->size() && it.b() < (int)posarr->size() && it.c() < (int)posarr->size() );
00877 VL_CHECK( it.a() >= 0 && it.b() >= 0 && it.c() >= 0 );
00878 }
00879 }
00880 VL_CHECK( idx == index_buffer.size() );
00881 drawCalls()->push_back(de.get());
00882 }
00883
00884 void Geometry::regenerateVertices(const std::vector<u32>& map_new_to_old)
00885 {
00886 VertexMapper mapper;
00887
00888 if (vertexArray())
00889 setVertexArray( mapper.regenerate( vertexArray(), map_new_to_old ).get() );
00890
00891 if (normalArray())
00892 setNormalArray( mapper.regenerate( normalArray(), map_new_to_old ).get() );
00893
00894 if (colorArray())
00895 setColorArray( mapper.regenerate( colorArray(), map_new_to_old ).get() );
00896
00897 if (secondaryColorArray())
00898 setSecondaryColorArray( mapper.regenerate( secondaryColorArray(), map_new_to_old ).get() );
00899
00900 if (fogCoordArray())
00901 setFogCoordArray( mapper.regenerate( fogCoordArray(), map_new_to_old ).get() );
00902
00903 for(int itex=0; itex<VL_MAX_TEXTURE_UNITS; ++itex)
00904 if (texCoordArray(itex))
00905 setTexCoordArray( itex, mapper.regenerate( texCoordArray(itex), map_new_to_old ).get() );
00906
00907 for(int i=0; i<vertexAttribArrays()->size(); ++i)
00908 vertexAttribArrays()->at(i)->setData( mapper.regenerate(vertexAttribArrays()->at(i)->data(), map_new_to_old ).get() );
00909 }
00910
00911 void Geometry::convertDrawCallToDrawArrays()
00912 {
00913 ArrayAbstract* posarr = vertexArray() ? vertexArray() : vertexAttribArray(vl::VA_Position) ? vertexAttribArray(vl::VA_Position)->data() : NULL;
00914
00915
00916 std::vector<u32> map_new_to_old;
00917 map_new_to_old.reserve( posarr ? (posarr->size() * 3) : (1024 * 64) );
00918
00919 for(int i=drawCalls()->size(); i--; )
00920 {
00921 int start = (int)map_new_to_old.size();
00922 for(IndexIterator it=drawCalls()->at(i)->indexIterator(); it.hasNext(); it.next())
00923 map_new_to_old.push_back(it.index());
00924 int count = (int)map_new_to_old.size() - start;
00925
00926
00927 ref<DrawArrays> da = new vl::DrawArrays( drawCalls()->at(i)->primitiveType(), start, count, drawCalls()->at(i)->instances() );
00928 drawCalls()->erase(i,1);
00929 drawCalls()->push_back(da.get());
00930 }
00931
00932 regenerateVertices(map_new_to_old);
00933 }
00934
00935 void Geometry::triangulateDrawCalls()
00936 {
00937
00938 for( int idraw=this->drawCalls()->size(); idraw--; )
00939 {
00940 DrawCall* dc = this->drawCalls()->at(idraw);
00941 switch(dc->primitiveType())
00942 {
00943 case PT_QUADS:
00944 case PT_QUAD_STRIP:
00945 case PT_POLYGON:
00946 break;
00947 default:
00948 continue;
00949 }
00950
00951 u32 tri_count = dc->countTriangles();
00952
00953 ref<DrawElementsUInt> triangles = new DrawElementsUInt(PT_TRIANGLES, dc->instances());
00954 triangles->indexBuffer()->resize( tri_count*3 );
00955 unsigned int* ptr = triangles->indexBuffer()->begin();
00956 for( TriangleIterator it = dc->triangleIterator(); it.hasNext(); ++it, ptr+=3 )
00957 {
00958 ptr[0] = it.a();
00959 ptr[1] = it.b();
00960 ptr[2] = it.c();
00961 }
00962 VL_CHECK( ptr == triangles->indexBuffer()->end() )
00963
00964 (*drawCalls())[idraw] = triangles;
00965 }
00966 }
00967
00968 void Geometry::shrinkDrawCalls()
00969 {
00970 #ifndef NDEBUG
00971 ArrayAbstract* posarr = vertexArray() ? vertexArray() : vertexAttribArray(vl::VA_Position) ? vertexAttribArray(vl::VA_Position)->data() : NULL;
00972 VL_CHECK(posarr);
00973 #endif
00974
00975 for( int idraw=this->drawCalls()->size(); idraw--; )
00976 {
00977 ref<DrawCall> dc = this->drawCalls()->at(idraw);
00978
00979 unsigned int restart_idx = dc->primitiveRestartIndex();
00980 bool restart_on = dc->primitiveRestartEnabled();
00981
00982
00983 int max_idx = -1;
00984 int idx_count = 0;
00985 for( vl::IndexIterator it = dc->indexIterator(); it.hasNext(); it.next(), ++idx_count )
00986 {
00987
00988 if (restart_on && it.index() == (int)restart_idx)
00989 continue;
00990 else
00991 max_idx = it.index() > max_idx ? it.index() : max_idx;
00992 }
00993
00994
00995 if ( max_idx < 0xFF || (max_idx == 0xFF && !restart_on) )
00996 {
00997 if (dc->isOfType(DrawElementsBase::Type()))
00998 {
00999 ref<DrawElementsUByte> de = new DrawElementsUByte( dc->primitiveType(), dc->instances() );
01000
01001 de->setPrimitiveRestartEnabled( dc->primitiveRestartEnabled() );
01002
01003 de->setBaseVertex( dc->as<DrawElementsBase>()->baseVertex() );
01004
01005 de->indexBuffer()->resize( idx_count );
01006 u32 i=0;
01007 for( vl::IndexIterator it = dc->indexIterator(); it.hasNext(); ++it, ++i )
01008 {
01009
01010 if (restart_on && it.index() == (int)restart_idx)
01011 de->indexBuffer()->at(i) = DrawElementsUByte::primitive_restart_index;
01012 else
01013 {
01014 VL_CHECK( it.index() >= 0 && it.index() < (int)posarr->size() );
01015 de->indexBuffer()->at(i) = (DrawElementsUByte::index_type)it.index();
01016 }
01017 }
01018 VL_CHECK( i == de->indexBuffer()->size() );
01019
01020 (*drawCalls())[idraw] = de;
01021 }
01022 else
01023 if (dc->isOfType(DrawRangeElementsBase::Type()))
01024 {
01025 ref<DrawRangeElementsUByte> de = new DrawRangeElementsUByte( dc->primitiveType(), dc->instances() );
01026
01027 de->setPrimitiveRestartEnabled( dc->primitiveRestartEnabled() );
01028
01029 de->setBaseVertex( dc->as<DrawRangeElementsBase>()->baseVertex() );
01030
01031 de->setRangeStart( dc->as<DrawRangeElementsBase>()->rangeStart() );
01032 de->setRangeEnd( dc->as<DrawRangeElementsBase>()->rangeEnd() );
01033
01034 de->indexBuffer()->resize( idx_count );
01035 u32 i=0;
01036 for( vl::IndexIterator it = dc->indexIterator(); it.hasNext(); ++it, ++i )
01037 {
01038
01039 if (restart_on && it.index() == (int)restart_idx)
01040 de->indexBuffer()->at(i) = DrawRangeElementsUByte::primitive_restart_index;
01041 else
01042 de->indexBuffer()->at(i) = (DrawRangeElementsUByte::index_type)it.index();
01043 }
01044 VL_CHECK( i == de->indexBuffer()->size() );
01045
01046 (*drawCalls())[idraw] = de;
01047 }
01048 else
01049 if (dc->isOfType(MultiDrawElementsBase::Type()))
01050 {
01051 ref<MultiDrawElementsUByte> de = new MultiDrawElementsUByte( dc->primitiveType() );
01052
01053 de->indexBuffer()->resize( idx_count );
01054 u32 i=0;
01055 for( vl::IndexIterator it = dc->indexIterator(); it.hasNext(); ++it, ++i )
01056 {
01057
01058 if (restart_on && it.index() == (int)restart_idx)
01059 de->indexBuffer()->at(i) = DrawElementsUByte::primitive_restart_index;
01060 else
01061 de->indexBuffer()->at(i) = (MultiDrawElementsUByte::index_type)it.index();
01062 }
01063 VL_CHECK( i == de->indexBuffer()->size() );
01064
01065 de->setPrimitiveRestartEnabled( dc->primitiveRestartEnabled() );
01066
01067 de->setBaseVertices( dc->as<MultiDrawElementsBase>()->baseVertices() );
01068
01069 de->setCountVector( dc->as<MultiDrawElementsBase>()->countVector() );
01070
01071 (*drawCalls())[idraw] = de;
01072 }
01073 }
01074 else
01075
01076 if ( max_idx < 0xFFFF || (max_idx == 0xFFFF && !restart_on) )
01077 {
01078 if (dc->isOfType(DrawElementsBase::Type()))
01079 {
01080 ref<DrawElementsUShort> de = new DrawElementsUShort( dc->primitiveType(), dc->instances() );
01081
01082 de->setPrimitiveRestartEnabled( dc->primitiveRestartEnabled() );
01083
01084 de->setBaseVertex( dc->as<DrawElementsBase>()->baseVertex() );
01085
01086 de->indexBuffer()->resize( idx_count );
01087 u32 i=0;
01088 for( vl::IndexIterator it = dc->indexIterator(); it.hasNext(); ++it, ++i )
01089 {
01090
01091 if (restart_on && it.index() == (int)restart_idx)
01092 de->indexBuffer()->at(i) = DrawElementsUShort::primitive_restart_index;
01093 else
01094 {
01095 VL_CHECK( it.index() >= 0 && it.index() < (int)posarr->size() );
01096 de->indexBuffer()->at(i) = (DrawElementsUShort::index_type)it.index();
01097 }
01098 }
01099 VL_CHECK( i == de->indexBuffer()->size() );
01100
01101 (*drawCalls())[idraw] = de;
01102 }
01103 else
01104 if (dc->isOfType(DrawRangeElementsBase::Type()))
01105 {
01106 ref<DrawRangeElementsUShort> de = new DrawRangeElementsUShort( dc->primitiveType(), dc->instances() );
01107
01108 de->setPrimitiveRestartEnabled( dc->primitiveRestartEnabled() );
01109
01110 de->setBaseVertex( dc->as<DrawRangeElementsBase>()->baseVertex() );
01111
01112 de->setRangeStart( dc->as<DrawRangeElementsBase>()->rangeStart() );
01113 de->setRangeEnd( dc->as<DrawRangeElementsBase>()->rangeEnd() );
01114
01115 de->indexBuffer()->resize( idx_count );
01116 u32 i=0;
01117 for( vl::IndexIterator it = dc->indexIterator(); it.hasNext(); ++it, ++i )
01118 {
01119
01120 if (restart_on && it.index() == (int)restart_idx)
01121 de->indexBuffer()->at(i) = DrawRangeElementsUShort::primitive_restart_index;
01122 else
01123 de->indexBuffer()->at(i) = (DrawRangeElementsUShort::index_type)it.index();
01124 }
01125 VL_CHECK( i == de->indexBuffer()->size() );
01126
01127 (*drawCalls())[idraw] = de;
01128 }
01129 else
01130 if (dc->isOfType(MultiDrawElementsBase::Type()))
01131 {
01132 ref<MultiDrawElementsUShort> de = new MultiDrawElementsUShort( dc->primitiveType() );
01133
01134 de->indexBuffer()->resize( idx_count );
01135 u32 i=0;
01136 for( vl::IndexIterator it = dc->indexIterator(); it.hasNext(); ++it, ++i )
01137 {
01138
01139 if (restart_on && it.index() == (int)restart_idx)
01140 de->indexBuffer()->at(i) = DrawElementsUShort::primitive_restart_index;
01141 else
01142 de->indexBuffer()->at(i) = (MultiDrawElementsUShort::index_type)it.index();
01143 }
01144 VL_CHECK( i == de->indexBuffer()->size() );
01145
01146 de->setPrimitiveRestartEnabled( dc->primitiveRestartEnabled() );
01147
01148 de->setBaseVertices( dc->as<MultiDrawElementsBase>()->baseVertices() );
01149
01150 de->setCountVector( dc->as<MultiDrawElementsBase>()->countVector() );
01151
01152 (*drawCalls())[idraw] = de;
01153 }
01154 }
01155
01156 }
01157 }
01158
01159 void Geometry::makeGLESFriendly()
01160 {
01161
01162 #if defined(VL_OPENGL_ES2)
01163 convertToVertexAttribs();
01164 #endif
01165
01166
01167 triangulateDrawCalls();
01168
01169
01170 shrinkDrawCalls();
01171
01172
01173 for(int i=0; i<drawCalls()->size(); ++i)
01174 {
01175 DrawCall* dc = drawCalls()->at(i);
01176
01177 switch(dc->primitiveType())
01178 {
01179 case GL_POINTS:
01180 case GL_LINE_STRIP:
01181 case GL_LINE_LOOP:
01182 case GL_LINES:
01183 case GL_TRIANGLE_STRIP:
01184 case GL_TRIANGLE_FAN:
01185 case GL_TRIANGLES:
01186 break;
01187
01188 case PT_QUADS:
01189 case PT_QUAD_STRIP:
01190 case PT_POLYGON:
01191 case PT_LINES_ADJACENCY:
01192 case PT_LINE_STRIP_ADJACENCY:
01193 case PT_TRIANGLES_ADJACENCY:
01194 case PT_TRIANGLE_STRIP_ADJACENCY:
01195 case PT_PATCHES:
01196 dc->setEnabled(false);
01197 Log::error("Geometry::makeGLESFriendly(): primitive type illegal under GLES, draw call disabled.\n");
01198 break;
01199
01200 default:
01201 VL_TRAP();
01202 break;
01203 }
01204 }
01205 }
01206
01207 bool Geometry::sortVertices()
01208 {
01209 ArrayAbstract* posarr = vertexArray() ? vertexArray() : vertexAttribArray(vl::VA_Position) ? vertexAttribArray(vl::VA_Position)->data() : NULL;
01210
01211 if (!posarr)
01212 {
01213 Log::warning("Geometry::sortVertices() failed. No vertices found.\n");
01214 return false;
01215 }
01216
01217
01218
01219 std::vector< ref<DrawElementsUInt> > de_u32_set;
01220
01221
01222 for(int i=0; i<drawCalls()->size(); ++i)
01223 {
01224 DrawCall* dc = drawCalls()->at(i);
01225 if (dc->primitiveRestartEnabled())
01226 {
01227 Log::error("Geometry::sortVertices() does not support DrawCalls with primitive restart enabled.\n");
01228 return false;
01229 }
01230
01231 DrawElementsUInt* de_u32 = dc->as<DrawElementsUInt>();
01232 DrawElementsUShort* de_u16 = dc->as<DrawElementsUShort>();
01233 DrawElementsUByte* de_u8 = dc->as<DrawElementsUByte>();
01234 if (de_u32)
01235 {
01236 ref<DrawElementsUInt> de = new DrawElementsUInt(de_u32->primitiveType(), de_u32->instances());
01237 de_u32_set.push_back(de);
01238 de->indexBuffer()->resize( de_u32->indexBuffer()->size() );
01239 for(unsigned int j=0; j<de_u32->indexBuffer()->size(); ++j)
01240 de->indexBuffer()->at(j) = de_u32->indexBuffer()->at(j) + de_u32->baseVertex();
01241 }
01242 else
01243 if(de_u16)
01244 {
01245 ref<DrawElementsUInt> de = new DrawElementsUInt(de_u16->primitiveType(), de_u16->instances());
01246 de_u32_set.push_back(de);
01247 de->indexBuffer()->resize( de_u16->indexBuffer()->size() );
01248 for(unsigned int j=0; j<de_u16->indexBuffer()->size(); ++j)
01249 de->indexBuffer()->at(j) = de_u16->indexBuffer()->at(j) + de_u16->baseVertex();
01250 }
01251 else
01252 if(de_u8)
01253 {
01254 ref<DrawElementsUInt> de = new DrawElementsUInt(de_u8->primitiveType(), de_u8->instances());
01255 de_u32_set.push_back(de);
01256 de->indexBuffer()->resize( de_u8->indexBuffer()->size() );
01257 for(unsigned int j=0; j<de_u8->indexBuffer()->size(); ++j)
01258 de->indexBuffer()->at(j) = de_u8->indexBuffer()->at(j) + de_u8->baseVertex();
01259 }
01260 else
01261 {
01262 Log::error("Geometry::sortVertices() supports only DrawElements* draw calls.\n");
01263 return false;
01264 }
01265 }
01266
01267
01268 drawCalls()->clear();
01269
01270
01271 std::vector<u32> map_new_to_old;
01272 map_new_to_old.resize( posarr->size() );
01273 memset(&map_new_to_old[0], 0xFF, map_new_to_old.size()*sizeof(map_new_to_old[0]));
01274
01275 std::vector<u32> map_old_to_new;
01276 map_old_to_new.resize( posarr->size() );
01277 memset(&map_old_to_new[0], 0xFF, map_old_to_new.size()*sizeof(map_old_to_new[0]));
01278
01279 std::vector<u32> used;
01280 used.resize( posarr->size() );
01281 memset(&used[0], 0, used.size()*sizeof(used[0]));
01282
01283
01284 u32 new_idx = 0;
01285 for(u32 i=0; i<de_u32_set.size(); ++i)
01286 {
01287 ArrayUInt1* index_buffer = de_u32_set[i]->indexBuffer();
01288 for(u32 idx=0; idx<index_buffer->size(); ++idx)
01289 {
01290 if (!used[index_buffer->at(idx)])
01291 {
01292 const DrawElementsUInt::index_type& old_idx = index_buffer->at(idx);
01293 map_new_to_old[new_idx] = old_idx;
01294 map_old_to_new[old_idx] = new_idx;
01295 used[old_idx] = 1;
01296 ++new_idx;
01297 }
01298 }
01299 }
01300
01301
01302 regenerateVertices(map_new_to_old);
01303
01304
01305 for(u32 i=0; i<de_u32_set.size(); ++i)
01306 {
01307 drawCalls()->push_back(de_u32_set[i].get());
01308 ArrayUInt1* index_buffer = de_u32_set[i]->indexBuffer();
01309 for(u32 j=0; j<index_buffer->size(); ++j)
01310 {
01311 index_buffer->at(j) = map_old_to_new[index_buffer->at(j)];
01312 }
01313 }
01314
01315 return true;
01316 }
01317
01318 void Geometry::colorizePrimitives()
01319 {
01320 ArrayAbstract* posarr = vertexArray() ? vertexArray() : vertexAttribArray(vl::VA_Position) ? vertexAttribArray(vl::VA_Position)->data() : NULL;
01321
01322 if (!posarr)
01323 return;
01324
01325 ref<ArrayFloat4> col = new vl::ArrayFloat4;
01326 col->resize( posarr->size() );
01327
01328 if (vertexArray())
01329 setColorArray( col.get() );
01330 else
01331 setVertexAttribArray( vl::VA_Color, col.get() );
01332
01333 for(int i=0; i<drawCalls()->size(); ++i)
01334 {
01335 fvec4 c;
01336 c.r() = rand()%100 / 99.0f;
01337 c.g() = rand()%100 / 99.0f;
01338 c.b() = rand()%100 / 99.0f;
01339 c.a() = 1.0f;
01340
01341 for(IndexIterator it=drawCalls()->at(i)->indexIterator(); it.hasNext(); it.next())
01342 col->at( it.index() ) = c;
01343 }
01344 }
01345
01346 void Geometry::computeTangentSpace(
01347 u32 vert_count,
01348 const fvec3 *vertex,
01349 const fvec3* normal,
01350 const fvec2 *texcoord,
01351 const DrawCall* prim,
01352 fvec3 *tangent,
01353 fvec3 *bitangent )
01354 {
01355 std::vector<fvec3> tan1;
01356 std::vector<fvec3> tan2;
01357 tan1.resize(vert_count);
01358 tan2.resize(vert_count);
01359
01360 for ( TriangleIterator trit = prim->triangleIterator(); trit.hasNext(); trit.next() )
01361 {
01362 int tri[] = { trit.a(), trit.b(), trit.c() };
01363
01364 VL_CHECK(tri[0] < (int)vert_count );
01365 VL_CHECK(tri[1] < (int)vert_count );
01366 VL_CHECK(tri[2] < (int)vert_count );
01367
01368 const fvec3& v1 = vertex[tri[0]];
01369 const fvec3& v2 = vertex[tri[1]];
01370 const fvec3& v3 = vertex[tri[2]];
01371
01372 const fvec2& w1 = texcoord[tri[0]];
01373 const fvec2& w2 = texcoord[tri[1]];
01374 const fvec2& w3 = texcoord[tri[2]];
01375
01376 float x1 = v2.x() - v1.x();
01377 float x2 = v3.x() - v1.x();
01378 float y1 = v2.y() - v1.y();
01379 float y2 = v3.y() - v1.y();
01380 float z1 = v2.z() - v1.z();
01381 float z2 = v3.z() - v1.z();
01382
01383 float s1 = w2.x() - w1.x();
01384 float s2 = w3.x() - w1.x();
01385 float t1 = w2.y() - w1.y();
01386 float t2 = w3.y() - w1.y();
01387
01388 float r = 1.0F / (s1 * t2 - s2 * t1);
01389 fvec3 sdir((t2 * x1 - t1 * x2) * r, (t2 * y1 - t1 * y2) * r, (t2 * z1 - t1 * z2) * r);
01390 fvec3 tdir((s1 * x2 - s2 * x1) * r, (s1 * y2 - s2 * y1) * r, (s1 * z2 - s2 * z1) * r);
01391
01392 tan1[tri[0]] += sdir;
01393 tan1[tri[1]] += sdir;
01394 tan1[tri[2]] += sdir;
01395
01396 tan2[tri[0]] += tdir;
01397 tan2[tri[1]] += tdir;
01398 tan2[tri[2]] += tdir;
01399 }
01400
01401 for ( u32 a = 0; a < vert_count; a++)
01402 {
01403 const fvec3& n = normal[a];
01404 const fvec3& t = tan1[a];
01405
01406
01407 tangent[a] = (t - n * dot(n, t)).normalize();
01408
01409 if ( bitangent )
01410 {
01411
01412 float w = (dot(cross(n, t), tan2[a]) < 0.0F) ? -1.0F : 1.0F;
01413 bitangent[a] = cross( n, tangent[a] ) * w;
01414 }
01415 }
01416 }
01417