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 #include <PVLE/Physics/GeometryHandlers.h>
00028
00029 #include <PVLE/Util/TracedException.h>
00030 #include <PVLE/Util/Util.h>
00031 #include <PVLE/Physics/Geom.h>
00032
00033
00034 #include <osg/Array>
00035 #include <osg/Vec3>
00036 #include <osg/Node>
00037 #include <osgDB/ReadFile>
00038 #include <boost/cast.hpp>
00039 #include <PVLE/3D/FindGeometriesVisitor.h>
00040 #include <PVLE/3D/Commons.h>
00041 #include <PVLE/3D/Utility3D.h>
00042
00043 namespace Physics {
00044
00045
00046 UserGeomsInitializer::UserGeomsInitializer() {
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063 }
00064
00065
00066 void MeshHandler::indexTriangles(UINT lengthPrimitive, UINT offset) {
00067 UINT max = offset + lengthPrimitive;
00068
00069 pLocalIndexArray->reserve(pLocalIndexArray->size() + lengthPrimitive);
00070 for(UINT i=offset; i<max; ++i) pLocalIndexArray->push_back(i);
00071 }
00072
00073 template<class TDrawElements>
00074 void MeshHandler::indexTriangles(const TDrawElements * pPrimitiveSet) {
00075 UINT lengthPrimitive = pPrimitiveSet->getNumIndices();
00076 pLocalIndexArray->reserve(pLocalIndexArray->size() + lengthPrimitive);
00077 for(typename TDrawElements::const_iterator itData = pPrimitiveSet->begin(), itDataEnd = pPrimitiveSet->end(); itData != itDataEnd; ++itData) pLocalIndexArray->push_back(*itData);
00078 }
00079
00080
00081 void MeshHandler::indexTriangleStrip(UINT lengthPrimitive, UINT offset) {
00082 UINT max = offset + lengthPrimitive;
00083
00084 pLocalIndexArray->reserve(pLocalIndexArray->size() + (lengthPrimitive-2)*3);
00085 bool invert = false;
00086 for(UINT i=offset+2; i<max; ++i) {
00087 pLocalIndexArray->push_back(i-2);
00088 if (invert) {
00089 pLocalIndexArray->push_back(i);
00090 pLocalIndexArray->push_back(i-1);
00091 } else {
00092 pLocalIndexArray->push_back(i-1);
00093 pLocalIndexArray->push_back(i);
00094 }
00095 invert = !invert;
00096 }
00097 }
00098
00099 template<class TDrawElements>
00100 void MeshHandler::indexTriangleStrip(const TDrawElements * pPrimitiveSet) {
00101 UINT lengthPrimitive = pPrimitiveSet->getNumIndices();
00102 pLocalIndexArray->reserve(pLocalIndexArray->size() + (lengthPrimitive-2)*3);
00103 typename TDrawElements::const_iterator
00104 itData = pPrimitiveSet->begin(),
00105 itDataEnd = pPrimitiveSet->end();
00106
00107 bool invert = false;
00108 GLuint a, b, c;
00109 ASSERT(itData != itDataEnd); a = *itData; ++itData;
00110 ASSERT(itData != itDataEnd); b = *itData; ++itData;
00111 for(; itData != itDataEnd; ++itData) {
00112 c = *itData;
00113 pLocalIndexArray->push_back(a);
00114 if (invert) {
00115 pLocalIndexArray->push_back(c);
00116 pLocalIndexArray->push_back(b);
00117 } else {
00118 pLocalIndexArray->push_back(b);
00119 pLocalIndexArray->push_back(c);
00120 }
00121 invert = !invert;
00122 a=b; b=c;
00123 }
00124 }
00125
00126
00127 void MeshHandler::indexTriangleFan(UINT lengthPrimitive, UINT offset) {
00128 UINT max = offset + lengthPrimitive;
00129
00130 pLocalIndexArray->reserve(pLocalIndexArray->size() + (lengthPrimitive-1)*3);
00131 for(UINT i=offset+2; i<max; ++i) {
00132 pLocalIndexArray->push_back(0);
00133 pLocalIndexArray->push_back(i-1);
00134 pLocalIndexArray->push_back(i);
00135 }
00136 }
00137
00138 template<class TDrawElements>
00139 void MeshHandler::indexTriangleFan(const TDrawElements * pPrimitiveSet) {
00140 UINT lengthPrimitive = pPrimitiveSet->getNumIndices();
00141 pLocalIndexArray->reserve(pLocalIndexArray->size() + (lengthPrimitive-1)*3);
00142
00143 typename TDrawElements::const_iterator
00144 itData = pPrimitiveSet->begin(),
00145 itDataEnd = pPrimitiveSet->end();
00146
00147 GLuint o, prev, cur;
00148 ASSERT(itData != itDataEnd); o = *itData; ++itData;
00149 ASSERT(itData != itDataEnd); prev = *itData; ++itData;
00150 for(; itData != itDataEnd; ++itData) {
00151 cur = *itData;
00152 pLocalIndexArray->push_back(o);
00153 pLocalIndexArray->push_back(prev);
00154 pLocalIndexArray->push_back(cur);
00155 prev=cur;
00156 }
00157 }
00158
00159 void MeshHandler::indexQuads(UINT lengthPrimitive, UINT offset) {
00160 UINT max = offset + lengthPrimitive;
00161
00162 pLocalIndexArray->reserve(pLocalIndexArray->size() + lengthPrimitive*6/4);
00163 for(UINT i=offset; i<max; i+=4) {
00164 pLocalIndexArray->push_back(i);
00165 pLocalIndexArray->push_back(i+1);
00166 pLocalIndexArray->push_back(i+2);
00167
00168 pLocalIndexArray->push_back(i);
00169 pLocalIndexArray->push_back(i+2);
00170 pLocalIndexArray->push_back(i+3);
00171 }
00172 }
00173
00174 template<class TDrawElements>
00175 void MeshHandler::indexQuads(const TDrawElements * pPrimitiveSet) {
00176 UINT lengthPrimitive = pPrimitiveSet->getNumIndices();
00177 pLocalIndexArray->reserve(pLocalIndexArray->size() + lengthPrimitive*6/4);
00178
00179 typename TDrawElements::const_iterator
00180 itData = pPrimitiveSet->begin(),
00181 itDataEnd = pPrimitiveSet->end();
00182
00183 GLuint a, b, c, d;
00184 for(; itData != itDataEnd; ) {
00185 a = *itData; ++itData;
00186 ASSERT(itData != itDataEnd); b = *itData; ++itData;
00187 ASSERT(itData != itDataEnd); c = *itData; ++itData;
00188 ASSERT(itData != itDataEnd); d = *itData; ++itData;
00189
00190 pLocalIndexArray->push_back(a);
00191 pLocalIndexArray->push_back(b);
00192 pLocalIndexArray->push_back(c);
00193
00194 pLocalIndexArray->push_back(a);
00195 pLocalIndexArray->push_back(c);
00196 pLocalIndexArray->push_back(d);
00197 }
00198 }
00199
00200
00201 void MeshHandler::indexQuadStrip(UINT lengthPrimitive, UINT offset) {
00202 UINT max = offset + lengthPrimitive;
00203
00204 pLocalIndexArray->reserve(pLocalIndexArray->size() + (lengthPrimitive-2)*3);
00205 for(UINT i=offset+3; i<max; i+=2) {
00206 pLocalIndexArray->push_back(i-3);
00207 pLocalIndexArray->push_back(i-2);
00208 pLocalIndexArray->push_back(i);
00209
00210 pLocalIndexArray->push_back(i-3);
00211 pLocalIndexArray->push_back(i);
00212 pLocalIndexArray->push_back(i-1);
00213 }
00214 }
00215
00216 template<class TDrawElements>
00217 void MeshHandler::indexQuadStrip(const TDrawElements * pPrimitiveSet) {
00218 UINT lengthPrimitive = pPrimitiveSet->getNumIndices();
00219 pLocalIndexArray->reserve(pLocalIndexArray->size() + (lengthPrimitive-2)*3);
00220
00221 typename TDrawElements::const_iterator
00222 itData = pPrimitiveSet->begin(),
00223 itDataEnd = pPrimitiveSet->end();
00224
00225 GLuint a, b, c, d;
00226 ASSERT(itData != itDataEnd); a = *itData; ++itData;
00227 ASSERT(itData != itDataEnd); b = *itData; ++itData;
00228 for(; itData != itDataEnd; ) {
00229 c = *itData; ++itData;
00230 ASSERT(itData != itDataEnd); d = *itData; ++itData;
00231
00232 pLocalIndexArray->push_back(a);
00233 pLocalIndexArray->push_back(b);
00234 pLocalIndexArray->push_back(d);
00235
00236 pLocalIndexArray->push_back(a);
00237 pLocalIndexArray->push_back(d);
00238 pLocalIndexArray->push_back(c);
00239
00240 a = c; b = d;
00241 }
00242 }
00243
00244
00245 template <class TDrawElements>
00246 void MeshHandler::indexByType(const osg::PrimitiveSet * pPrimitiveSet) {
00247 const TDrawElements * pCastPrimitive = boost::polymorphic_downcast<const TDrawElements *>(pPrimitiveSet);
00248 switch(pCastPrimitive->getMode()) {
00249 case osg::PrimitiveSet::TRIANGLES: indexTriangles<TDrawElements>(pCastPrimitive); break;
00250 case osg::PrimitiveSet::TRIANGLE_STRIP: indexTriangleStrip<TDrawElements>(pCastPrimitive); break;
00251 case osg::PrimitiveSet::TRIANGLE_FAN: indexTriangleFan<TDrawElements>(pCastPrimitive); break;
00252 case osg::PrimitiveSet::QUADS: indexQuads<TDrawElements>(pCastPrimitive); break;
00253 case osg::PrimitiveSet::QUAD_STRIP: indexQuadStrip<TDrawElements>(pCastPrimitive); break;
00254 default: THROW_TRACED_EXCEPTION("Unsupported primitive mode for physics (Handles only triangles (list/strip/fan) and quads (list/strip), not points or lines)");
00255 }
00256 }
00257
00258
00259
00260 dGeomID MeshHandler::create(dSpaceID spaceId) {
00261
00262 const osg::Array * pV = pGeo->getVertexArray();
00263 const TIndexArray *pI = boost::polymorphic_downcast<const TIndexArray *>(pGeo->getVertexIndices());
00264 const osg::Array * pN = pGeo->getNormalArray();
00265
00266
00267 ASSERT(pV->getType() == osg::Array::Vec3ArrayType);
00268
00269
00270 if (pGeo->getNormalBinding() == osg::Geometry::BIND_PER_PRIMITIVE) {
00271
00273 LOG_NOTICE << "NOT IMPLMENTED : Normal data is BIND_PER_PRIMITIVE. Fallback to autocompute." << std::endl;
00274 pN = NULL;
00275 } else if (pGeo->getNormalBinding() == osg::Geometry::BIND_PER_VERTEX) {
00276
00278 LOG_NOTICE << "NOT IMPLMENTED : Normal data is BIND_PER_VERTEX. Fallback to autocompute." << std::endl;
00279 pN = NULL;
00280 } else {
00281 LOG_NOTICE << "Normal data is unuseable for physics (not BIND_PER_VERTEX or BIND_BY_PRIMITIVE). Using no normal data." << std::endl;
00282 pN = NULL;
00283 }
00284 if (!pN) LOG_WARN << "[Performance warning] Normal data is unavailable for physics. Fallback to auto-computation by physics engine (will compute each time necessary)." << std::endl;
00285
00286 ASSERT(!pN || pN->getType() == osg::Array::Vec3ArrayType);
00287
00288
00289
00290
00291 if (pI) THROW_TRACED_EXCEPTION("DEV ONLY : Direct index array is encountered (not implemented).");
00292
00293 LOG_INFO << "Direct index data unavailable for physics. Rebuilding." << std::endl;
00294 if (pGeo->getNumPrimitiveSets() == 0) THROW_TRACED_EXCEPTION("No primitive found");
00295
00296 pLocalIndexArray = new TIndexArray;
00297 pI = boost::polymorphic_downcast<const TIndexArray *>(pLocalIndexArray.get());
00298
00299 UINT nbVertex = pV->getNumElements();
00300
00301 osg::Geometry::PrimitiveSetList::const_iterator
00302 it = pGeo->getPrimitiveSetList().begin(),
00303 itEnd = pGeo->getPrimitiveSetList().end();
00304 for(; it != itEnd; ++it) {
00305
00306 osg::PrimitiveSet::Type primType = (*it)->getType();
00307
00308
00309
00310
00311 if (primType == osg::PrimitiveSet::DrawElementsUIntPrimitiveType) indexByType<osg::DrawElementsUInt>(it->get());
00312 else if (primType == osg::PrimitiveSet::DrawElementsUShortPrimitiveType) indexByType<osg::DrawElementsUShort>(it->get());
00313 else if (primType == osg::PrimitiveSet::DrawElementsUBytePrimitiveType) indexByType<osg::DrawElementsUByte>(it->get());
00314 else {
00315
00316
00317 void (MeshHandler::* indexFunc)(UINT, UINT) = NULL;
00318 switch((*it)->getMode()) {
00319 case osg::PrimitiveSet::TRIANGLES: indexFunc = &MeshHandler::indexTriangles; break;
00320 case osg::PrimitiveSet::TRIANGLE_STRIP: indexFunc = &MeshHandler::indexTriangleStrip; break;
00321 case osg::PrimitiveSet::TRIANGLE_FAN: indexFunc = &MeshHandler::indexTriangleFan; break;
00322 case osg::PrimitiveSet::QUADS: indexFunc = &MeshHandler::indexQuads; break;
00323 case osg::PrimitiveSet::QUAD_STRIP: indexFunc = &MeshHandler::indexQuadStrip; break;
00324 default: THROW_TRACED_EXCEPTION("Unsupported primitive mode for physics (Handles only triangles and quad, not points or lines)");
00325 }
00326
00327 if (primType == osg::PrimitiveSet::DrawArraysPrimitiveType) {
00328 THROW_TRACED_EXCEPTION("Implementation needs testing : never encountered case");
00329
00330
00331 (this->*indexFunc)(nbVertex, 0);
00332 }
00333 else if (primType == osg::PrimitiveSet::DrawArrayLengthsPrimitiveType) {
00334
00335
00336
00337 GLsizei offset = 0;
00338 osg::DrawArrayLengths::const_iterator
00339 itData = boost::polymorphic_downcast<const osg::DrawArrayLengths *>(it->get())->begin(),
00340 itDataEnd = boost::polymorphic_downcast<const osg::DrawArrayLengths *>(it->get())->end();
00341 for(; itData != itDataEnd; ++itData) {
00342 (this->*indexFunc)(*itData, offset);
00343 offset += *itData;
00344 }
00345 }
00346 else THROW_TRACED_EXCEPTION("Unknown primitive type");
00347
00348 }
00349 }
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367 #ifdef dSINGLE
00368 dGeomTriMeshDataBuildSingle1(
00369 #else
00370 dGeomTriMeshDataBuildDouble1(
00371 #endif
00372 meshDataId,
00373
00374 pV->getDataPointer(), pV->getTotalDataSize() / pV->getNumElements(), pV->getNumElements(),
00375 pI->getDataPointer(), pI->getNumElements(), pI->getDataSize()*3,
00376 pN ? pN->getDataPointer() : NULL );
00377
00378
00379 id = dCreateTriMesh(spaceId, meshDataId, NULL, NULL, NULL);
00380 return id;
00381 }
00382
00383
00384 MeshHandler::MeshHandler(osg::Node * pModel) : pGeo(NULL), pLocalIndexArray(NULL) {
00385 meshDataId = dGeomTriMeshDataCreate();
00386
00387 FindGeometriesVisitor v;
00388 pModel->accept(v);
00389 if (v.vFoundGeometries.size() < 1) THROW_TRACED_EXCEPTION("Geometry not found in the given node file.");
00390 pOwnGeo = new osg::Geometry(*v.vFoundGeometries[0], osg::CopyOp::DEEP_COPY_ALL);
00391 pGeo = pOwnGeo.get();
00392 }
00393
00394
00395 MeshHandler::MeshHandler(const osg::HeightField * pGfxHeightField) : pGeo(NULL), pLocalIndexArray(NULL) {
00396 meshDataId = dGeomTriMeshDataCreate();
00397
00398 pOwnGeo = new osg::Geometry;
00399 pGeo = pOwnGeo.get();
00400
00401
00402 typedef osg::TemplateArray< osg::Vec3f, osg::Array::Vec3ArrayType, sizeof(osg::Vec3f), GL_FLOAT > TVertexArray;
00403 typedef osg::TemplateArray< osg::Vec3f, osg::Array::Vec3ArrayType, sizeof(osg::Vec3f), GL_FLOAT > TNormalArray;
00404 TVertexArray * pV = new TVertexArray;
00405
00406 TNormalArray * pN = new TNormalArray;
00407
00408 pOwnGeo->setVertexArray(pV);
00409
00410 pOwnGeo->setNormalArray(pN);
00411
00412 UINT c, r = 0;
00413 const UINT nbCols = pGfxHeightField->getNumColumns(), nbRows = pGfxHeightField->getNumRows();
00414
00415 osg::DrawElementsUInt * pPS = new osg::DrawElementsUInt(osg::PrimitiveSet::TRIANGLES);
00416 pOwnGeo->addPrimitiveSet(pPS);
00417
00418 pV->reserve(nbCols * nbRows);
00419
00420 pPS->reserve((nbCols-1) * (nbRows-1) * 6);
00421 pN->reserve((nbCols-1) * (nbRows-1));
00422
00423
00424
00425
00426
00427 for(r=0; r<nbRows; ++r) {
00428 for(c=0; c<nbCols; ++c) {
00429 #ifdef PHY_DEBUG_HEIGHT_FIELD
00430 osg::Vec3 debugHFVec = pGfxHeightField->getVertex(c, r);
00431 debugHFVec._v[2] = 0;
00432 pV->push_back(debugHFVec);
00433 #else
00434 pV->push_back(pGfxHeightField->getVertex(c, r));
00435 #endif
00436 }
00437 }
00438
00439
00440 pOwnGeo->setNormalBinding(osg::Geometry::BIND_PER_PRIMITIVE);
00441
00442 #define V(r,c) ((r)*nbCols + (c)) // Not optimized, but clear...
00443
00444 osg::Vec3 v0, v1, v2, v3;
00445 for(r=1; r<nbRows; ++r) {
00446 for(c=1; c<nbCols; ++c) {
00447
00448 pPS->push_back(V(r-1, c-1));
00449 pPS->push_back(V(r-1, c));
00450 pPS->push_back(V(r, c-1));
00451
00452 pPS->push_back(V(r, c-1));
00453 pPS->push_back(V(r-1, c));
00454 pPS->push_back(V(r, c));
00455
00456 #ifdef PHY_DEBUG_HEIGHT_FIELD
00457 pN->push_back(osg::Vec3(0,0,1));
00458 pN->push_back(osg::Vec3(0,0,1));
00459 #else
00460
00461 v0 = pGfxHeightField->getVertex(c-1, r-1);
00462 v1 = pGfxHeightField->getVertex(c, r-1);
00463 v2 = pGfxHeightField->getVertex(c-1, r);
00464 v3 = pGfxHeightField->getVertex(c, r);
00465 pN->push_back((v1-v0) ^ (v2-v0));
00466 pN->push_back((v1-v3) ^ (v2-v3));
00467
00468
00469
00470
00471
00472
00474
00475
00476 #endif
00477 }
00478 }
00479
00480 }
00481
00482
00483 UINT MeshHandler::getADOverrideFlag() { return AD_STEPS | AD_SAMPLES_COUNT | AD_LINEAR | AD_ANGULAR; }
00484
00485 UINT MeshHandler::getADSteps() { return 10; }
00486 UINT MeshHandler::getADSamplesCount() { return 5; }
00487 dReal MeshHandler::getADLinearThreshold() { return .1; }
00488 dReal MeshHandler::getADAngularThreshold() { return .1; }
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567 HeightFieldHandler::HeightFieldHandler(const osg::HeightField * pGfxHeightField, float thickness, const graphVec3 & offset_from_graph, bool bWarp)
00568 : bPlaceable(true), scale(1), offset(0), thickness(thickness), bWarp(bWarp), idHF(0)
00569 {
00570 widthSamples = pGfxHeightField->getNumColumns();
00571 depthSamples = pGfxHeightField->getNumRows();
00572 ASSERT(widthSamples>0);
00573 ASSERT(depthSamples>0);
00574 width = pGfxHeightField->getXInterval() * (widthSamples-1);
00575 depth = pGfxHeightField->getYInterval() * (depthSamples-1);
00576
00577 pData = new float[widthSamples*depthSamples];
00578 idHFData = dGeomHeightfieldDataCreate();
00579
00580
00581 UINT c,r;
00582 for(c=0; c<widthSamples; ++c) {
00583 for(r=0; r<depthSamples; ++r) {
00584 pData[c*widthSamples + r] = pGfxHeightField->getVertex(c, r).z();
00585 }
00586 }
00587
00588 graphVec3 origin = pGfxHeightField->getOrigin();
00589 origin.z() = 0;
00590 toPhyVec3(origin + offset_from_graph + graphVec3(width/2, depth/2, 0), pos);
00591 toPhyQuat(pGfxHeightField->getRotation(), rot);
00592 }
00593
00594
00595 HeightFieldHandler::HeightFieldHandler(const HeightFieldHandler & hf)
00596 : bPlaceable(hf.bPlaceable), scale(hf.scale), offset(hf.offset), thickness(hf.thickness), bWarp(hf.bWarp),
00597 widthSamples(hf.widthSamples), depthSamples(hf.depthSamples), width(hf.width), depth(hf.depth),
00598 idHF(0)
00599 {
00600 ASSERT(widthSamples>0);
00601 ASSERT(depthSamples>0);
00602
00603 pData = new float[widthSamples*depthSamples];
00604 idHFData = dGeomHeightfieldDataCreate();
00605
00606 memcpy(pData, hf.pData, widthSamples*depthSamples*sizeof(float));
00607
00608 pos[0] = hf.pos[0];
00609 pos[1] = hf.pos[1];
00610 pos[2] = hf.pos[2];
00611 pos[3] = hf.pos[3];
00612
00613 rot[0] = hf.rot[0];
00614 rot[1] = hf.rot[1];
00615 rot[2] = hf.rot[2];
00616 rot[3] = hf.rot[3];
00617 }
00618
00619
00620 dGeomID HeightFieldHandler::create(dSpaceID spaceId) {
00621
00622
00623
00624 dGeomHeightfieldDataBuildSingle(idHFData, pData, 0, width, depth, widthSamples, depthSamples, scale, offset, thickness, bWarp ? 1 : 0);
00625
00626
00627
00628
00629
00630 idHF = dCreateHeightfield(0, idHFData, bPlaceable ? 1 : 0);
00631
00632
00633 dMatrix3 R;
00634 graphQuat q(osg::PI_2, osg::X_AXIS);
00635 q *= graphQuat(osg::PI_2, osg::Z_AXIS);
00636 graphMat r(q * toGraphQuat(rot));
00637 toPhyMatRotation(r, R);
00638 dGeomSetRotation(idHF, R);
00639 dGeomSetPosition(idHF, pos[0], pos[1], pos[2]);
00640
00641
00642 id = dCreateGeomTransform(spaceId);
00643 dGeomTransformSetCleanup(id, 0);
00644 dGeomTransformSetInfo(id, 1);
00645 dGeomTransformSetGeom(id, idHF);
00646
00647 return id;
00648 }
00649
00650
00651 }