MezzanineEngine 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
collisionshape.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 _collisionshape_cpp
41 #define _collisionshape_cpp
42 
43 #include "Physics/collisionshape.h"
44 #include "collisionshapemanager.h"
45 #include "stringtool.h"
46 
47 // For Utility functions
48 #include "Physics/boxcollisionshape.h"
49 #include "Physics/capsulecollisionshape.h"
50 #include "Physics/conecollisionshape.h"
51 #include "Physics/convexhullcollisionshape.h"
52 #include "Physics/cylindercollisionshape.h"
53 #include "Physics/multispherecollisionshape.h"
54 #include "Physics/spherecollisionshape.h"
55 #include "Physics/dynamicmeshcollisionshape.h"
56 #include "Physics/heightfieldcollisionshape.h"
57 #include "Physics/planecollisionshape.h"
58 #include "Physics/softcollisionshape.h"
59 #include "Physics/staticmeshcollisionshape.h"
60 #include "Physics/compoundcollisionshape.h"
61 
62 #include "btBulletDynamicsCommon.h"
63 
64 namespace Mezzanine
65 {
66  namespace Physics
67  {
68  /////////////////////////////////////////
69  // CollisionShape Functions
70 
72  ShapeBase(NULL)
73  {
74  }
75 
77  {
78  }
79 
80  ///////////////////////////////////////////////////////////////////////////////
81  // Utility
82 
84  {
85  return this->Name;
86  }
87 
88  ///////////////////////////////////////////////////////////////////////////////
89  // Configuration Methods
90 
91  void CollisionShape::SetMargin(const Real& Margin)
92  {
93  this->ShapeBase->setMargin(Margin);
94  }
95 
97  {
98  return this->ShapeBase->getMargin();
99  }
100 
101  void CollisionShape::SetScaling(const Vector3& Scaling)
102  {
103  this->ShapeBase->setLocalScaling(Scaling.GetBulletVector3());
104  }
105 
107  {
108  return Vector3(this->ShapeBase->getLocalScaling());
109  }
110 
111  ///////////////////////////////////////////////////////////////////////////////
112  // Serialization
113 
114  void CollisionShape::ProtoSerialize(XML::Node& CurrentRoot) const
115  {
116  XML::Node CollisionNode = CurrentRoot.AppendChild(this->CollisionShape::SerializableName());
117  if (!CollisionNode) { SerializeError("create CollisionNode",this->CollisionShape::SerializableName());}
118 
119  XML::Attribute Version = CollisionNode.AppendAttribute("Version");
120  if (Version)
121  { Version.SetValue(1); }
122  else
123  { SerializeError("Create Version Attribute", SerializableName()); }
124 
125  XML::Attribute NameAttr = CollisionNode.AppendAttribute("Name");
126  if(!NameAttr)
127  { SerializeError("Create Name Attribute", SerializableName()); }
128  NameAttr.SetValue(this->GetName());
129 
130  XML::Attribute MarginAttr = CollisionNode.AppendAttribute("Margin");
131  if(!MarginAttr)
132  { SerializeError("Create Margin Attribute", SerializableName()); }
133  MarginAttr.SetValue(this->GetMargin());
134 
135  XML::Node ScalingNode = CollisionNode.AppendChild("Scaling");
136  if (!ScalingNode) { SerializeError("Create Name Attribute", SerializableName()); }
137  this->GetScaling().ProtoSerialize(ScalingNode);
138  }
139 
141  {
142  if ( Mezzanine::String(OneNode.Name())==this->CollisionShape::SerializableName() )
143  {
144  if(OneNode.GetAttribute("Version").AsInt() == 1)
145  {
146  if(OneNode.GetAttribute("Name"))
147  { this->Name = OneNode.GetAttribute("Name").AsString(); }
148  this->SetMargin(OneNode.GetAttribute("Margin").AsReal());
149 
150  XML::Node ScalingNode = OneNode.GetChild("Scaling").GetFirstChild();
151  if(!ScalingNode)
152  { DeSerializeError("locate Scaling node",SerializableName()); }
153  this->SetScaling(Vector3(ScalingNode));
154  }else{
155  DeSerializeError("find usable serialization version",SerializableName());
156  }
157  }else{
158  DeSerializeError(String("find correct class to deserialize, found a ")+OneNode.Name(),SerializableName());
159  }
160  }
161 
163  { return String("CollisionShape"); }
164 
165  ///////////////////////////////////////////////////////////////////////////////
166  // Internal Methods
167 
169  {
170  this->Name = NewName;
171  }
172 
173  btCollisionShape* CollisionShape::_GetInternalShape() const
174  {
175  return this->ShapeBase;
176  }
177 
178  /////////////////////////////////////////
179  // Utility Functions
180 
181  CollisionShape* CreateShape(CollisionShape::ShapeType ShapeToCreate, const String& Name_, btCollisionShape* ShapeToModel)
182  {
183  if (ShapeToModel)
184  {
185  switch(ShapeToCreate)
186  {
188  return new BoxCollisionShape(Name_,(btBoxShape*)ShapeToModel);
190  return new CapsuleCollisionShape(Name_,(btCapsuleShape*)ShapeToModel);
192  return new ConeCollisionShape(Name_,(btConeShape*)ShapeToModel);
194  return new ConvexHullCollisionShape(Name_,(btConvexHullShape*)ShapeToModel);
196  return new CylinderCollisionShape(Name_,(btCylinderShape*)ShapeToModel);
198  return new MultiSphereCollisionShape(Name_,(btMultiSphereShape*)ShapeToModel);
200  return new SphereCollisionShape(Name_,(btSphereShape*)ShapeToModel);
202  return new DynamicMeshCollisionShape(Name_,(btGImpactMeshShape*)ShapeToModel);
204  return new HeightfieldCollisionShape(Name_,(btHeightfieldTerrainShape*)ShapeToModel);
206  return new PlaneCollisionShape(Name_,(btStaticPlaneShape*)ShapeToModel);
208  return new SoftCollisionShape(Name_,(btSoftBodyCollisionShape*)ShapeToModel);
210  return new StaticMeshCollisionShape(Name_,(btBvhTriangleMeshShape*)ShapeToModel);
211  case CollisionShape::ST_Compound: // holy recursive batman
212  return new CompoundCollisionShape(Name_,(btCompoundShape*)ShapeToModel);
213  default:
214  { MEZZ_EXCEPTION(Exception::PARAMETERS_EXCEPTION,"Attempting to convert an unsupported/unwrapped Collision Shape type into a CollisionShape instance."); }
215  }
216  }else{
217  MEZZ_EXCEPTION(Exception::PARAMETERS_EXCEPTION,"Attempting to convert an empty Internal Collision Shape type into a CollisionShape instance.");
218  }
219  }
220 
222  {
223  CollisionShape::ShapeType ShapeToCreate = StringToShapeType(OneNode.Name());
224 
225  String Name_("Defunct");
226 
227  switch(ShapeToCreate)
228  {
230  return new BoxCollisionShape(OneNode);
232  return new CapsuleCollisionShape(OneNode);
234  return new ConeCollisionShape(OneNode);
236  return new ConvexHullCollisionShape(OneNode);
238  return new CylinderCollisionShape(OneNode);
240  return new MultiSphereCollisionShape(OneNode);
242  return new SphereCollisionShape(OneNode);
243  case CollisionShape::ST_DynamicTriMesh: /// @todo Complete CreateShape function once DynamicMeshCollisionShape can be deserialized
244  //return new DynamicMeshCollisionShape(Name_,(btGImpactMeshShape*)ShapeToModel);
245  { MEZZ_EXCEPTION(Exception::NOT_IMPLEMENTED_EXCEPTION,"Attempting to convert an unsupported/unwrapped Collision Shape type into a CollisionShape instance, specifically a DynamicMeshCollisionShape."); }
247  return new HeightfieldCollisionShape(Name_);
249  return new PlaneCollisionShape(Name_);
250  case CollisionShape::ST_Soft: /// @todo Complete CreateShape function once SoftCollisionShape can be deserialized
251  //return new SoftCollisionShape(Name_,(btSoftBodyCollisionShape*)ShapeToModel);
252  { MEZZ_EXCEPTION(Exception::NOT_IMPLEMENTED_EXCEPTION,"Attempting to convert an unsupported/unwrapped Collision Shape type into a CollisionShape instance, specifically a SoftCollisionShape."); }
253  case CollisionShape::ST_StaticTriMesh: /// @todo Complete CreateShape function once StaticMeshCollisionShape can be deserialized
254  //return new StaticMeshCollisionShape(Name_,(btBvhTriangleMeshShape*)ShapeToModel);
255  { MEZZ_EXCEPTION(Exception::NOT_IMPLEMENTED_EXCEPTION,"Attempting to convert an unsupported/unwrapped Collision Shape type into a CollisionShape instance, specifically a StaticMeshShape."); }
256  case CollisionShape::ST_Compound: // holy recursive batman
257  return new CompoundCollisionShape(Name_);
258  default:
259  { MEZZ_EXCEPTION(Exception::PARAMETERS_EXCEPTION,"Attempting to convert an unsupported/unwrapped Collision Shape type into a CollisionShape instance."); }
260  }
261  }
262 
264  {
265  switch(InternalShapeType)
266  {
267  case BOX_SHAPE_PROXYTYPE: return CollisionShape::ST_Box;
268  case CAPSULE_SHAPE_PROXYTYPE: return CollisionShape::ST_Capsule;
269  case CONE_SHAPE_PROXYTYPE: return CollisionShape::ST_Cone;
270  case CONVEX_HULL_SHAPE_PROXYTYPE: return CollisionShape::ST_ConvexHull;
271  case CYLINDER_SHAPE_PROXYTYPE: return CollisionShape::ST_Cylinder;
272  case MULTI_SPHERE_SHAPE_PROXYTYPE: return CollisionShape::ST_MultiSphere;
273  case SPHERE_SHAPE_PROXYTYPE: return CollisionShape::ST_Sphere;
274  case GIMPACT_SHAPE_PROXYTYPE: return CollisionShape::ST_DynamicTriMesh;
275  case TERRAIN_SHAPE_PROXYTYPE: return CollisionShape::ST_Heightfield;
276  case STATIC_PLANE_PROXYTYPE: return CollisionShape::ST_Plane;
277  case SOFTBODY_SHAPE_PROXYTYPE: return CollisionShape::ST_Soft;
278  case TRIANGLE_MESH_SHAPE_PROXYTYPE: return CollisionShape::ST_StaticTriMesh;
279  case COMPOUND_SHAPE_PROXYTYPE: return CollisionShape::ST_Compound;
280  default:
281  { MEZZ_EXCEPTION(Exception::PARAMETERS_EXCEPTION,"Attempting to convert an unsupported/unwrapped Internal Collision Shape type into a Physics::CollisionShapeShapeType."); }
282  }
283  }
284 
286  {
287  switch(ShapeToConvert)
288  {
289  case CollisionShape::ST_Box: return String("BoxCollisionShape");
290  case CollisionShape::ST_Capsule: return String("CapsuleCollisionShape");
291  case CollisionShape::ST_Cone: return String("ConeCollisionShape");
292  case CollisionShape::ST_ConvexHull: return String("ConvexHullCollisionShape");
293  case CollisionShape::ST_Cylinder: return String("CylinderCollisionShape");
294  case CollisionShape::ST_MultiSphere: return String("MultiSphereCollisionShape");
295  case CollisionShape::ST_Sphere: return String("SphereCollisionShape");
296  case CollisionShape::ST_DynamicTriMesh: return String("DynamicMeshCollisionShape");
297  case CollisionShape::ST_Heightfield: return String("HeightfieldCollisionShapeString(");
298  case CollisionShape::ST_Plane: return String("PlaneCollisionShape");
299  case CollisionShape::ST_Soft: return String("SoftCollisionShape");
300  case CollisionShape::ST_StaticTriMesh: return String("StaticMeshCollisionShape");
301  case CollisionShape::ST_Compound: return String("CompoundCollisionShape");
302  default:
303  { MEZZ_EXCEPTION(Exception::PARAMETERS_EXCEPTION,"Attempting to convert an unsupported/unwrapped Collision Shape type into a String."); }
304  }
305  }
306 
308  {
309  if(TypeName.size()<5)
310  { MEZZ_EXCEPTION(Exception::PARAMETERS_EXCEPTION,"Attempting to convert a CollisionShape::ShapeType String into a CollisionShape::ShapeType which is too short to be valid."); }
311  switch(TypeName.at(3))
312  {
313  case 'C':
314  if (String("BoxCollisionShape")==TypeName)
315  { return CollisionShape::ST_Box; }
316  else
317  { MEZZ_EXCEPTION(Exception::PARAMETERS_EXCEPTION,"Attempting to convert an invalid CollisionShape::ShapeType String into a CollisionShape::ShapeType 'C'."); }
318  case 's':
319  if (String("CapsuleCollisionShape")==TypeName)
320  { return CollisionShape::ST_Capsule; }
321  else
322  { MEZZ_EXCEPTION(Exception::PARAMETERS_EXCEPTION,"Attempting to convert an invalid CollisionShape::ShapeType String into a CollisionShape::ShapeType 's'."); }
323  case 'e':
324  if (String("SphereCollisionShape")==TypeName)
325  { return CollisionShape::ST_Sphere; }
326  else if (String("ConeCollisionShape")==TypeName)
327  { return CollisionShape::ST_Cone; }
328  else
329  { MEZZ_EXCEPTION(Exception::PARAMETERS_EXCEPTION,"Attempting to convert an invalid CollisionShape::ShapeType String into a CollisionShape::ShapeType 'e'."); }
330  case 'v':
331  if (String("ConvexHullCollisionShape")==TypeName)
333  else
334  { MEZZ_EXCEPTION(Exception::PARAMETERS_EXCEPTION,"Attempting to convert an invalid CollisionShape::ShapeType String into a CollisionShape::ShapeType 'v'."); }
335  case 'i':
336  if (String("CylinderCollisionShape")==TypeName)
337  { return CollisionShape::ST_Cylinder; }
338  else
339  { MEZZ_EXCEPTION(Exception::PARAMETERS_EXCEPTION,"Attempting to convert an invalid CollisionShape::ShapeType String into a CollisionShape::ShapeType 'i'."); }
340  case 't':
341  if (String("StaticMeshCollisionShape")==TypeName)
343  else if (String("MultiSphereCollisionShape")==TypeName)
345  else
346  { MEZZ_EXCEPTION(Exception::PARAMETERS_EXCEPTION,"Attempting to convert an invalid CollisionShape::ShapeType String into a CollisionShape::ShapeType 't'."); }
347  case 'a':
348  if (String("DynamicMeshCollisionShape")==TypeName)
350  else
351  { MEZZ_EXCEPTION(Exception::PARAMETERS_EXCEPTION,"Attempting to convert an invalid CollisionShape::ShapeType String into a CollisionShape::ShapeType 'a'."); }
352  case 'g':
353  if (String("HeightfieldCollisionShapeString")==TypeName)
355  else
356  { MEZZ_EXCEPTION(Exception::PARAMETERS_EXCEPTION,"Attempting to convert an invalid CollisionShape::ShapeType String into a CollisionShape::ShapeType 'g'."); }
357  case 'n':
358  if (String("PlaneCollisionShape")==TypeName)
359  { return CollisionShape::ST_Plane; }
360  else
361  { MEZZ_EXCEPTION(Exception::PARAMETERS_EXCEPTION,"Attempting to convert an invalid CollisionShape::ShapeType String into a CollisionShape::ShapeType 'n'."); }
362  case 'o':
363  if (String("SoftCollisionShape")==TypeName)
364  { return CollisionShape::ST_Soft; }
365  else
366  { MEZZ_EXCEPTION(Exception::PARAMETERS_EXCEPTION,"Attempting to convert an invalid CollisionShape::ShapeType String into a CollisionShape::ShapeType 'o'."); }
367  case 'p':
368  if (String("CompoundCollisionShape")==TypeName)
369  { return CollisionShape::ST_Compound; }
370  else
371  { MEZZ_EXCEPTION(Exception::PARAMETERS_EXCEPTION,"Attempting to convert an invalid CollisionShape::ShapeType String into a CollisionShape::ShapeType 'p'."); }
372  default:
373  { MEZZ_EXCEPTION(Exception::PARAMETERS_EXCEPTION,"Attempting to convert an invalid CollisionShape::ShapeType String into a CollisionShape::ShapeType."); }
374  }
375  }
376 
377  ///////////////////////////////////////
378  // CollisionShapeDeSerializer
380  {
381  XML::Document* Doc = new XML::Document();
382  String OneTag( Mezzanine::XML::GetOneTag(Stream) );
383  if(!Doc->Load(OneTag.c_str()))
384  {
385  delete Doc;
386  MEZZ_EXCEPTION(Exception::PARAMETERS_EXCEPTION,"Could not Deserialize XML Stream which should contain a Collision Shape, XML looked Like: " + OneTag + ".");
387  }
388 
389  CollisionShape* Results = ProtoDeSerialize(Doc->GetFirstChild());
390  delete Doc;
391  return Results;
392  }
393 
395  { return CreateShape(OneNode); }
396 
397  std::istream& CollisionShapeDeSerializer::DeSerialize(std::istream& Stream)
398  {
399  PerformDeSerialization(Stream);
400  return Stream;
401  }
402 
404  { return PerformDeSerialization(Stream); }
405 
407  { return String("Shapes"); }
408 
409  }//Physics
410 }//Mezzanine
411 
412 std::ostream& operator << (std::ostream& stream, const Mezzanine::Physics::CollisionShape& ShapeToSerialize)
413  { Mezzanine::Serialize(stream, ShapeToSerialize); return stream; }
414 
415 std::istream& operator >> (std::istream& stream, Mezzanine::Physics::CollisionShape& x)
416  { return Mezzanine::DeSerialize(stream, x); }
417 
418 void operator >> (const Mezzanine::XML::Node& OneNode, Mezzanine::Physics::CollisionShape& x)
419  { x.ProtoDeSerialize(OneNode); }
420 
421 
422 #endif