MezzanineEngine 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
collisionshapemanager.cpp
1 // © Copyright 2010 - 2014 BlackTopp Studios Inc.
2 /* This file is part of The Mezzanine Engine.
3 
4  The Mezzanine Engine is free software: you can redistribute it and/or modify
5  it under the terms of the GNU General Public License as published by
6  the Free Software Foundation, either version 3 of the License, or
7  (at your option) any later version.
8 
9  The Mezzanine Engine is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  GNU General Public License for more details.
13 
14  You should have received a copy of the GNU General Public License
15  along with The Mezzanine Engine. If not, see <http://www.gnu.org/licenses/>.
16 */
17 /* The original authors have included a copy of the license specified above in the
18  'Docs' folder. See 'gpl.txt'
19 */
20 /* We welcome the use of the Mezzanine engine to anyone, including companies who wish to
21  Build professional software and charge for their product.
22 
23  However there are some practical restrictions, so if your project involves
24  any of the following you should contact us and we will try to work something
25  out:
26  - DRM or Copy Protection of any kind(except Copyrights)
27  - Software Patents You Do Not Wish to Freely License
28  - Any Kind of Linking to Non-GPL licensed Works
29  - Are Currently In Violation of Another Copyright Holder's GPL License
30  - If You want to change our code and not add a few hundred MB of stuff to
31  your distribution
32 
33  These and other limitations could cause serious legal problems if you ignore
34  them, so it is best to simply contact us or the Free Software Foundation, if
35  you have any questions.
36 
37  Joseph Toppi - toppij@gmail.com
38  John Blackwood - makoenergy02@gmail.com
39 */
40 #ifndef _collisionshapemanager_cpp
41 #define _collisionshapemanager_cpp
42 
43 #include "Physics/collisionshapemanager.h"
44 #include "Graphics/mesh.h"
45 #include "Graphics/meshmanager.h"
46 #include "resourcemanager.h"
47 
48 #include "Physics/collisionshape.h"
49 #include "Physics/boxcollisionshape.h"
50 #include "Physics/capsulecollisionshape.h"
51 #include "Physics/conecollisionshape.h"
52 #include "Physics/convexhullcollisionshape.h"
53 #include "Physics/cylindercollisionshape.h"
54 #include "Physics/multispherecollisionshape.h"
55 #include "Physics/spherecollisionshape.h"
56 #include "Physics/dynamicmeshcollisionshape.h"
57 #include "Physics/heightfieldcollisionshape.h"
58 #include "Physics/planecollisionshape.h"
59 #include "Physics/softcollisionshape.h"
60 #include "Physics/staticmeshcollisionshape.h"
61 #include "Physics/compoundcollisionshape.h"
62 
63 // For logging
64 #include "stringtool.h"
65 #include "entresol.h"
66 
67 #include <Ogre.h>
68 #include "btBulletDynamicsCommon.h"
69 #include "BulletSoftBody/btSoftRigidDynamicsWorld.h"
70 #include "BulletCollision/CollisionShapes/btShapeHull.h"
71 #include "BulletCollision/Gimpact/btGImpactShape.h"
72 #include "ConvexBuilder.h"
73 #include "Internal/decompinterface.h.cpp"
74 #include <btBulletWorldImporter.h>
75 
76 #include <fstream>
77 
78 namespace Mezzanine
79 {
80  template<> Physics::CollisionShapeManager* Singleton<Physics::CollisionShapeManager>::SingletonPtr = NULL;
81 
82  namespace Physics
83  {
84  //template<> CollisionShapeManager* Singleton<CollisionShapeManager>::SingletonPtr = NULL;
85 
87  {
88  }
89 
91  {
92  /// @todo This class currently doesn't initialize anything from XML, if that changes this constructor needs to be expanded.
93  }
94 
96  {
97  this->Deinitialize();
98  this->DestroyAllShapes();
99  }
100 
101  btTriangleMesh* CollisionShapeManager::CreateBulletTrimesh(Graphics::Mesh* ObjectMesh, bool UseAllSubmeshes)
102  {
103  Ogre::MeshPtr myMesh = ObjectMesh->_GetInternalMesh();
104  Ogre::SubMesh* subMesh = NULL;
105  Ogre::IndexData* IndexData = NULL;
106  Ogre::VertexData* VertexData = NULL;
107  bool use32bitindexes = false;
108  unsigned int triCount = 0;
109  unsigned int vCount = 0;
110  unsigned int iCount = 0;
111  Whole VertPrevSize = 0;
112  Whole IndiPrevSize = 0;
113  Ogre::Vector3* vertices = NULL;
114  unsigned long* indices = NULL;
115  bool SharedVerts = myMesh->getSubMesh(0)->useSharedVertices;
116 
117  if(UseAllSubmeshes)
118  {
119  for( Whole X = 0 ; X < myMesh->getNumSubMeshes() ; X++ )
120  {
121  vCount += SharedVerts ? myMesh->sharedVertexData->vertexCount : myMesh->getSubMesh(X)->vertexData->vertexCount;
122  iCount += myMesh->getSubMesh(X)->indexData->indexCount;
123  }
124  }else{
125  vCount += SharedVerts ? myMesh->sharedVertexData->vertexCount : myMesh->getSubMesh(0)->vertexData->vertexCount;
126  iCount += myMesh->getSubMesh(0)->indexData->indexCount;
127  }
128 
129  vertices = new Ogre::Vector3[vCount];
130  indices = new unsigned long[iCount];
131 
132  // Get the submesh and associated data
133  for( unsigned short int SubMeshIndex = 0 ; SubMeshIndex < myMesh->getNumSubMeshes() ; SubMeshIndex++ )
134  {
135  if( !UseAllSubmeshes && ( SubMeshIndex > 0 ) )
136  break;
137  if( SharedVerts && (SubMeshIndex > 0) )
138  break;
139 
140  subMesh = myMesh->getSubMesh(SubMeshIndex);
141  IndexData = subMesh->indexData;
142  VertexData = SharedVerts ? myMesh->sharedVertexData : myMesh->getSubMesh(SubMeshIndex)->vertexData;
143 
144  // Get the position element
145  const Ogre::VertexElement* posElem = VertexData->vertexDeclaration->findElementBySemantic(Ogre::VES_POSITION);
146  // Get a pointer to the vertex buffer
147  Ogre::HardwareVertexBufferSharedPtr vBuffer = VertexData->vertexBufferBinding->getBuffer(posElem->getSource());
148  // Get a pointer to the index buffer
149  Ogre::HardwareIndexBufferSharedPtr iBuffer = IndexData->indexBuffer;
150  // Get the number of triangles
151  triCount += ( IndexData->indexCount / 3 );
152 
153  // Lock the vertex buffer (READ ONLY)
154  unsigned char* vertex = static_cast<unsigned char*>(vBuffer->lock(Ogre::HardwareBuffer::HBL_READ_ONLY));
155  float* pReal = NULL;
156  for (size_t j = 0; j < VertexData->vertexCount; ++j, vertex += vBuffer->getVertexSize() )
157  {
158  posElem->baseVertexPointerToElement(vertex, &pReal);
159  Ogre::Vector3 pt(pReal[0], pReal[1], pReal[2]);
160  vertices[j + VertPrevSize] = pt;
161  }
162  vBuffer->unlock();
163  size_t index_offset = 0;
164  use32bitindexes = (iBuffer->getType() == Ogre::HardwareIndexBuffer::IT_32BIT);
165 
166  // Lock the index buffer (READ ONLY)
167  unsigned long* pLong = static_cast<unsigned long*>(iBuffer->lock(Ogre::HardwareBuffer::HBL_READ_ONLY));
168  unsigned short* pShort = reinterpret_cast<unsigned short*>(pLong);
169 
170  if( use32bitindexes )
171  {
172  for (size_t k = 0; k < triCount*3; ++k)
173  {
174  indices[index_offset+IndiPrevSize] = pLong[k];
175  index_offset++;
176  }
177  }else{
178  for (size_t k = 0; k < triCount*3; ++k)
179  {
180  indices[index_offset+IndiPrevSize] = static_cast<unsigned long>(pShort[k]);
181  index_offset++;
182  }
183  }
184  iBuffer->unlock();
185 
186  VertPrevSize+=VertexData->vertexCount;
187  IndiPrevSize+=IndexData->indexCount;
188  }
189 
190  // We now have vertices and indices ready to go
191 
192  // The Bullet triangle mesh
193  btTriangleMesh* trimesh = new btTriangleMesh(use32bitindexes);
194 
195  // Setup the tri mesh
196  btVector3 vert0, vert1, vert2;
197  int i=0;
198 
199  // For every triangle
200  for (unsigned int y=0; y<triCount; y++)
201  {
202  // Set each vertex
203  vert0.setValue(vertices[indices[i]].x, vertices[indices[i]].y, vertices[indices[i]].z);
204  vert1.setValue(vertices[indices[i+1]].x, vertices[indices[i+1]].y, vertices[indices[i+1]].z);
205  vert2.setValue(vertices[indices[i+2]].x, vertices[indices[i+2]].y, vertices[indices[i+2]].z);
206 
207  // Add it into the trimesh
208  trimesh->addTriangle(vert0, vert1, vert2);
209 
210  // Increase index count
211  i+=3;
212  }
213  delete[] vertices;
214  delete[] indices;
215 
216  return trimesh;
217  }
218 
219  CollisionShape* CollisionShapeManager::WrapShape(const String& Name, btCollisionShape* InternalShape)
220  {
221  switch(InternalShape->getShapeType())
222  {
223  case BOX_SHAPE_PROXYTYPE:
224  {
225  BoxCollisionShape* BoxShape = new BoxCollisionShape(Name,(btBoxShape*)InternalShape);
226  return BoxShape;
227  break;
228  }
229  case CAPSULE_SHAPE_PROXYTYPE:
230  {
231  CapsuleCollisionShape* CapsuleShape = new CapsuleCollisionShape(Name,(btCapsuleShape*)InternalShape);
232  return CapsuleShape;
233  break;
234  }
235  case CONE_SHAPE_PROXYTYPE:
236  {
237  ConeCollisionShape* ConeShape = new ConeCollisionShape(Name,(btConeShape*)InternalShape);
238  return ConeShape;
239  break;
240  }
241  case CONVEX_HULL_SHAPE_PROXYTYPE:
242  {
243  ConvexHullCollisionShape* ConvexHullShape = new ConvexHullCollisionShape(Name,(btConvexHullShape*)InternalShape);
244  return ConvexHullShape;
245  break;
246  }
247  case CYLINDER_SHAPE_PROXYTYPE:
248  {
249  CylinderCollisionShape* CylinderShape = new CylinderCollisionShape(Name,(btCylinderShape*)InternalShape);
250  return CylinderShape;
251  break;
252  }
253  case MULTI_SPHERE_SHAPE_PROXYTYPE:
254  {
255  MultiSphereCollisionShape* MultiSphereShape = new MultiSphereCollisionShape(Name,(btMultiSphereShape*)InternalShape);
256  return MultiSphereShape;
257  break;
258  }
259  case SPHERE_SHAPE_PROXYTYPE:
260  {
261  SphereCollisionShape* SphereShape = new SphereCollisionShape(Name,(btSphereShape*)InternalShape);
262  return SphereShape;
263  break;
264  }
265  case GIMPACT_SHAPE_PROXYTYPE:
266  {
267  DynamicMeshCollisionShape* GImpactShape = new DynamicMeshCollisionShape(Name,(btGImpactMeshShape*)InternalShape);
268  return GImpactShape;
269  break;
270  }
271  case TERRAIN_SHAPE_PROXYTYPE:
272  {
273  HeightfieldCollisionShape* HeightFieldShape = new HeightfieldCollisionShape(Name,(btHeightfieldTerrainShape*)InternalShape);
274  return HeightFieldShape;
275  break;
276  }
277  case STATIC_PLANE_PROXYTYPE:
278  {
279  PlaneCollisionShape* PlaneShape = new PlaneCollisionShape(Name,(btStaticPlaneShape*)InternalShape);
280  return PlaneShape;
281  break;
282  }
283  case SOFTBODY_SHAPE_PROXYTYPE:
284  {
285  SoftCollisionShape* SoftBodyShape = new SoftCollisionShape(Name,(btSoftBodyCollisionShape*)InternalShape);
286  return SoftBodyShape;
287  break;
288  }
289  case TRIANGLE_MESH_SHAPE_PROXYTYPE:
290  {
291  StaticMeshCollisionShape* BvhShape = new StaticMeshCollisionShape(Name,(btBvhTriangleMeshShape*)InternalShape);
292  return BvhShape;
293  break;
294  }
295  case COMPOUND_SHAPE_PROXYTYPE:
296  {
297  CompoundCollisionShape* Compound = new CompoundCollisionShape(Name,(btCompoundShape*)InternalShape);
298  return Compound;
299  break;
300  }
301  default:
302  {
303  MEZZ_EXCEPTION(Exception::NOT_IMPLEMENTED_EXCEPTION,"Attempting to load an unsupported/unwrapped Collision Shape in CompoundShapeManager::LoadAllShapesFromFile.");
304  }//default
305  }
306  }
307 
308  ///////////////////////////////////////////////////////////////////////////////
309  // Generic Shape Management
310 
312  {
313  ShapeMapIterator CS = this->CollisionShapes.find(Shape->GetName());
314  if(CS != this->CollisionShapes.end())
315  {
316  if((*CS).second != Shape)
317  {
318  MEZZ_EXCEPTION(Exception::II_DUPLICATE_IDENTITY_EXCEPTION,"Name of Collision Shape already exists on another object. Names should be Unique.");
319  }
320  }else{
321  this->CollisionShapes[Shape->GetName()] = Shape;
322  }
323  }
324 
326  {
327  ShapeMapIterator CS = this->CollisionShapes.find(Name);
328  if(CS == this->CollisionShapes.end()) return NULL;
329  else return (*CS).second;
330  }
331 
333  {
334  return this->CollisionShapes.size();
335  }
336 
338  {
339  this->RemoveShape( Shape->GetName() );
340  }
341 
343  {
344  ShapeMapIterator CS = this->CollisionShapes.find(Name);
345  if(CS == this->CollisionShapes.end())
346  return;
347  this->CollisionShapes.erase(CS);
348  }
349 
351  {
352  this->CollisionShapes.clear();
353  }
354 
356  {
357  this->DestroyShape(Shape->GetName());
358  }
359 
361  {
362  ShapeMapIterator CS = this->CollisionShapes.find(Name);
363  if(CS == this->CollisionShapes.end())
364  return;
365  delete (*CS).second;
366  this->CollisionShapes.erase(CS);
367  }
368 
370  {
371  for( ShapeMapIterator CS = this->CollisionShapes.begin() ; CS != this->CollisionShapes.end() ; CS++ )
372  {
373  CollisionShape* CurrShape = (*CS).second;
374  delete CurrShape;
375  }
376  this->CollisionShapes.clear();
377  }
378 
380  { return this->CollisionShapes.begin(); }
381 
383  { return this->CollisionShapes.end(); }
384 
386  { return this->CollisionShapes.begin(); }
387 
389  { return this->CollisionShapes.end(); }
390 
391  ///////////////////////////////////////////////////////////////////////////////
392  // Shape Creation Utilities
393 
395  {
396  btConvexShape *tmpshape = new btConvexTriangleMeshShape(this->CreateBulletTrimesh(ObjectMesh,UseAllSubmeshes));
397  btShapeHull *hull = new btShapeHull(tmpshape);
398  btScalar margin = tmpshape->getMargin();
399  hull->buildHull(margin);
400  //tmpshape->setUserPointer(hull);
401  btConvexHullShape* convexShape = new btConvexHullShape();
402  for (int b=0;b<hull->numVertices();b++)
403  {
404  convexShape->addPoint(hull->getVertexPointer()[b]);
405  }
406  delete tmpshape;
407  delete hull;
408  return new ConvexHullCollisionShape(Name,convexShape);
409  }
410 
411  ConvexHullCollisionShape* CollisionShapeManager::GenerateConvexHull(const String& Name, const String& MeshName, const String& Group, bool UseAllSubmeshes)
412  {
413  Graphics::Mesh* ObjectMesh = Graphics::MeshManager::GetSingletonPtr()->LoadMesh(MeshName,Group);
414  return this->GenerateConvexHull(Name,ObjectMesh,UseAllSubmeshes);
415  }
416 
418  {
419  btGImpactMeshShape* gimpact = new btGImpactMeshShape(this->CreateBulletTrimesh(ObjectMesh,UseAllSubmeshes));
420  return new DynamicMeshCollisionShape(Name,gimpact);
421  }
422 
423  DynamicMeshCollisionShape* CollisionShapeManager::GenerateDynamicTriMesh(const String& Name, const String& MeshName, const String& Group, bool UseAllSubmeshes)
424  {
425  Graphics::Mesh* ObjectMesh = Graphics::MeshManager::GetSingletonPtr()->LoadMesh(MeshName,Group);
426  return this->GenerateDynamicTriMesh(Name,ObjectMesh,UseAllSubmeshes);
427  }
428 
430  {
431  btBvhTriangleMeshShape* tmpshape = new btBvhTriangleMeshShape(this->CreateBulletTrimesh(ObjectMesh,UseAllSubmeshes),true);
432  return new StaticMeshCollisionShape(Name,tmpshape);
433  }
434 
435  StaticMeshCollisionShape* CollisionShapeManager::GenerateStaticTriMesh(const String& Name, const String& MeshName, const String& Group, bool UseAllSubmeshes)
436  {
437  Graphics::Mesh* ObjectMesh = Graphics::MeshManager::GetSingletonPtr()->LoadMesh(MeshName,Group);
438  return this->GenerateStaticTriMesh(Name,ObjectMesh,UseAllSubmeshes);
439  }
440 
441  CompoundCollisionShape* CollisionShapeManager::PerformConvexDecomposition(const String& Name, Graphics::Mesh* ObjectMesh, Whole Depth, Real CPercent, Real PPercent, bool UseAllSubmeshes)
442  {
443  //new submesh friendly code
444  Ogre::MeshPtr myMesh = ObjectMesh->_GetInternalMesh();
445  Ogre::SubMesh* subMesh = NULL;
446  Ogre::IndexData* indexData = NULL;
447  Ogre::VertexData* vertexData = NULL;
448  bool use32bitindexes = false;
449  unsigned int currtriCount = 0;
450  unsigned int triCount = 0;
451  unsigned int vCount = 0;
452  unsigned int iCount = 0;
453  Whole VertPrevSize = 0;
454  Whole IndiPrevSize = 0;
455  bool SharedVerts = myMesh->getSubMesh(0)->useSharedVertices;
456 
457  Whole* VertPerSubMesh = NULL;
458 
459  if(UseAllSubmeshes)
460  {
461  VertPerSubMesh = new Whole[myMesh->getNumSubMeshes()];
462  for( Whole X = 0 ; X < myMesh->getNumSubMeshes() ; X++ )
463  {
464  vCount += SharedVerts ? myMesh->sharedVertexData->vertexCount : myMesh->getSubMesh(X)->vertexData->vertexCount;
465  iCount += myMesh->getSubMesh(X)->indexData->indexCount;
466  VertPerSubMesh[X] = SharedVerts ? myMesh->sharedVertexData->vertexCount : myMesh->getSubMesh(X)->vertexData->vertexCount;
467  }
468  }else{
469  vCount += SharedVerts ? myMesh->sharedVertexData->vertexCount : myMesh->getSubMesh(0)->vertexData->vertexCount;
470  iCount += myMesh->getSubMesh(0)->indexData->indexCount;
471  }
472 
473  Ogre::Vector3* vertices = new Ogre::Vector3[vCount];
474  unsigned int* indices = new unsigned int[iCount];
475 
476  for( unsigned short int SubMeshIndex = 0 ; SubMeshIndex < myMesh->getNumSubMeshes() ; SubMeshIndex++ )
477  {
478  if( !UseAllSubmeshes && (SubMeshIndex > 0) )
479  break;
480  if( SharedVerts && (SubMeshIndex > 0) )
481  break;
482 
483  subMesh = myMesh->getSubMesh(SubMeshIndex);
484  indexData = subMesh->indexData;
485  vertexData = SharedVerts ? myMesh->sharedVertexData : myMesh->getSubMesh(SubMeshIndex)->vertexData;
486 
487  const Ogre::VertexElement* posElem = vertexData->vertexDeclaration->findElementBySemantic(Ogre::VES_POSITION);
488  Ogre::HardwareVertexBufferSharedPtr vBuffer = vertexData->vertexBufferBinding->getBuffer(posElem->getSource());
489  Ogre::HardwareIndexBufferSharedPtr iBuffer = indexData->indexBuffer;
490  currtriCount=indexData->indexCount/3;
491  triCount+=(indexData->indexCount/3);
492 
493  unsigned char* vertex = static_cast<unsigned char*>(vBuffer->lock(Ogre::HardwareBuffer::HBL_READ_ONLY));
494  float* pReal = NULL;
495  for( size_t j = 0 ; j < vertexData->vertexCount ; j++, vertex += vBuffer->getVertexSize() )
496  {
497  posElem->baseVertexPointerToElement(vertex, &pReal);
498  vertices[j + VertPrevSize].x = *pReal++;
499  vertices[j + VertPrevSize].y = *pReal++;
500  vertices[j + VertPrevSize].z = *pReal++;
501  }
502  vBuffer->unlock();
503  size_t index_offset = 0;
504  use32bitindexes = (iBuffer->getType() == Ogre::HardwareIndexBuffer::IT_32BIT);
505 
506  unsigned long* pLong = static_cast<unsigned long*>(iBuffer->lock(Ogre::HardwareBuffer::HBL_READ_ONLY));
507  unsigned short* pShort = reinterpret_cast<unsigned short*>(pLong);
508 
509  if( use32bitindexes )
510  {
511  for (size_t k = 0; k < currtriCount*3; ++k)
512  {
513  if(SubMeshIndex > 0 && VertPerSubMesh) {
514  indices[index_offset+IndiPrevSize] = pLong[k] + VertPerSubMesh[SubMeshIndex];
515  }else{
516  indices[index_offset+IndiPrevSize] = pLong[k];
517  }
518  index_offset++;
519  }
520  }else{
521  for( size_t k = 0 ; k < currtriCount * 3 ; ++k )
522  {
523  if(SubMeshIndex > 0 && VertPerSubMesh) {
524  indices[index_offset+IndiPrevSize] = (static_cast<unsigned long>(pShort[k])) + VertPerSubMesh[SubMeshIndex];
525  }else{
526  indices[index_offset+IndiPrevSize] = static_cast<unsigned long>(pShort[k]);
527  }
528  index_offset++;
529  }
530  }
531  iBuffer->unlock();
532 
533  VertPrevSize += vertexData->vertexCount;
534  IndiPrevSize += indexData->indexCount;
535  }
536 
537  ConvexDecomposition::DecompDesc desc;
538  desc.mVcount = vertexData->vertexCount;
539  desc.mTcount = triCount;
540  desc.mVertices = &vertices[0].x;
541  desc.mIndices = &indices[0];
542  unsigned int maxv = 16;
543  float skinWidth = 0.0;
544  desc.mDepth = Depth;
545  desc.mCpercent = CPercent;
546  desc.mPpercent = PPercent;
547  desc.mMaxVertices = maxv;
548  desc.mSkinWidth = skinWidth;
549 
550  Internal::MezzConvexDecomposition decomp;
551  desc.mCallback = &decomp;
552 
553  ConvexBuilder cb(desc.mCallback);
554  cb.process(desc);
555 
556  CompoundCollisionShape* compound = new CompoundCollisionShape(Name);
557  btTransform trans;
558  trans.setIdentity();
559  for (int i=0;i<decomp.m_convexShapes.size();i++)
560  {
561  std::stringstream namestream;
562  namestream << Name << "Child" << i;
563  Vector3 centroid(decomp.m_convexCentroids[i]);
564  ConvexHullCollisionShape* convexShape = new ConvexHullCollisionShape(namestream.str(),decomp.m_convexShapes[i]);
565  compound->AddChildShape(convexShape,centroid);
566  }
567  delete[] vertices;
568  delete[] indices;
569  delete[] VertPerSubMesh;
570  return compound;
571  }
572 
573  CompoundCollisionShape* CollisionShapeManager::PerformConvexDecomposition(const String& Name, const String& MeshName, const String& Group, Whole Depth, Real CPercent, Real PPercent, bool UseAllSubmeshes)
574  {
575  Graphics::Mesh* ObjectMesh = Graphics::MeshManager::GetSingletonPtr()->LoadMesh(MeshName,Group);
576  return this->PerformConvexDecomposition(Name,ObjectMesh,Depth,CPercent,PPercent,UseAllSubmeshes);
577  }
578 
579  ///////////////////////////////////////////////////////////////////////////////
580  // Shape Saving/Loading Utilities
581 
583  {
584  /// @todo Replace this stack allocated stream for one initialized from the Resource Manager, after the system is ready.
585  Resource::FileStream ShapesStream( FileName, ResourceManager::GetSingletonPtr()->GetAssetPath(FileName,Group) );
586  XML::Document ShapesDoc;
587  XML::ParseResult DocResult = ShapesDoc.Load(ShapesStream);
588  if( DocResult.Status != XML::StatusOk ) {
589  MEZZ_EXCEPTION(Exception::SYNTAX_ERROR_EXCEPTION_XML,"Failed to parse XML file \"" + FileName + "\".");
590  }
591  XML::Node ShapesRoot = ShapesDoc.GetChild("InitializerRoot");
592  if( ShapesRoot.Empty() ) {
593  MEZZ_EXCEPTION(Exception::SYNTAX_ERROR_EXCEPTION_XML,"Failed to find expected Root node in \"" + FileName + "\".");
594  }
595 
596  for( XML::NodeIterator ShapeIt = ShapesRoot.begin() ; ShapeIt != ShapesRoot.end() ; ++ShapeIt )
597  {
598  CollisionShape* DeSerializedShape = Physics::CreateShape( (*ShapeIt) );
599  this->CollisionShapes.insert( std::pair<String,CollisionShape*>(DeSerializedShape->GetName(),DeSerializedShape) );
600  }
601  }
602 
604  {
605  XML::Document ShapesDoc;
606  XML::Node DeclNode = ShapesDoc.AppendChild(XML::NodeDeclaration);
607  XML::Attribute VerAttrib = DeclNode.AppendAttribute("version");
608 
609  if( DeclNode.SetName("xml") && VerAttrib.SetValue("1.0") ) {
610  XML::Node ShapesRoot = ShapesDoc.AppendChild( "ShapesRoot" );
611  for( ShapeMapIterator ShapeIt = this->CollisionShapes.begin() ; ShapeIt != this->CollisionShapes.end() ; ++ShapeIt )
612  {
613  (*ShapeIt).second->ProtoSerialize( ShapesRoot );
614  }
615 
616  /// @todo Replace this stack allocated stream for one initialized from the Resource Manager, after the system is ready.
618  ShapesDoc.Save(SettingsStream,"\t",XML::FormatIndent);
619  }else{
620  MEZZ_EXCEPTION(Exception::INVALID_STATE_EXCEPTION,"Failed to create XML document declaration for file \"" + FileName + "\".");
621  }
622  }
623 
624  void CollisionShapeManager::SaveShapesToXMLFile(const String& FileName, ShapeVector& ShapesToSave)
625  {
626  XML::Document ShapesDoc;
627  XML::Node DeclNode = ShapesDoc.AppendChild(XML::NodeDeclaration);
628  XML::Attribute VerAttrib = DeclNode.AppendAttribute("version");
629 
630  if( DeclNode.SetName("xml") && VerAttrib.SetValue("1.0") ) {
631  XML::Node ShapesRoot = ShapesDoc.AppendChild( "ShapesRoot" );
632  for( ShapeVectorIterator ShapeIt = ShapesToSave.begin() ; ShapeIt != ShapesToSave.end() ; ++ShapeIt )
633  {
634  (*ShapeIt)->ProtoSerialize( ShapesRoot );
635  }
636 
637  /// @todo Replace this stack allocated stream for one initialized from the Resource Manager, after the system is ready.
639  ShapesDoc.Save(SettingsStream,"\t",XML::FormatIndent);
640  }else{
641  MEZZ_EXCEPTION(Exception::INVALID_STATE_EXCEPTION,"Failed to create XML document declaration for file \"" + FileName + "\".");
642  }
643  }
644 
646  {
647  btBulletWorldImporter Importer;
648  Ogre::DataStreamPtr Stream = Ogre::ResourceGroupManager::getSingleton().openResource(FileName,Group);
649  char* buffer = new char[Stream->size()];
650  Stream->read((void*)buffer, Stream->size());
651  if(!Importer.loadFileFromMemory(buffer, Stream->size()))
652  {
653  MEZZ_EXCEPTION(Exception::IO_FILE_EXCEPTION,"Failed to load file: " + FileName + ".")
654  }
655  delete[] buffer;
656  for( Whole X = 0 ; X < Importer.getNumCollisionShapes() ; ++X )
657  {
658  btCollisionShape* Shape = Importer.getCollisionShapeByIndex(X);
659  const char* MaybeAName = Importer.getNameForPointer((void*)Shape);
660  String Name;
661  if(MaybeAName)
662  {
663  Name = String(MaybeAName);
664  ShapeMapIterator it = this->CollisionShapes.find(Name);
665  if(it == this->CollisionShapes.end())
666  {
667  CollisionShape* NewShape = this->WrapShape(Name,Shape);
668  this->CollisionShapes.insert( std::pair<String,CollisionShape*>(Name,NewShape) );
669  }
670  }else{
671  static Whole NameCount = 0;
672  Name = String("Unnamed") += StringTools::ConvertToString(NameCount++);
673  CollisionShape* NewShape = this->WrapShape(Name,Shape);
674  this->UnnamedShapes.push_back(NewShape);
675  }
676  }
677  }
678 
680  {
681  btDefaultSerializer* BulletSerializer = new btDefaultSerializer(1024*1024*5);
682  BulletSerializer->startSerialization();
683  for( ShapeMapIterator it = this->CollisionShapes.begin() ; it != this->CollisionShapes.end() ; it++ )
684  {
685  CollisionShape* Shape = (*it).second;
686  BulletSerializer->registerNameForPointer((void*)Shape->_GetInternalShape(),(*it).first.c_str());
687  int len = Shape->_GetInternalShape()->calculateSerializeBufferSize();
688  btChunk* chunk = BulletSerializer->allocate(len,1);
689  const char* structType = Shape->_GetInternalShape()->serialize(chunk->m_oldPtr, BulletSerializer);
690  BulletSerializer->finalizeChunk(chunk,structType,BT_SHAPE_CODE,Shape->_GetInternalShape());
691  }
692  BulletSerializer->finishSerialization();
693  FILE* f2 = fopen(FileName.c_str(),"wb");
694  fwrite(BulletSerializer->getBufferPointer(),BulletSerializer->getCurrentBufferSize(),1,f2);
695  fclose(f2);
696  }
697 
699  {
700  btDefaultSerializer* BulletSerializer = new btDefaultSerializer(1024*1024*5);
701  BulletSerializer->startSerialization();
702  for( ShapeVectorIterator it = ShapesToSave.begin() ; it != ShapesToSave.end() ; it++ )
703  {
704  Physics::CollisionShape* Shape = (*it);
705  BulletSerializer->registerNameForPointer((void*)Shape->_GetInternalShape(),(*it)->GetName().c_str());
706  int len = Shape->_GetInternalShape()->calculateSerializeBufferSize();
707  btChunk* chunk = BulletSerializer->allocate(len,1);
708  const char* structType = Shape->_GetInternalShape()->serialize(chunk->m_oldPtr, BulletSerializer);
709  BulletSerializer->finalizeChunk(chunk,structType,BT_SHAPE_CODE,Shape->_GetInternalShape());
710  }
711  BulletSerializer->finishSerialization();
712  FILE* f2 = fopen(FileName.c_str(),"wb");
713  fwrite(BulletSerializer->getBufferPointer(),BulletSerializer->getCurrentBufferSize(),1,f2);
714  fclose(f2);
715  }
716 
717  ///////////////////////////////////////////////////////////////////////////////
718  // Unnamed Shape Management
719 
721  {
722  return this->UnnamedShapes;
723  }
724 
726  {
727  for( ShapeVectorIterator ShapeIt = this->UnnamedShapes.begin() ; ShapeIt != this->UnnamedShapes.end() ; ++ShapeIt )
728  {
729  if( (*ShapeIt) == Shape ) {
730  this->UnnamedShapes.erase( ShapeIt );
731  break;
732  }
733  }
734 
735  ShapeMapIterator NaIt = this->CollisionShapes.find(NewName);
736  if(NaIt != this->CollisionShapes.end()) {
737  MEZZ_EXCEPTION(Exception::II_DUPLICATE_IDENTITY_EXCEPTION,"Attempting to assign non-unique name to an unnamed Collision Shape.");
738  }
739 
740  Shape->_SetShapeName(NewName);
741  this->CollisionShapes.insert( std::pair<String,CollisionShape*>(NewName,Shape) );
742  }
743 
744  ///////////////////////////////////////////////////////////////////////////////
745  // Utility
746 
748  { Initialized = true; }
749 
751  { Initialized = false; }
752 
753  ///////////////////////////////////////////////////////////////////////////////
754  // Type Identifier Methods
755 
757  { return ManagerBase::MT_CollisionShapeManager; }
758 
760  { return "DefaultCollisionShapeManager"; }
761 
762  ///////////////////////////////////////////////////////////////////////////////
763  // DefaultCollisionShapeManagerFactory Methods
764 
766  {
767  }
768 
770  {
771  }
772 
774  {
775  return "DefaultCollisionShapeManager";
776  }
777 
779  {
781  {
782  /// @todo Add something to log a warning that the manager exists and was requested to be constructed when we have a logging manager set up.
784  }else return new CollisionShapeManager();
785  }
786 
788  {
790  {
791  /// @todo Add something to log a warning that the manager exists and was requested to be constructed when we have a logging manager set up.
793  }else return new CollisionShapeManager(XMLNode);
794  }
795 
797  {
798  delete ToBeDestroyed;
799  }
800  }//Physics
801 }//Mezzanine
802 
803 #endif