MezzanineEngine 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
rigidproxy.cpp
1 // © Copyright 2010 - 2012 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 _rigidproxy_cpp
41 #define _rigidproxy_cpp
42 
43 #include "Physics/rigidproxy.h"
44 #include "Physics/collisionshape.h"
45 #include "Physics/physicsmanager.h"
46 #include "Physics/collisionshapemanager.h"
47 
48 #include "enumerations.h"
49 #include "stringtool.h"
50 
51 #include "Internal/motionstate.h.cpp"
52 
53 #include <btBulletDynamicsCommon.h>
54 #include <BulletSoftBody/btSoftRigidDynamicsWorld.h>
55 
56 namespace Mezzanine
57 {
58  namespace Physics
59  {
60  RigidProxy::RigidProxy(const Real Mass, PhysicsManager* Creator) :
61  CollidableProxy(Creator),
62  PhysicsRigidBody(NULL)
63  {
64  this->CreateRigidObject(Mass);
65  }
66 
67  RigidProxy::RigidProxy(const XML::Node& SelfRoot, PhysicsManager* Creator) :
68  CollidableProxy(Creator),
69  PhysicsRigidBody(NULL)
70  {
71  this->CreateRigidObject(1);
72  this->ProtoDeSerialize(SelfRoot);
73  }
74 
76  {
77  if( this->IsInWorld() )
78  this->RemoveFromWorld();
79 
80  delete this->PhysicsRigidBody->getMotionState();
81  delete this->PhysicsRigidBody;
82  }
83 
85  {
86  this->PhysicsRigidBody = new btRigidBody(Mass, NULL/* MotionState */, NULL/* CollisionShape */);
87  this->PhysicsRigidBody->setMotionState( new Internal::MultiMotionState( this ) );
88  this->PhysicsRigidBody->setUserPointer( static_cast<CollidableProxy*>( this ) );
89  if(0.0 == Mass) {
90  this->PhysicsRigidBody->setCollisionFlags( btCollisionObject::CF_STATIC_OBJECT );
91  this->CollisionGroup = Physics::CF_StaticFilter;
92  this->CollisionMask = Physics::CF_AllFilter & ~Physics::CF_StaticFilter;
93  }else{
94  this->PhysicsRigidBody->setCollisionFlags( this->PhysicsRigidBody->getCollisionFlags() & (~btCollisionObject::CF_STATIC_OBJECT) );
95  // Use default group and mask
96  }
97  this->SetGravity( this->Manager->GetWorldGravity() );
98  }
99 
100  ///////////////////////////////////////////////////////////////////////////////
101  // Utility
102 
104  {
105  return Mezzanine::PT_Physics_RigidProxy;
106  }
107 
109  {
110  if( !this->IsInWorld() ) {
111  // Preserve gravity when adding
112  Vector3 Grav = this->GetGravity();
113  this->Manager->_GetPhysicsWorldPointer()->addRigidBody( this->PhysicsRigidBody, this->CollisionGroup, this->CollisionMask );
114  this->SetGravity(Grav);
115  }
116  }
117 
119  {
120  if( this->IsInWorld() ) {
121  this->Manager->_GetPhysicsWorldPointer()->removeRigidBody( this->PhysicsRigidBody );
122  }
123  }
124 
125  ///////////////////////////////////////////////////////////////////////////////
126  // Collision Settings
127 
129  {
130  if( Shape != NULL ) {
131  if(CollisionShape::ST_StaticTriMesh != Shape->GetType()) {
132  Real Mass = this->PhysicsRigidBody->getInvMass();
133  if(0 != Mass) {
134  Mass = 1 / Mass;
135  }
136  btVector3 Inertia(0,0,0);
137  Shape->_GetInternalShape()->calculateLocalInertia(Mass,Inertia);
138  this->PhysicsRigidBody->setMassProps(Mass,Inertia);
140  this->PhysicsRigidBody->updateInertiaTensor();
141  }else{
143  }
144  CollisionShapeManager::GetSingletonPtr()->StoreShape(Shape);
145  }else{
147  }
148  }
149 
150  ///////////////////////////////////////////////////////////////////////////////
151  // Movement Factors
152 
154  { this->PhysicsRigidBody->setLinearFactor(Factor.GetBulletVector3()); }
155 
157  { return Vector3(this->PhysicsRigidBody->getLinearFactor()); }
158 
160  { this->PhysicsRigidBody->setAngularFactor(Factor.GetBulletVector3()); }
161 
163  { return Vector3(this->PhysicsRigidBody->getAngularFactor()); }
164 
165  ///////////////////////////////////////////////////////////////////////////////
166  // Rigid Physics Properties
167 
168  void RigidProxy::SetMass(Real NewMass)
169  { this->PhysicsRigidBody->setMassProps( NewMass, btVector3(1,1,1) / this->PhysicsRigidBody->getInvInertiaDiagLocal() ); }
170 
172  { return ( this->PhysicsRigidBody->getInvMass() != 0 ? 1 / this->PhysicsRigidBody->getInvMass() : 0 ); }
173 
174  void RigidProxy::SetDamping(const Real LinDamping, const Real AngDamping)
175  { this->PhysicsRigidBody->setDamping( LinDamping, AngDamping ); }
176 
178  { return this->PhysicsRigidBody->getLinearDamping(); }
179 
181  { return this->PhysicsRigidBody->getAngularDamping(); }
182 
184  { this->PhysicsRigidBody->setLinearVelocity( LinVel.GetBulletVector3() ); }
185 
187  { return Vector3(this->PhysicsRigidBody->getLinearVelocity()); }
188 
190  { this->PhysicsRigidBody->setAngularVelocity( AngVel.GetBulletVector3() ); }
191 
193  { return Vector3(this->PhysicsRigidBody->getAngularVelocity()); }
194 
195  void RigidProxy::SetGravity(const Vector3& Gravity)
196  { this->PhysicsRigidBody->setGravity( Gravity.GetBulletVector3() ); }
197 
199  { return Vector3(this->PhysicsRigidBody->getGravity()); }
200 
201  void RigidProxy::ApplyForce(const Vector3& Force)
202  { this->PhysicsRigidBody->applyCentralForce( Force.GetBulletVector3() ); }
203 
205  { return Vector3(this->PhysicsRigidBody->getTotalForce()); }
206 
207  void RigidProxy::ApplyTorque(const Vector3& Torque)
208  { this->PhysicsRigidBody->applyTorque( Torque.GetBulletVector3() ); }
209 
211  { return Vector3(this->PhysicsRigidBody->getTotalTorque()); }
212 
213  ///////////////////////////////////////////////////////////////////////////////
214  // Sticky Data
215 
216  /*
217  void RigidProxy::SetStickyData(const Whole& MaxNumContacts)
218  {
219  if(MaxNumContacts > 0) StickyContacts->MaxNumContacts = MaxNumContacts;
220  else ClearStickyContacts();
221  }
222 
223  void RigidProxy::ClearStickyContacts()
224  {
225  if(0 == StickyContacts->StickyConstraints.size())
226  return;
227  btDiscreteDynamicsWorld* BulletWorld = Entresol::GetSingletonPtr()->GetPhysicsManager()->GetPhysicsWorldPointer();
228  for( std::vector<StickyConstraint*>::iterator SCit = StickyContacts->StickyConstraints.begin() ; SCit != StickyContacts->StickyConstraints.end() ; ++SCit )
229  {
230  BulletWorld->removeConstraint((*SCit)->GetConstraintBase());
231 
232  ActorRigid* OtherActor = (*SCit)->GetActorA() != Parent ? (*SCit)->GetActorA() : (*SCit)->GetActorB();
233  StickyData* OtherSettings = OtherActor->GetPhysicsSettings()->GetStickyData();
234  for( std::vector<StickyConstraint*>::iterator SCit2 = OtherSettings->StickyConstraints.begin() ; SCit2 != OtherSettings->StickyConstraints.end() ; ++SCit2 )
235  {
236  if( (*SCit) == (*SCit2) )
237  {
238  OtherSettings->StickyConstraints.erase(SCit2);
239  break;
240  }
241  }
242 
243  delete (*SCit);
244  }
245  StickyContacts->StickyConstraints.clear();
246  StickyContacts->CreationQueue.clear();
247  }
248 
249  StickyData* RigidProxy::GetStickyData() const
250  { return StickyContacts; }
251  */
252 
253  ///////////////////////////////////////////////////////////////////////////////
254  // Transform Syncronization
255 
257  { static_cast<Internal::MultiMotionState*>( this->PhysicsRigidBody->getMotionState() )->AddSyncObject(ToBeAdded); }
258 
260  { return static_cast<Internal::MultiMotionState*>( this->PhysicsRigidBody->getMotionState() )->GetSyncObject(Index); }
261 
263  { return static_cast<Internal::MultiMotionState*>( this->PhysicsRigidBody->getMotionState() )->GetNumSyncObjects(); }
264 
266  { static_cast<Internal::MultiMotionState*>( this->PhysicsRigidBody->getMotionState() )->RemoveSyncObject(ToBeRemoved); }
267 
269  { static_cast<Internal::MultiMotionState*>( this->PhysicsRigidBody->getMotionState() )->RemoveAllSyncObjects(); }
270 
271  ///////////////////////////////////////////////////////////////////////////////
272  // Serialization
273 
275  {
276  this->CollidableProxy::ProtoSerialize(SelfRoot);
277  // We're at the base implementation, so no calling of child implementations
278  XML::Node PropertiesNode = SelfRoot.AppendChild( RigidProxy::GetSerializableName() + "Properties" );
279 
280  if( PropertiesNode.AppendAttribute("Version").SetValue("1") &&
281  PropertiesNode.AppendAttribute("Mass").SetValue( this->GetMass() ) &&
282  PropertiesNode.AppendAttribute("LinearDamping").SetValue( this->GetLinearDamping() ) &&
283  PropertiesNode.AppendAttribute("AngularDamping").SetValue( this->GetAngularDamping() ) )
284  {
285  XML::Node LinVelNode = PropertiesNode.AppendChild("LinearVelocty");
286  this->GetLinearVelocity().ProtoSerialize( LinVelNode );
287 
288  XML::Node AngVelNode = PropertiesNode.AppendChild("AngularVelocity");
289  this->GetAngularVelocity().ProtoSerialize( AngVelNode );
290 
291  XML::Node LinFactNode = PropertiesNode.AppendChild("LinearFactor");
292  this->GetLinearMovementFactor().ProtoSerialize( LinFactNode );
293 
294  XML::Node AngFactNode = PropertiesNode.AppendChild("AngularFactor");
295  this->GetAngularMovementFactor().ProtoSerialize( AngFactNode );
296 
297  XML::Node ForceNode = PropertiesNode.AppendChild("Force");
298  this->GetAppliedForce().ProtoSerialize( ForceNode );
299 
300  XML::Node TorqueNode = PropertiesNode.AppendChild("Torque");
301  this->GetAppliedTorque().ProtoSerialize( TorqueNode );
302 
303  XML::Node GravityNode = PropertiesNode.AppendChild("Gravity");
304  this->GetGravity().ProtoSerialize( GravityNode );
305 
306  return;
307  }else{
308  SerializeError("Create XML Attribute Values",RigidProxy::GetSerializableName() + "Properties",true);
309  }
310  }
311 
313  {
314  this->PhysicsRigidBody->clearForces();
315  this->CollidableProxy::ProtoDeSerialize(SelfRoot);
316  // We're at the base implementation, so no calling of child implementations
317  XML::Attribute CurrAttrib;
318  XML::Node PropertiesNode = SelfRoot.GetChild( RigidProxy::GetSerializableName() + "Properties" );
319 
320  if( !PropertiesNode.Empty() ) {
321  if(PropertiesNode.GetAttribute("Version").AsInt() == 1) {
322  Real LinDam = 0, AngDam = 0;
323 
324  CurrAttrib = PropertiesNode.GetAttribute("Mass");
325  if( !CurrAttrib.Empty() )
326  this->SetMass( CurrAttrib.AsReal() );
327 
328  CurrAttrib = PropertiesNode.GetAttribute("LinearDamping");
329  if( !CurrAttrib.Empty() )
330  LinDam = CurrAttrib.AsReal();
331 
332  CurrAttrib = PropertiesNode.GetAttribute("AngularDamping");
333  if( !CurrAttrib.Empty() )
334  AngDam = CurrAttrib.AsReal();
335 
336  this->SetDamping(LinDam,AngDam);
337 
338  // Get the properties that need their own nodes
339  XML::Node LinVelNode = PropertiesNode.GetChild("LinearVelocty").GetFirstChild();
340  if( !LinVelNode.Empty() ) {
341  Vector3 LinVel(LinVelNode);
342  this->SetLinearVelocity(LinVel);
343  }
344 
345  XML::Node AngVelNode = PropertiesNode.GetChild("AngularVelocity").GetFirstChild();
346  if( !AngVelNode.Empty() ) {
347  Vector3 AngVel(AngVelNode);
348  this->SetAngularVelocity(AngVel);
349  }
350 
351  XML::Node LinFactNode = PropertiesNode.GetChild("LinearFactor").GetFirstChild();
352  if( !LinFactNode.Empty() ) {
353  Vector3 LinFact(LinFactNode);
354  this->SetLinearMovementFactor(LinFact);
355  }
356 
357  XML::Node AngFactNode = PropertiesNode.GetChild("AngularFactor").GetFirstChild();
358  if( !AngFactNode.Empty() ) {
359  Vector3 AngFact(AngFactNode);
360  this->SetAngularMovementFactor(AngFact);
361  }
362 
363  XML::Node ForceNode = PropertiesNode.GetChild("Force").GetFirstChild();
364  if( !ForceNode.Empty() ) {
365  Vector3 Force(ForceNode);
366  this->ApplyForce(Force);
367  }
368 
369  XML::Node TorqueNode = PropertiesNode.GetChild("Torque").GetFirstChild();
370  if( !TorqueNode.Empty() ) {
371  Vector3 Torque(TorqueNode);
372  this->ApplyTorque(Torque);
373  }
374 
375  XML::Node GravityNode = PropertiesNode.GetChild("Gravity").GetFirstChild();
376  if( !GravityNode.Empty() ) {
377  Vector3 Gravity(GravityNode);
378  this->SetGravity(Gravity);
379  }
380  }else{
381  MEZZ_EXCEPTION(Exception::INVALID_VERSION_EXCEPTION,"Incompatible XML Version for " + (RigidProxy::GetSerializableName() + "Properties" ) + ": Not Version 1.");
382  }
383  }else{
384  MEZZ_EXCEPTION(Exception::II_IDENTITY_NOT_FOUND_EXCEPTION,RigidProxy::GetSerializableName() + "Properties" + " was not found in the provided XML node, which was expected.");
385  }
386  }
387 
389  { return RigidProxy::GetSerializableName(); }
390 
392  { return "RigidProxy"; }
393 
394  ///////////////////////////////////////////////////////////////////////////////
395  // Internal Methods
396 
397  btRigidBody* RigidProxy::_GetPhysicsObject() const
398  { return this->PhysicsRigidBody; }
399 
400  btCollisionObject* RigidProxy::_GetBasePhysicsObject() const
401  { return this->PhysicsRigidBody; }
402  }// Physics
403 }// Mezzanine
404 
405 #endif