Spinning Topp Logo BlackTopp Studios
inc
collisionshapemanager.cpp
1 // © Copyright 2010 - 2016 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"
47 #include "Resource/filestream.h"
48 
49 #include "Physics/collisionshape.h"
50 #include "Physics/boxcollisionshape.h"
51 #include "Physics/capsulecollisionshape.h"
52 #include "Physics/conecollisionshape.h"
53 #include "Physics/convexhullcollisionshape.h"
54 #include "Physics/cylindercollisionshape.h"
55 #include "Physics/multispherecollisionshape.h"
56 #include "Physics/spherecollisionshape.h"
57 #include "Physics/dynamicmeshcollisionshape.h"
58 #include "Physics/heightfieldcollisionshape.h"
59 #include "Physics/planecollisionshape.h"
60 #include "Physics/softcollisionshape.h"
61 #include "Physics/staticmeshcollisionshape.h"
62 #include "Physics/compoundcollisionshape.h"
63 
64 // For logging
65 #include "stringtool.h"
66 #include "entresol.h"
67 
68 #include <Ogre.h>
69 #include "btBulletDynamicsCommon.h"
70 #include "BulletSoftBody/btSoftRigidDynamicsWorld.h"
71 #include "BulletCollision/CollisionShapes/btShapeHull.h"
72 #include "BulletCollision/Gimpact/btGImpactShape.h"
73 #include "ConvexBuilder.h"
74 #include "Internal/decompinterface.h.cpp"
75 #include <btBulletWorldImporter.h>
76 
77 #include <fstream>
78 
79 namespace Mezzanine
80 {
81  /// @brief the backing for the pointer declared in singleton.h
82  template<> Physics::CollisionShapeManager* Singleton<Physics::CollisionShapeManager>::SingletonPtr = NULL;
83 
84  namespace Physics
85  {
86  //template<> CollisionShapeManager* Singleton<CollisionShapeManager>::SingletonPtr = NULL;
87  const String CollisionShapeManager::ImplementationName = "DefaultCollisionShapeManager";
88  const ManagerBase::ManagerType CollisionShapeManager::InterfaceType = ManagerBase::MT_CollisionShapeManager;
89 
91  { }
92 
94  {
95  /// @todo This class currently doesn't initialize anything from XML, if that changes this constructor needs to be expanded.
96  }
97 
99  {
100  this->Deinitialize();
101  this->DestroyAllShapes();
102  }
103 
104  btTriangleMesh* CollisionShapeManager::CreateBulletTrimesh(Graphics::Mesh* ObjectMesh, Boole UseAllSubmeshes)
105  {
106  Ogre::MeshPtr myMesh = ObjectMesh->_GetInternalMesh();
107  Ogre::SubMesh* subMesh = NULL;
108  Ogre::IndexData* IndexData = NULL;
109  Ogre::VertexData* VertexData = NULL;
110  Boole use32bitindexes = false;
111  unsigned int triCount = 0;
112  unsigned int vCount = 0;
113  unsigned int iCount = 0;
114  Whole VertPrevSize = 0;
115  Whole IndiPrevSize = 0;
116  Ogre::Vector3* vertices = NULL;
117  unsigned long* indices = NULL;
118  Boole SharedVerts = myMesh->getSubMesh(0)->useSharedVertices;
119 
120  if(UseAllSubmeshes)
121  {
122  for( Whole X = 0 ; X < myMesh->getNumSubMeshes() ; X++ )
123  {
124  vCount += SharedVerts ? myMesh->sharedVertexData->vertexCount : myMesh->getSubMesh(X)->vertexData->vertexCount;
125  iCount += myMesh->getSubMesh(X)->indexData->indexCount;
126  }
127  }else{
128  vCount += SharedVerts ? myMesh->sharedVertexData->vertexCount : myMesh->getSubMesh(0)->vertexData->vertexCount;
129  iCount += myMesh->getSubMesh(0)->indexData->indexCount;
130  }
131 
132  vertices = new Ogre::Vector3[vCount];
133  indices = new unsigned long[iCount];
134 
135  // Get the submesh and associated data
136  for( unsigned short int SubMeshIndex = 0 ; SubMeshIndex < myMesh->getNumSubMeshes() ; SubMeshIndex++ )
137  {
138  if( !UseAllSubmeshes && ( SubMeshIndex > 0 ) )
139  break;
140  if( SharedVerts && (SubMeshIndex > 0) )
141  break;
142 
143  subMesh = myMesh->getSubMesh(SubMeshIndex);
144  IndexData = subMesh->indexData;
145  VertexData = SharedVerts ? myMesh->sharedVertexData : myMesh->getSubMesh(SubMeshIndex)->vertexData;
146 
147  // Get the position element
148  const Ogre::VertexElement* posElem = VertexData->vertexDeclaration->findElementBySemantic(Ogre::VES_POSITION);
149  // Get a pointer to the vertex buffer
150  Ogre::HardwareVertexBufferSharedPtr vBuffer = VertexData->vertexBufferBinding->getBuffer(posElem->getSource());
151  // Get a pointer to the index buffer
152  Ogre::HardwareIndexBufferSharedPtr iBuffer = IndexData->indexBuffer;
153  // Get the number of triangles
154  triCount += ( IndexData->indexCount / 3 );
155 
156  // Lock the vertex buffer (READ ONLY)
157  unsigned char* vertex = static_cast<unsigned char*>(vBuffer->lock(Ogre::HardwareBuffer::HBL_READ_ONLY));
158  float* pReal = NULL;
159  for (size_t j = 0; j < VertexData->vertexCount; ++j, vertex += vBuffer->getVertexSize() )
160  {
161  posElem->baseVertexPointerToElement(vertex, &pReal);
162  Ogre::Vector3 pt(pReal[0], pReal[1], pReal[2]);
163  vertices[j + VertPrevSize] = pt;
164  }
165  vBuffer->unlock();
166  size_t index_offset = 0;
167  use32bitindexes = (iBuffer->getType() == Ogre::HardwareIndexBuffer::IT_32BIT);
168 
169  // Lock the index buffer (READ ONLY)
170  unsigned long* pLong = static_cast<unsigned long*>(iBuffer->lock(Ogre::HardwareBuffer::HBL_READ_ONLY));
171  unsigned short* pShort = reinterpret_cast<unsigned short*>(pLong);
172 
173  if( use32bitindexes )
174  {
175  for (size_t k = 0; k < triCount*3; ++k)
176  {
177  indices[index_offset+IndiPrevSize] = pLong[k];
178  index_offset++;
179  }
180  }else{
181  for (size_t k = 0; k < triCount*3; ++k)
182  {
183  indices[index_offset+IndiPrevSize] = static_cast<unsigned long>(pShort[k]);
184  index_offset++;
185  }
186  }
187  iBuffer->unlock();
188 
189  VertPrevSize+=VertexData->vertexCount;
190  IndiPrevSize+=IndexData->indexCount;
191  }
192 
193  // We now have vertices and indices ready to go
194 
195  // The Bullet triangle mesh
196  btTriangleMesh* trimesh = new btTriangleMesh(use32bitindexes);
197 
198  // Setup the tri mesh
199  btVector3 vert0, vert1, vert2;
200  int i=0;
201 
202  // For every triangle
203  for (unsigned int y=0; y<triCount; y++)
204  {
205  // Set each vertex
206  vert0.setValue(vertices[indices[i]].x, vertices[indices[i]].y, vertices[indices[i]].z);
207  vert1.setValue(vertices[indices[i+1]].x, vertices[indices[i+1]].y, vertices[indices[i+1]].z);
208  vert2.setValue(vertices[indices[i+2]].x, vertices[indices[i+2]].y, vertices[indices[i+2]].z);
209 
210  // Add it into the trimesh
211  trimesh->addTriangle(vert0, vert1, vert2);
212 
213  // Increase index count
214  i+=3;
215  }
216  delete[] vertices;
217  delete[] indices;
218 
219  return trimesh;
220  }
221 
222  CollisionShape* CollisionShapeManager::WrapShape(const String& Name, btCollisionShape* InternalShape)
223  {
224  switch(InternalShape->getShapeType())
225  {
226  case BOX_SHAPE_PROXYTYPE:
227  {
228  BoxCollisionShape* BoxShape = new BoxCollisionShape(Name,(btBoxShape*)InternalShape);
229  return BoxShape;
230  break;
231  }
232  case CAPSULE_SHAPE_PROXYTYPE:
233  {
234  CapsuleCollisionShape* CapsuleShape = new CapsuleCollisionShape(Name,(btCapsuleShape*)InternalShape);
235  return CapsuleShape;
236  break;
237  }
238  case CONE_SHAPE_PROXYTYPE:
239  {
240  ConeCollisionShape* ConeShape = new ConeCollisionShape(Name,(btConeShape*)InternalShape);
241  return ConeShape;
242  break;
243  }
244  case CONVEX_HULL_SHAPE_PROXYTYPE:
245  {
246  ConvexHullCollisionShape* ConvexHullShape = new ConvexHullCollisionShape(Name,(btConvexHullShape*)InternalShape);
247  return ConvexHullShape;
248  break;
249  }
250  case CYLINDER_SHAPE_PROXYTYPE:
251  {
252  CylinderCollisionShape* CylinderShape = new CylinderCollisionShape(Name,(btCylinderShape*)InternalShape);
253  return CylinderShape;
254  break;
255  }
256  case MULTI_SPHERE_SHAPE_PROXYTYPE:
257  {
258  MultiSphereCollisionShape* MultiSphereShape = new MultiSphereCollisionShape(Name,(btMultiSphereShape*)InternalShape);
259  return MultiSphereShape;
260  break;
261  }
262  case SPHERE_SHAPE_PROXYTYPE:
263  {
264  SphereCollisionShape* SphereShape = new SphereCollisionShape(Name,(btSphereShape*)InternalShape);
265  return SphereShape;
266  break;
267  }
268  case GIMPACT_SHAPE_PROXYTYPE:
269  {
270  DynamicMeshCollisionShape* GImpactShape = new DynamicMeshCollisionShape(Name,(btGImpactMeshShape*)InternalShape);
271  return GImpactShape;
272  break;
273  }
274  case TERRAIN_SHAPE_PROXYTYPE:
275  {
276  HeightfieldCollisionShape* HeightFieldShape = new HeightfieldCollisionShape(Name,(btHeightfieldTerrainShape*)InternalShape);
277  return HeightFieldShape;
278  break;
279  }
280  case STATIC_PLANE_PROXYTYPE:
281  {
282  PlaneCollisionShape* PlaneShape = new PlaneCollisionShape(Name,(btStaticPlaneShape*)InternalShape);
283  return PlaneShape;
284  break;
285  }
286  case SOFTBODY_SHAPE_PROXYTYPE:
287  {
288  SoftCollisionShape* SoftBodyShape = new SoftCollisionShape(Name,(btSoftBodyCollisionShape*)InternalShape);
289  return SoftBodyShape;
290  break;
291  }
292  case TRIANGLE_MESH_SHAPE_PROXYTYPE:
293  {
294  StaticMeshCollisionShape* BvhShape = new StaticMeshCollisionShape(Name,(btBvhTriangleMeshShape*)InternalShape);
295  return BvhShape;
296  break;
297  }
298  case COMPOUND_SHAPE_PROXYTYPE:
299  {
300  CompoundCollisionShape* Compound = new CompoundCollisionShape(Name,(btCompoundShape*)InternalShape);
301  return Compound;
302  break;
303  }
304  default:
305  {
306  MEZZ_EXCEPTION(ExceptionBase::NOT_IMPLEMENTED_EXCEPTION,"Attempting to load an unsupported/unwrapped Collision Shape in CompoundShapeManager::LoadAllShapesFromFile.");
307  }//default
308  }
309  }
310 
311  ///////////////////////////////////////////////////////////////////////////////
312  // Generic Shape Management
313 
315  {
316  ShapeMapIterator CS = this->CollisionShapes.find(Shape->GetName());
317  if(CS != this->CollisionShapes.end()) {
318  if((*CS).second != Shape) {
319  MEZZ_EXCEPTION(ExceptionBase::II_DUPLICATE_IDENTITY_EXCEPTION,"Name of Collision Shape already exists on another object. Names should be Unique.");
320  }
321  }else{
322  this->CollisionShapes[Shape->GetName()] = Shape;
323  }
324  }
325 
327  {
328  ShapeMapIterator CS = this->CollisionShapes.find(Name);
329  if(CS == this->CollisionShapes.end()) return NULL;
330  else return (*CS).second;
331  }
332 
334  {
335  return this->CollisionShapes.size();
336  }
337 
339  {
340  this->RemoveShape( Shape->GetName() );
341  }
342 
344  {
345  ShapeMapIterator CS = this->CollisionShapes.find(Name);
346  if(CS == this->CollisionShapes.end())
347  return;
348  this->CollisionShapes.erase(CS);
349  }
350 
352  {
353  this->CollisionShapes.clear();
354  }
355 
357  {
358  this->DestroyShape(Shape->GetName());
359  }
360 
362  {
363  ShapeMapIterator CS = this->CollisionShapes.find(Name);
364  if(CS == this->CollisionShapes.end())
365  return;
366  delete (*CS).second;
367  this->CollisionShapes.erase(CS);
368  }
369 
371  {
372  for( ShapeMapIterator CS = this->CollisionShapes.begin() ; CS != this->CollisionShapes.end() ; CS++ )
373  {
374  CollisionShape* CurrShape = (*CS).second;
375  delete CurrShape;
376  }
377  this->CollisionShapes.clear();
378  }
379 
381  { return this->CollisionShapes.begin(); }
382 
384  { return this->CollisionShapes.end(); }
385 
387  { return this->CollisionShapes.begin(); }
388 
390  { return this->CollisionShapes.end(); }
391 
392  ///////////////////////////////////////////////////////////////////////////////
393  // Shape Creation Utilities
394 
396  {
397  btConvexShape *tmpshape = new btConvexTriangleMeshShape(this->CreateBulletTrimesh(ObjectMesh,UseAllSubmeshes));
398  btShapeHull *hull = new btShapeHull(tmpshape);
399  btScalar margin = tmpshape->getMargin();
400  hull->buildHull(margin);
401  //tmpshape->setUserPointer(hull);
402  btConvexHullShape* convexShape = new btConvexHullShape();
403  for (int b=0;b<hull->numVertices();b++)
404  {
405  convexShape->addPoint(hull->getVertexPointer()[b]);
406  }
407  delete tmpshape;
408  delete hull;
409  return new ConvexHullCollisionShape(Name,convexShape);
410  }
411 
412  ConvexHullCollisionShape* CollisionShapeManager::GenerateConvexHull(const String& Name, const String& MeshName, const String& Group, Boole UseAllSubmeshes)
413  {
414  Graphics::Mesh* ObjectMesh = Graphics::MeshManager::GetSingletonPtr()->LoadMesh(MeshName,Group);
415  return this->GenerateConvexHull(Name,ObjectMesh,UseAllSubmeshes);
416  }
417 
419  {
420  btGImpactMeshShape* gimpact = new btGImpactMeshShape(this->CreateBulletTrimesh(ObjectMesh,UseAllSubmeshes));
421  return new DynamicMeshCollisionShape(Name,gimpact);
422  }
423 
424  DynamicMeshCollisionShape* CollisionShapeManager::GenerateDynamicTriMesh(const String& Name, const String& MeshName, const String& Group, Boole UseAllSubmeshes)
425  {
426  Graphics::Mesh* ObjectMesh = Graphics::MeshManager::GetSingletonPtr()->LoadMesh(MeshName,Group);
427  return this->GenerateDynamicTriMesh(Name,ObjectMesh,UseAllSubmeshes);
428  }
429 
431  {
432  btBvhTriangleMeshShape* tmpshape = new btBvhTriangleMeshShape(this->CreateBulletTrimesh(ObjectMesh,UseAllSubmeshes),true);
433  return new StaticMeshCollisionShape(Name,tmpshape);
434  }
435 
436  StaticMeshCollisionShape* CollisionShapeManager::GenerateStaticTriMesh(const String& Name, const String& MeshName, const String& Group, Boole UseAllSubmeshes)
437  {
438  Graphics::Mesh* ObjectMesh = Graphics::MeshManager::GetSingletonPtr()->LoadMesh(MeshName,Group);
439  return this->GenerateStaticTriMesh(Name,ObjectMesh,UseAllSubmeshes);
440  }
441 
443  {
444  //new submesh friendly code
445  Ogre::MeshPtr myMesh = ObjectMesh->_GetInternalMesh();
446  Ogre::SubMesh* subMesh = NULL;
447  Ogre::IndexData* indexData = NULL;
448  Ogre::VertexData* vertexData = NULL;
449  Boole use32bitindexes = false;
450  unsigned int currtriCount = 0;
451  unsigned int triCount = 0;
452  unsigned int vCount = 0;
453  unsigned int iCount = 0;
454  Whole VertPrevSize = 0;
455  Whole IndiPrevSize = 0;
456  Boole SharedVerts = myMesh->getSubMesh(0)->useSharedVertices;
457 
458  Whole* VertPerSubMesh = NULL;
459 
460  if(UseAllSubmeshes)
461  {
462  VertPerSubMesh = new Whole[myMesh->getNumSubMeshes()];
463  for( Whole X = 0 ; X < myMesh->getNumSubMeshes() ; X++ )
464  {
465  vCount += SharedVerts ? myMesh->sharedVertexData->vertexCount : myMesh->getSubMesh(X)->vertexData->vertexCount;
466  iCount += myMesh->getSubMesh(X)->indexData->indexCount;
467  VertPerSubMesh[X] = SharedVerts ? myMesh->sharedVertexData->vertexCount : myMesh->getSubMesh(X)->vertexData->vertexCount;
468  }
469  }else{
470  vCount += SharedVerts ? myMesh->sharedVertexData->vertexCount : myMesh->getSubMesh(0)->vertexData->vertexCount;
471  iCount += myMesh->getSubMesh(0)->indexData->indexCount;
472  }
473 
474  Ogre::Vector3* vertices = new Ogre::Vector3[vCount];
475  unsigned int* indices = new unsigned int[iCount];
476 
477  for( unsigned short int SubMeshIndex = 0 ; SubMeshIndex < myMesh->getNumSubMeshes() ; SubMeshIndex++ )
478  {
479  if( !UseAllSubmeshes && (SubMeshIndex > 0) )
480  break;
481  if( SharedVerts && (SubMeshIndex > 0) )
482  break;
483 
484  subMesh = myMesh->getSubMesh(SubMeshIndex);
485  indexData = subMesh->indexData;
486  vertexData = SharedVerts ? myMesh->sharedVertexData : myMesh->getSubMesh(SubMeshIndex)->vertexData;
487 
488  const Ogre::VertexElement* posElem = vertexData->vertexDeclaration->findElementBySemantic(Ogre::VES_POSITION);
489  Ogre::HardwareVertexBufferSharedPtr vBuffer = vertexData->vertexBufferBinding->getBuffer(posElem->getSource());
490  Ogre::HardwareIndexBufferSharedPtr iBuffer = indexData->indexBuffer;
491  currtriCount=indexData->indexCount/3;
492  triCount+=(indexData->indexCount/3);
493 
494  unsigned char* vertex = static_cast<unsigned char*>(vBuffer->lock(Ogre::HardwareBuffer::HBL_READ_ONLY));
495  float* pReal = NULL;
496  for( size_t j = 0 ; j < vertexData->vertexCount ; j++, vertex += vBuffer->getVertexSize() )
497  {
498  posElem->baseVertexPointerToElement(vertex, &pReal);
499  vertices[j + VertPrevSize].x = *pReal++;
500  vertices[j + VertPrevSize].y = *pReal++;
501  vertices[j + VertPrevSize].z = *pReal++;
502  }
503  vBuffer->unlock();
504  size_t index_offset = 0;
505  use32bitindexes = (iBuffer->getType() == Ogre::HardwareIndexBuffer::IT_32BIT);
506 
507  unsigned long* pLong = static_cast<unsigned long*>(iBuffer->lock(Ogre::HardwareBuffer::HBL_READ_ONLY));
508  unsigned short* pShort = reinterpret_cast<unsigned short*>(pLong);
509 
510  if( use32bitindexes )
511  {
512  for (size_t k = 0; k < currtriCount*3; ++k)
513  {
514  if(SubMeshIndex > 0 && VertPerSubMesh) {
515  indices[index_offset+IndiPrevSize] = pLong[k] + VertPerSubMesh[SubMeshIndex];
516  }else{
517  indices[index_offset+IndiPrevSize] = pLong[k];
518  }
519  index_offset++;
520  }
521  }else{
522  for( size_t k = 0 ; k < currtriCount * 3 ; ++k )
523  {
524  if(SubMeshIndex > 0 && VertPerSubMesh) {
525  indices[index_offset+IndiPrevSize] = (static_cast<unsigned long>(pShort[k])) + VertPerSubMesh[SubMeshIndex];
526  }else{
527  indices[index_offset+IndiPrevSize] = static_cast<unsigned long>(pShort[k]);
528  }
529  index_offset++;
530  }
531  }
532  iBuffer->unlock();
533 
534  VertPrevSize += vertexData->vertexCount;
535  IndiPrevSize += indexData->indexCount;
536  }
537 
538  ConvexDecomposition::DecompDesc desc;
539  desc.mVcount = vertexData->vertexCount;
540  desc.mTcount = triCount;
541  desc.mVertices = &vertices[0].x;
542  desc.mIndices = &indices[0];
543  unsigned int maxv = 16;
544  float skinWidth = 0.0;
545  desc.mDepth = Depth;
546  desc.mCpercent = CPercent;
547  desc.mPpercent = PPercent;
548  desc.mMaxVertices = maxv;
549  desc.mSkinWidth = skinWidth;
550 
551  Internal::MezzConvexDecomposition decomp;
552  desc.mCallback = &decomp;
553 
554  ConvexBuilder cb(desc.mCallback);
555  cb.process(desc);
556 
557  CompoundCollisionShape* compound = new CompoundCollisionShape(Name);
558  btTransform trans;
559  trans.setIdentity();
560  for (int i=0;i<decomp.m_convexShapes.size();i++)
561  {
562  std::stringstream namestream;
563  namestream << Name << "Child" << i;
564  Vector3 centroid(decomp.m_convexCentroids[i]);
565  ConvexHullCollisionShape* convexShape = new ConvexHullCollisionShape(namestream.str(),decomp.m_convexShapes[i]);
566  compound->AddChildShape(convexShape,centroid);
567  }
568  delete[] vertices;
569  delete[] indices;
570  delete[] VertPerSubMesh;
571  return compound;
572  }
573 
574  CompoundCollisionShape* CollisionShapeManager::PerformConvexDecomposition(const String& Name, const String& MeshName, const String& Group, Whole Depth, Real CPercent, Real PPercent, Boole UseAllSubmeshes)
575  {
576  Graphics::Mesh* ObjectMesh = Graphics::MeshManager::GetSingletonPtr()->LoadMesh(MeshName,Group);
577  return this->PerformConvexDecomposition(Name,ObjectMesh,Depth,CPercent,PPercent,UseAllSubmeshes);
578  }
579 
580  ///////////////////////////////////////////////////////////////////////////////
581  // Shape Saving/Loading Utilities
582 
584  {
585  /// @todo Replace this stack allocated stream for one initialized from the Resource Manager, after the system is ready.
586  Resource::FileStream ShapesStream( FileName, Resource::ResourceManager::GetSingletonPtr()->GetAssetPath(FileName,Group) );
587  XML::Document ShapesDoc;
588  XML::ParseResult DocResult = ShapesDoc.Load(ShapesStream);
589  if( DocResult.Status != XML::StatusOk ) {
590  MEZZ_EXCEPTION(ExceptionBase::SYNTAX_ERROR_EXCEPTION_XML,"Failed to parse XML file \"" + FileName + "\".");
591  }
592  XML::Node ShapesRoot = ShapesDoc.GetChild("InitializerRoot");
593  if( ShapesRoot.Empty() ) {
594  MEZZ_EXCEPTION(ExceptionBase::SYNTAX_ERROR_EXCEPTION_XML,"Failed to find expected Root node in \"" + FileName + "\".");
595  }
596 
597  for( XML::NodeIterator ShapeIt = ShapesRoot.begin() ; ShapeIt != ShapesRoot.end() ; ++ShapeIt )
598  {
599  CollisionShape* DeSerializedShape = Physics::CreateShape( (*ShapeIt) );
600  this->CollisionShapes.insert( std::pair<String,CollisionShape*>(DeSerializedShape->GetName(),DeSerializedShape) );
601  }
602  }
603 
605  {
606  XML::Document ShapesDoc;
607  XML::Node DeclNode = ShapesDoc.AppendChild(XML::NodeDeclaration);
608  XML::Attribute VerAttrib = DeclNode.AppendAttribute("version");
609 
610  if( DeclNode.SetName("xml") && VerAttrib.SetValue("1.0") ) {
611  XML::Node ShapesRoot = ShapesDoc.AppendChild( "ShapesRoot" );
612  for( ShapeMapIterator ShapeIt = this->CollisionShapes.begin() ; ShapeIt != this->CollisionShapes.end() ; ++ShapeIt )
613  {
614  (*ShapeIt).second->ProtoSerialize( ShapesRoot );
615  }
616 
617  /// @todo Replace this stack allocated stream for one initialized from the Resource Manager, after the system is ready.
618  Resource::FileStream SettingsStream(FileName,".",Resource::SF_Truncate | Resource::SF_Write);
619  ShapesDoc.Save(SettingsStream,"\t",XML::FormatIndent);
620  }else{
621  MEZZ_EXCEPTION(ExceptionBase::INVALID_STATE_EXCEPTION,"Failed to create XML document declaration for file \"" + FileName + "\".");
622  }
623  }
624 
625  void CollisionShapeManager::SaveShapesToXMLFile(const String& FileName, ShapeVector& ShapesToSave)
626  {
627  XML::Document ShapesDoc;
628  XML::Node DeclNode = ShapesDoc.AppendChild(XML::NodeDeclaration);
629  XML::Attribute VerAttrib = DeclNode.AppendAttribute("version");
630 
631  if( DeclNode.SetName("xml") && VerAttrib.SetValue("1.0") ) {
632  XML::Node ShapesRoot = ShapesDoc.AppendChild( "ShapesRoot" );
633  for( ShapeVectorIterator ShapeIt = ShapesToSave.begin() ; ShapeIt != ShapesToSave.end() ; ++ShapeIt )
634  {
635  (*ShapeIt)->ProtoSerialize( ShapesRoot );
636  }
637 
638  /// @todo Replace this stack allocated stream for one initialized from the Resource Manager, after the system is ready.
639  Resource::FileStream SettingsStream(FileName,".",Resource::SF_Truncate | Resource::SF_Write);
640  ShapesDoc.Save(SettingsStream,"\t",XML::FormatIndent);
641  }else{
642  MEZZ_EXCEPTION(ExceptionBase::INVALID_STATE_EXCEPTION,"Failed to create XML document declaration for file \"" + FileName + "\".");
643  }
644  }
645 
647  {
648  btBulletWorldImporter Importer;
649  Ogre::DataStreamPtr Stream = Ogre::ResourceGroupManager::getSingleton().openResource(FileName,Group);
650  char* buffer = new char[Stream->size()];
651  Stream->read((void*)buffer, Stream->size());
652  if(!Importer.loadFileFromMemory(buffer, Stream->size()))
653  {
654  MEZZ_EXCEPTION(ExceptionBase::IO_FILE_EXCEPTION,"Failed to load file: " + FileName + ".")
655  }
656  delete[] buffer;
657  for( Whole X = 0 ; X < Importer.getNumCollisionShapes() ; ++X )
658  {
659  btCollisionShape* Shape = Importer.getCollisionShapeByIndex(X);
660  const char* MaybeAName = Importer.getNameForPointer((void*)Shape);
661  String Name;
662  if(MaybeAName)
663  {
664  Name = String(MaybeAName);
665  ShapeMapIterator it = this->CollisionShapes.find(Name);
666  if(it == this->CollisionShapes.end())
667  {
668  CollisionShape* NewShape = this->WrapShape(Name,Shape);
669  this->CollisionShapes.insert( std::pair<String,CollisionShape*>(Name,NewShape) );
670  }
671  }else{
672  static Whole NameCount = 0;
673  Name = String("Unnamed") += StringTools::ConvertToString(NameCount++);
674  CollisionShape* NewShape = this->WrapShape(Name,Shape);
675  this->UnnamedShapes.push_back(NewShape);
676  }
677  }
678  }
679 
681  {
682  btDefaultSerializer* BulletSerializer = new btDefaultSerializer(1024*1024*5);
683  BulletSerializer->startSerialization();
684  for( ShapeMapIterator it = this->CollisionShapes.begin() ; it != this->CollisionShapes.end() ; it++ )
685  {
686  CollisionShape* Shape = (*it).second;
687  BulletSerializer->registerNameForPointer((void*)Shape->_GetInternalShape(),(*it).first.c_str());
688  int len = Shape->_GetInternalShape()->calculateSerializeBufferSize();
689  btChunk* chunk = BulletSerializer->allocate(len,1);
690  const char* structType = Shape->_GetInternalShape()->serialize(chunk->m_oldPtr, BulletSerializer);
691  BulletSerializer->finalizeChunk(chunk,structType,BT_SHAPE_CODE,Shape->_GetInternalShape());
692  }
693  BulletSerializer->finishSerialization();
694  FILE* f2 = fopen(FileName.c_str(),"wb");
695  fwrite(BulletSerializer->getBufferPointer(),BulletSerializer->getCurrentBufferSize(),1,f2);
696  fclose(f2);
697  }
698 
700  {
701  btDefaultSerializer* BulletSerializer = new btDefaultSerializer(1024*1024*5);
702  BulletSerializer->startSerialization();
703  for( ShapeVectorIterator it = ShapesToSave.begin() ; it != ShapesToSave.end() ; it++ )
704  {
705  Physics::CollisionShape* Shape = (*it);
706  BulletSerializer->registerNameForPointer((void*)Shape->_GetInternalShape(),(*it)->GetName().c_str());
707  int len = Shape->_GetInternalShape()->calculateSerializeBufferSize();
708  btChunk* chunk = BulletSerializer->allocate(len,1);
709  const char* structType = Shape->_GetInternalShape()->serialize(chunk->m_oldPtr, BulletSerializer);
710  BulletSerializer->finalizeChunk(chunk,structType,BT_SHAPE_CODE,Shape->_GetInternalShape());
711  }
712  BulletSerializer->finishSerialization();
713  FILE* f2 = fopen(FileName.c_str(),"wb");
714  fwrite(BulletSerializer->getBufferPointer(),BulletSerializer->getCurrentBufferSize(),1,f2);
715  fclose(f2);
716  }
717 
718  ///////////////////////////////////////////////////////////////////////////////
719  // Unnamed Shape Management
720 
722  {
723  return this->UnnamedShapes;
724  }
725 
727  {
728  for( ShapeVectorIterator ShapeIt = this->UnnamedShapes.begin() ; ShapeIt != this->UnnamedShapes.end() ; ++ShapeIt )
729  {
730  if( (*ShapeIt) == Shape ) {
731  this->UnnamedShapes.erase( ShapeIt );
732  break;
733  }
734  }
735 
736  ShapeMapIterator NaIt = this->CollisionShapes.find(NewName);
737  if(NaIt != this->CollisionShapes.end()) {
738  MEZZ_EXCEPTION(ExceptionBase::II_DUPLICATE_IDENTITY_EXCEPTION,"Attempting to assign non-unique name to an unnamed Collision Shape.");
739  }
740 
741  Shape->_SetShapeName(NewName);
742  this->CollisionShapes.insert( std::pair<String,CollisionShape*>(NewName,Shape) );
743  }
744 
745  ///////////////////////////////////////////////////////////////////////////////
746  // Utility
747 
749  { Initialized = true; }
750 
752  { Initialized = false; }
753 
754  ///////////////////////////////////////////////////////////////////////////////
755  // Type Identifier Methods
756 
759 
762 
763  ///////////////////////////////////////////////////////////////////////////////
764  // DefaultCollisionShapeManagerFactory Methods
765 
767  { }
768 
770  { }
771 
774 
777 
779  {
781  /// @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.
783  }else return new CollisionShapeManager();
784  }
785 
787  {
789  /// @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.
791  }else return new CollisionShapeManager(XMLNode);
792  }
793 
795  { delete ToBeDestroyed; }
796  }//Physics
797 }//Mezzanine
798 
799 #endif
This is the base class for all collision shapes.
virtual Whole GetNumStoredShapes()
Gets the number of stored shapes in this manager.
Attribute AppendAttribute(const Char8 *Name)
Creates an Attribute and puts it at the end of this Nodes attributes.
Thrown when duplicates of teh same identity string exist.
Definition: exception.h:95
A light-weight handle for manipulating attributes in DOM tree.
Definition: attribute.h:74
virtual void LoadAllShapesFromBinaryFile(const String &FileName, const String &Group)
Loads all shapes saved in an existing binary file, and stores them in this manager.
Clear the contents of the file when opening. Note that this will also create the file if it's not fou...
Definition: datastream.h:73
A triangle mesh collsion shape based on a graphics mesh.
bool Boole
Generally acts a single bit, true or false.
Definition: datatypes.h:173
virtual void LoadAllShapesFromXMLFile(const String &FileName, const String &Group)
Loads all shapes saved in an existing XML file, and stores them in this manager.
A physics shape comprised of multiple sphere's placed in local space.
ManagerType
A listing of Manager Types.
Definition: managerbase.h:65
EntresolManager * CreateManager(const NameValuePairList &Params)
Creates a manager of the type represented by this factory.
CollisionShape * CreateShape(CollisionShape::ShapeType ShapeToCreate, const String &Name_, btCollisionShape *ShapeToModel)
Create A shape of a type and optionally model it after an example.
String ConvertToString(const Vector2 &ToConvert)
Converts a Vector2 into a string.
Definition: stringtool.cpp:291
static const String ImplementationName
A String containing the name of this manager implementation.
static const ManagerBase::ManagerType InterfaceType
A ManagerType enum value used to describe the type of interface/functionality this manager provides...
ShapeMapIterator EndCollisionShape()
Gets an Iterator to one passed the last CollisionShape in this manager.
ShapeVector::iterator ShapeVectorIterator
Vector Iterator type for CollisionShape instances stored by this class.
Thrown when and XML document is being parsed but is invalid.
Definition: exception.h:100
#define MEZZ_EXCEPTION(num, desc)
An easy way to throw exceptions with rich information.
Definition: exception.h:3048
This class is used to check and modify the properties of a graphics mesh.
Definition: mesh.h:63
Thrown when we just have not coded a thing yet, but we knew what the API should look like...
Definition: exception.h:117
virtual DynamicMeshCollisionShape * GenerateDynamicTriMesh(const String &Name, Graphics::Mesh *ObjectMesh, Boole UseAllSubmeshes=false)
Generates a mesh shape for dynamic objects.
A triangle mesh collsion shape based on a graphics mesh.
Ogre::MeshPtr _GetInternalMesh() const
Gets the internal Mesh pointer.
Definition: mesh.cpp:151
virtual void DestroyShape(CollisionShape *Shape)
Removes a shape from this manager and deletes it.
Declaration of FileStream.
virtual ~CollisionShapeManager()
Class destructor.
virtual String GetImplementationTypeName() const
This Allows any manager name to be sent to a stream. Primarily used for logging.
virtual void DestroyAllShapes()
Removes all shapes from the manager and then deletes them.
virtual btCollisionShape * _GetInternalShape() const
Gets the internal shape pointer this collision shape is based on.
A simple convex shape built from a low number of points in local space.
virtual void StoreShape(CollisionShape *Shape)
Stores a pre-made shape in this manager.
virtual void RemoveAllShapes()
Removes all shapes from the manager without deleting them.
ManagerBase::ManagerType GetManagerType() const
Gets the type of manager that is created by this factory.
bool Empty() const
Is this storing anything at all?
ParseResult Load(std::basic_istream< char, std::char_traits< char > > &stream, unsigned int options=ParseDefault, Encoding DocumentEncoding=EncodingAuto)
Load XML from a stream.
ShapeMap CollisionShapes
This stores the names and collision Shapes.
virtual void Initialize()
Configures this manager for use prior to entering the main loop.
std::vector< CollisionShape * > ShapeVector
Vector container type for CollisionShape storage by this class.
virtual void SaveAllStoredShapesToXMLFile(const String &FileName)
Takes all the shapes currently stored this manager and saves them to a XML file.
ShapeVector & GetUnnamedShapes()
Returns a vector of unnamed shapes stored in this manager.
This is returned to indicated there where no issues parsing the XML document.
void SetNameForUnnamedShape(const String &NewName, CollisionShape *Shape)
Assigns a name to an unnamed shape.
float Real
A Datatype used to represent a real floating point number.
Definition: datatypes.h:141
virtual void SaveShapesToXMLFile(const String &FileName, ShapeVector &ShapesToSave)
Saves all shapes contained in a vector and saves them to a XML file.
void Save(Writer &WriterInstance, const Char8 *indent="\t", unsigned int flags=FormatDefault, Encoding DocumentEncoding=EncodingAuto) const
Save XML document to WriterInstance.
virtual CollisionShape * GetShape(const String &Name)
Gets a shape already stored in this manager.
bool SetValue(const Char8 *rhs)
Set the value of this.
static Boole SingletonValid()
Checks to see if the singleton pointer is valid.
Definition: singleton.h:110
virtual void SaveAllStoredShapesToBinaryFile(const String &FileName)
Takes all the shapes currently stored this manager and saves them to a binary file.
bool SetName(const Char8 *rhs)
Set the name of .
static MeshManager * GetSingletonPtr()
Fetches a pointer to the singleton.
Definition: singleton.h:97
This is the base class for all managers that do no describe properties of a single world...
Permit write operations on the stream.
Definition: datastream.h:69
Child node iterator (a bidirectional iterator over a collection of Node)
Definition: nodeiterator.h:77
virtual void AddChildShape(CollisionShape *Child, const Vector3 &ChildLocation, const Quaternion &ChildRotation)
Adds a shape to this compound shape.
Thrown when there is an unknown issue with a file.
Definition: exception.h:74
A light-weight handle for manipulating nodes in DOM tree.
Definition: node.h:89
iterator begin() const
Get a Child node iterator that references the first child Node.
iterator end() const
Get a Child node iterator that references one past the last child Node.
ProcessDepth Depth
The current process depth as interpretted by Main.
Definition: mezztest.cpp:82
virtual void RemoveShape(CollisionShape *Shape)
Removes a shape from this manager without deleting it.
virtual CompoundCollisionShape * PerformConvexDecomposition(const String &Name, Graphics::Mesh *ObjectMesh, Whole Depth, Real CPercent, Real PPercent, Boole UseAllSubmeshes=false)
Generates a compound shape of Convex Hulls from a provided mesh.
The defintion of the Resource Manager.
Troubleshooting data intended to help troublshoot XML parsing errors.
Definition: parseresult.h:71
virtual void Deinitialize()
Removes this manager from any necessary configuration so it can be safely disposed of...
std::list< NameValuePair > NameValuePairList
This is a datatype mostly used for describing settings or parameters that can't be declared in advanc...
Definition: datatypes.h:206
virtual void SaveShapesToBinaryFile(const String &FileName, ShapeVector &ShapesToSave)
Saves all shapes contained in a vector and saves them to a binary file.
Thrown when the available information should have worked but failed for unknown reasons.
Definition: exception.h:113
virtual ConvexHullCollisionShape * GenerateConvexHull(const String &Name, Graphics::Mesh *ObjectMesh, Boole UseAllSubmeshes=false)
Generates a Convex Hull from a provided mesh.
A collision shape for soft proxies.
ParseStatus Status
Parsing status ( see ParseStatus )
Definition: parseresult.h:74
ShapeMap::const_iterator ConstShapeMapIterator
Const Map Iterator type for CollisionShape instances stored by this class.
The root node of any xml hierarchy is a Document.
Definition: document.h:83
btTriangleMesh * CreateBulletTrimesh(Graphics::Mesh *ObjectMesh, Boole UseAllSubmeshes)
Creates a TriMesh to be used in TriMesh based collision shapes.
virtual StaticMeshCollisionShape * GenerateStaticTriMesh(const String &Name, Graphics::Mesh *ObjectMesh, Boole UseAllSubmeshes=false)
Generates a mesh shape for static objects.
virtual void _SetShapeName(const String &NewName)
Sets the name of this collision shape.
This is used to represent a point in space, or a vector through space.
Definition: vector3.h:77
Document declaration, i.e. ''.
This represents a stream to a file on disk using the C++ file stream API.
Definition: filestream.h:56
ShapeVector UnnamedShapes
Stores shapes that have not been given a name.
The bulk of the engine components go in this namspace.
Definition: actor.cpp:56
unsigned long Whole
Whole is an unsigned integer, it will be at least 32bits in size.
Definition: datatypes.h:151
A Flat wall/floor of limitless size.
virtual ManagerBase::ManagerType GetInterfaceType() const
This returns the type of this manager.
CountedPtr< DataStream > DataStreamPtr
This is a convenience type for a data stream in a counted pointer.
Definition: datastream.h:383
ShapeMap::iterator ShapeMapIterator
Map Iterator type for CollisionShape instances stored by this class.
String GetManagerImplName() const
Gets the name of the manager that is created by this factory.
void DestroyManager(EntresolManager *ToBeDestroyed)
Destroys a Manager created by this factory.
This manager is for the storage of all shapes and creation of mesh shapes.
Node AppendChild(NodeType Type=NodeElement)
Creates a Node and makes it a child of this one.
ShapeMapIterator BeginCollisionShape()
Gets an Iterator to the first CollisionShape in this manager.
CollisionShape * WrapShape(const String &Name, btCollisionShape *InternalShape)
Creates a wrapper for an internal bullet shape.
std::string String
A datatype used to a series of characters.
Definition: datatypes.h:159
A series of values that store hieght in a grid like fashion.
A collision shape composed of many other collision shapes placed and oriented in local space...
Node GetChild(const Char8 *Name) const
Attempt to get a child Node with a given name.
virtual const String & GetName() const
Gets the name of this shape.
const unsigned int FormatIndent
Indent the nodes that are written to output stream with as many indentation strings as deep the node ...
Boole Initialized
Simple Boole indicating whether or not this manager has been initialized.
Definition: managerbase.h:111