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 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
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
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
00335
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
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
00359 if (vertexArray())
00360 setNormalArray( norm3f.get() );
00361 else
00362 setVertexAttribArray(VA_Normal, norm3f.get());
00363
00364
00365 for(u32 i=0; i<norm3f->size(); ++i)
00366 (*norm3f)[i] = 0;
00367
00368
00369 for(int prim=0; prim<(int)drawCalls()->size(); prim++)
00370 {
00371
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
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
00497
00498 bool vbo_on = Has_BufferObject && isBufferObjectEnabled() && !isDisplayListEnabled();
00499 gl_context->bindVAS(this, vbo_on, false);
00500
00501
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
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
00573 de_vector.push_back( deb );
00574 drawCalls()->eraseAt(i);
00575 }
00576 }
00577
00578 std::reverse(de_vector.begin(), de_vector.end());
00579
00580
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
00592 if ( index_count % 2 )
00593 indices.push_back( indices.back() );
00594
00595
00596 if ( i != de_vector.size()-1 )
00597 {
00598
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
00638 mergendo_calls.push_back( drawCalls()->at(i) );
00639 drawCalls()->eraseAt(i);
00640 }
00641 }
00642
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
00656 de_prim_restart->indexBuffer()->resize(total_index_count + mergendo_calls.size()-1);
00657 GLuint* index = de_prim_restart->indexBuffer()->begin();
00658
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
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
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
00712 de_multi->indexBuffer()->resize(total_index_count);
00713 GLuint* index = de_multi->indexBuffer()->begin();
00714
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
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
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
00757 mergendo_calls.insert( mergendo_calls.begin(), drawCalls()->at(i) );
00758 drawCalls()->eraseAt(i);
00759 }
00760 }
00761
00762 std::reverse(mergendo_calls.begin(), mergendo_calls.end());
00763
00764 if (mergendo_calls.empty())
00765 return;
00766
00767
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
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
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
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
00833 mergendo_calls.insert( mergendo_calls.begin(), drawCalls()->at(i) );
00834 drawCalls()->eraseAt(i);
00835 }
00836
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
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
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
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
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
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
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
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
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
01000 de->setPrimitiveRestartEnabled( dc->primitiveRestartEnabled() );
01001
01002 de->setBaseVertex( dc->as<DrawElementsBase>()->baseVertex() );
01003
01004 de->indexBuffer()->resize( idx_count );
01005 u32 i=0;
01006 for( vl::IndexIterator it = dc->indexIterator(); it.hasNext(); ++it, ++i )
01007 {
01008
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
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
01026 de->setPrimitiveRestartEnabled( dc->primitiveRestartEnabled() );
01027
01028 de->setBaseVertex( dc->as<DrawRangeElementsBase>()->baseVertex() );
01029
01030 de->setRangeStart( dc->as<DrawRangeElementsBase>()->rangeStart() );
01031 de->setRangeEnd( dc->as<DrawRangeElementsBase>()->rangeEnd() );
01032
01033 de->indexBuffer()->resize( idx_count );
01034 u32 i=0;
01035 for( vl::IndexIterator it = dc->indexIterator(); it.hasNext(); ++it, ++i )
01036 {
01037
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
01045 (*drawCalls())[idraw] = de;
01046 }
01047 else
01048 if (dc->isOfType(MultiDrawElementsBase::Type()))
01049 {
01050 ref<MultiDrawElementsUByte> de = new MultiDrawElementsUByte( dc->primitiveType() );
01051
01052 de->indexBuffer()->resize( idx_count );
01053 u32 i=0;
01054 for( vl::IndexIterator it = dc->indexIterator(); it.hasNext(); ++it, ++i )
01055 {
01056
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
01064 de->setPrimitiveRestartEnabled( dc->primitiveRestartEnabled() );
01065
01066 de->setBaseVertices( dc->as<MultiDrawElementsBase>()->baseVertices() );
01067
01068 de->setCountVector( dc->as<MultiDrawElementsBase>()->countVector() );
01069
01070 (*drawCalls())[idraw] = de;
01071 }
01072 }
01073 else
01074
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
01081 de->setPrimitiveRestartEnabled( dc->primitiveRestartEnabled() );
01082
01083 de->setBaseVertex( dc->as<DrawElementsBase>()->baseVertex() );
01084
01085 de->indexBuffer()->resize( idx_count );
01086 u32 i=0;
01087 for( vl::IndexIterator it = dc->indexIterator(); it.hasNext(); ++it, ++i )
01088 {
01089
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
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
01107 de->setPrimitiveRestartEnabled( dc->primitiveRestartEnabled() );
01108
01109 de->setBaseVertex( dc->as<DrawRangeElementsBase>()->baseVertex() );
01110
01111 de->setRangeStart( dc->as<DrawRangeElementsBase>()->rangeStart() );
01112 de->setRangeEnd( dc->as<DrawRangeElementsBase>()->rangeEnd() );
01113
01114 de->indexBuffer()->resize( idx_count );
01115 u32 i=0;
01116 for( vl::IndexIterator it = dc->indexIterator(); it.hasNext(); ++it, ++i )
01117 {
01118
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
01126 (*drawCalls())[idraw] = de;
01127 }
01128 else
01129 if (dc->isOfType(MultiDrawElementsBase::Type()))
01130 {
01131 ref<MultiDrawElementsUShort> de = new MultiDrawElementsUShort( dc->primitiveType() );
01132
01133 de->indexBuffer()->resize( idx_count );
01134 u32 i=0;
01135 for( vl::IndexIterator it = dc->indexIterator(); it.hasNext(); ++it, ++i )
01136 {
01137
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
01145 de->setPrimitiveRestartEnabled( dc->primitiveRestartEnabled() );
01146
01147 de->setBaseVertices( dc->as<MultiDrawElementsBase>()->baseVertices() );
01148
01149 de->setCountVector( dc->as<MultiDrawElementsBase>()->countVector() );
01150
01151 (*drawCalls())[idraw] = de;
01152 }
01153 }
01154
01155 }
01156 }
01157
01158 void Geometry::makeGLESFriendly()
01159 {
01160
01161 #if defined(VL_OPENGL_ES2)
01162 convertToVertexAttribs();
01163 #endif
01164
01165
01166 triangulateDrawCalls();
01167
01168
01169 shrinkDrawCalls();
01170
01171
01172 for(int i=0; i<drawCalls()->size(); ++i)
01173 {
01174 DrawCall* dc = drawCalls()->at(i);
01175
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
01217
01218 std::vector< ref<DrawElementsUInt> > de_u32_set;
01219
01220
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();
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();
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();
01258 }
01259 else
01260 {
01261 Log::error("Geometry::sortVertices() supports only DrawElements* draw calls.\n");
01262 return false;
01263 }
01264 }
01265
01266
01267 drawCalls()->clear();
01268
01269
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]));
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]));
01277
01278 std::vector<u32> used;
01279 used.resize( posarr->size() );
01280 memset(&used[0], 0, used.size()*sizeof(used[0]));
01281
01282
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
01301 regenerateVertices(map_new_to_old);
01302
01303
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
01406 tangent[a] = (t - n * dot(n, t)).normalize();
01407
01408 if ( bitangent )
01409 {
01410
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