MezzanineEngine 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
hingeconstraint.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 _physicshingeconstraint_cpp
41 #define _physicshingeconstraint_cpp
42 
43 #include "Physics/hingeconstraint.h"
44 #include "Physics/rigidproxy.h"
45 
46 #include "stringtool.h"
47 #include "serialization.h"
48 
49 #include <btBulletDynamicsCommon.h>
50 
51 namespace Mezzanine
52 {
53  namespace Physics
54  {
55  ////////////////////////////////////////////////////////////////////////////////
56  // Hinge Constraint Functions
57 
58  btTypedConstraint* HingeConstraint::GetConstraintBase() const
59  { return this->Hinge; }
60 
61  ////////////////////////////////////////////////////////////////////////////////
62  // HingeConstraint Construction and Destruction
63 
64  HingeConstraint::HingeConstraint(RigidProxy* ProxyA, RigidProxy* ProxyB, const Vector3& PivotInA, const Vector3& PivotInB, const Vector3& AxisInA, const Vector3& AxisInB, bool UseReferenceFrameA)
65  {
66  this->SetBodies(ProxyA,ProxyB);
67 
68  btVector3 tempA(AxisInA.GetBulletVector3());
69  btVector3 tempB(AxisInB.GetBulletVector3());
70  this->Hinge = new btHingeConstraint(*(ProxA->_GetPhysicsObject()), *(ProxB->_GetPhysicsObject()), PivotInA.GetBulletVector3(), PivotInB.GetBulletVector3(), tempA, tempB, bool(UseReferenceFrameA));
71  }
72 
73  HingeConstraint::HingeConstraint(RigidProxy* ProxyA, const Vector3& PivotInA, const Vector3& AxisInA, bool UseReferenceFrameA)
74  {
75  this->SetBodies(ProxyA);
76 
77  btVector3 tempA(AxisInA.GetBulletVector3());
78  this->Hinge = new btHingeConstraint(*(ProxA->_GetPhysicsObject()), PivotInA.GetBulletVector3(), tempA, bool(UseReferenceFrameA));
79  }
80 
81  HingeConstraint::HingeConstraint(RigidProxy* ProxyA, RigidProxy* ProxyB, const Vector3& VectorA, const Vector3& VectorB, const Quaternion& QuaternionA, const Quaternion& QuaternionB, bool UseReferenceFrameA)
82  {
83  this->SetBodies(ProxyA,ProxyB);
84 
85  btTransform transa(QuaternionA.GetBulletQuaternion(), VectorA.GetBulletVector3());
86  btTransform transb(QuaternionB.GetBulletQuaternion(), VectorB.GetBulletVector3());
87  this->Hinge = new btHingeConstraint(*(ProxA->_GetPhysicsObject()), *(ProxB->_GetPhysicsObject()), transa, transb, UseReferenceFrameA);
88  }
89 
90  HingeConstraint::HingeConstraint(RigidProxy* ProxyA, RigidProxy* ProxyB, const Transform& TransformA, const Transform& TransformB, bool UseReferenceFrameA)
91  {
92  this->SetBodies(ProxyA,ProxyB);
93  this->Hinge = new btHingeConstraint(*(ProxA->_GetPhysicsObject()), *(ProxB->_GetPhysicsObject()), TransformA.GetBulletTransform(), TransformB.GetBulletTransform(), UseReferenceFrameA);
94  }
95 
96 
98  {
99  if(this->Hinge)
100  delete this->Hinge;
101  }
102 
103  ////////////////////////////////////////////////////////////////////////////////
104  // HingeConstraint Position and Orientation
105 
107  { this->Hinge->getAFrame().setOrigin(Location.GetBulletVector3()); }
108 
110  { this->Hinge->getBFrame().setOrigin(Location.GetBulletVector3()); }
111 
113  { return Vector3(this->Hinge->getAFrame().getOrigin()); }
114 
116  { return Vector3(this->Hinge->getBFrame().getOrigin()); }
117 
119  { this->Hinge->getBFrame().setRotation(Rotation.GetBulletQuaternion()); }
120 
122  { this->Hinge->getBFrame().setRotation(Rotation.GetBulletQuaternion()); }
123 
125  { return Quaternion(this->Hinge->getAFrame().getRotation()); }
126 
128  { return Quaternion(this->Hinge->getBFrame().getRotation()); }
129 
131  { this->Hinge->getAFrame() << TranA; }
132 
134  { this->Hinge->getBFrame() << TranB; }
135 
137  { return Transform(this->Hinge->getAFrame()); }
138 
140  { return Transform(this->Hinge->getBFrame()); }
141 
142  ////////////////////////////////////////////////////////////////////////////////
143  // HingeConstraint Angular Motor
144 
145  void HingeConstraint::EnableMotor(bool EnableMotor, Real TargetVelocity, Real MaxMotorImpulse)
146  { this->Hinge->enableAngularMotor(EnableMotor, TargetVelocity, MaxMotorImpulse); }
147 
148  void HingeConstraint::EnableMotor(bool EnableMotor)
149  { this->Hinge->enableMotor(EnableMotor); }
150 
152  { return this->Hinge->getEnableAngularMotor(); }
153 
155  { this->Hinge->setMaxMotorImpulse(MaxMotorImpulse); }
156 
158  { return this->Hinge->getMaxMotorImpulse(); }
159 
161  { this->Hinge->setMotorTarget(QuatAInB.GetBulletQuaternion(), Dt); }
162 
164  { this->Hinge->setMotorTarget(TargetAngle, Dt); }
165 
167  { this->Hinge->setMotorTargetVelocity(TargetVelocity); }
168 
170  { return this->Hinge->getMotorTargetVelosity(); }
171 
172  ////////////////////////////////////////////////////////////////////////////////
173  // HingeConstraint Limits
174 
175  void HingeConstraint::SetLimit(Real Low, Real High, Real Softness, Real BiasFactor, Real RelaxationFactor)
176  { this->Hinge->setLimit(Low, High, Softness, BiasFactor, RelaxationFactor); }
177 
179  { return this->Hinge->getLowerLimit(); }
180 
182  { return this->Hinge->getUpperLimit(); }
183 
185  { return this->Hinge->getLimitSoftness(); }
186 
188  { return this->Hinge->getLimitBiasFactor(); }
189 
191  { return this->Hinge->getLimitRelaxationFactor(); }
192 
193  ////////////////////////////////////////////////////////////////////////////////
194  // HingeConstraint Details
195 
196  void HingeConstraint::SetAxis(const Vector3& AxisInA)
197  {
198  btVector3 temp(AxisInA.GetBulletVector3());
199  this->Hinge->setAxis(temp);
200  }
201 
203  {
204  return this->Hinge->getHingeAngle();
205  }
206 
208  {
209  Constraint::ParamList Results;
210  if(-1==Axis||5==Axis)
211  {
212  Results.push_back(Con_Stop_ERP);
213  Results.push_back(Con_CFM);
214  Results.push_back(Con_Stop_CFM);
215  }
216  return Results;
217  }
218 
220  {
221  Constraint::AxisList Results;
222  Results.push_back(-1);
223  return Results;
224  }
225 
227  {
228  Constraint::AxisList Results;
229  Results.push_back(5);
230  return Results;
231  }
232 
234  {
235  // the logic here should match the logic in the source at http://bulletphysics.com/Bullet/BulletFull/btHingeConstraint_8cpp_source.html#l00962
236  if ( -1!=Axis && 5!=Axis )
237  { return false; }
238  return ( Con_Stop_ERP==Param && this->Hinge->getFlags() & BT_HINGE_FLAGS_ERP_STOP ) || //if we are checking the stop_erp AND the stop_erp bit is set
239  ( Con_Stop_CFM==Param && this->Hinge->getFlags() & BT_HINGE_FLAGS_CFM_STOP ) || //if we are checking the stop_cfm AND the stop_cfm bit is set
240  ( Con_CFM==Param && this->Hinge->getFlags() & BT_HINGE_FLAGS_CFM_NORM ) ; //if we are checking the cfm AND the cfm bit is set
241  }
242 
244  { return this->Hinge->getUseReferenceFrameA(); }
245 
246  void HingeConstraint::SetUseReferenceFrameA(bool UseReferenceFrameA)
247  { this->Hinge->setUseReferenceFrameA(UseReferenceFrameA); }
248 
250  { return this->Hinge->getUseFrameOffset(); }
251 
252  void HingeConstraint::SetUseFrameOffset(bool FrameOffset)
253  { this->Hinge->setUseFrameOffset(FrameOffset); }
254 
255  ////////////////////////////////////////////////////////////////////////////////
256  // HingeConstraint Serialization
257 
259  {
260  XML::Node HingeNode = CurrentRoot.AppendChild(SerializableName()); // The base node all the base constraint stuff will go in
261  if (!HingeNode)
262  { SerializeError("Create HingeNode", SerializableName()); }
263 
264  XML::Attribute VerAttr = HingeNode.AppendAttribute("Version"); // Base Attributes
265  XML::Attribute RefA = HingeNode.AppendAttribute("ReferenceInA");
266  XML::Attribute FrameOff = HingeNode.AppendAttribute("UseFrameOffset");
267  if( VerAttr && RefA && FrameOff )
268  {
269  VerAttr.SetValue(1);
270  RefA.SetValue(this->GetUseReferenceFrameA());
271  FrameOff.SetValue(this->GetUseFrameOffset());
272  }else{
273  SerializeError("Create HingeNode Attributes", SerializableName());
274  }
275 
276  XML::Node MotorNode = HingeNode.AppendChild("Motor"); // Motor Node
277  if (!MotorNode)
278  { SerializeError("Create MotorNode", SerializableName()); }
279 
280  XML::Attribute MotEnabled = MotorNode.AppendAttribute("Enabled"); // Motor Attributes
281  XML::Attribute MotImpulse = MotorNode.AppendAttribute("MaxImpulse");
282  XML::Attribute MotTarget = MotorNode.AppendAttribute("TargetVelocity");
283  if( MotEnabled && MotImpulse && MotTarget )
284  {
285  MotEnabled.SetValue(this->GetMotorEnabled());
286  MotImpulse.SetValue(this->GetMaxMotorImpulse());
287  MotTarget.SetValue(this->GetMotorTargetVelocity());
288  }else{
289  SerializeError("Create MotorNode Attributes", SerializableName());
290  }
291 
292  XML::Node LimitNode = HingeNode.AppendChild("Limits"); // Limits Node
293  if (!LimitNode)
294  { SerializeError("Create LimitNode", SerializableName()); }
295 
296  XML::Attribute LimLow = LimitNode.AppendAttribute("Low"); // Limits Attributes
297  XML::Attribute LimHigh = LimitNode.AppendAttribute("High");
298  XML::Attribute LimSoft = LimitNode.AppendAttribute("Softness");
299  XML::Attribute LimBias = LimitNode.AppendAttribute("BiasFactor");
300  XML::Attribute LimRelax = LimitNode.AppendAttribute("RelaxationFactor");
301  if( LimLow && LimHigh && LimSoft && LimBias && LimRelax )
302  {
303  LimLow.SetValue(this->GetLimitLow());
304  LimHigh.SetValue(this->GetLimitHigh());
305  LimSoft.SetValue(this->GetLimitSoftness());
306  LimBias.SetValue(this->GetLimitBiasFactor());
307  LimRelax.SetValue(this->GetLimitRelaxationFactor());
308  }else{
309  SerializeError("Create MotorNode Attributes", SerializableName());
310  }
311 
313  }
314 
316  {
317  if ( Mezzanine::String(OneNode.Name())==this->HingeConstraint::SerializableName() )
318  {
319  if(OneNode.GetAttribute("Version").AsInt() == 1)
320  {
321  XML::Node DualTranny = OneNode.GetChild("DualTransformConstraint");
322  if(!DualTranny)
323  { DeSerializeError("locate DualTransforn node",SerializableName()); }
325 
326  XML::Node MotorNode = OneNode.GetChild("Motor");
327  if(!MotorNode)
328  { DeSerializeError("locate Motor node",SerializableName()); }
329 
330  XML::Node LimitNode = OneNode.GetChild("Limits");
331  if(!LimitNode)
332  { DeSerializeError("locate Limits node",SerializableName()); }
333 
334  this->SetUseReferenceFrameA(OneNode.GetAttribute("ReferenceInA").AsBool());
335  this->SetUseFrameOffset(OneNode.GetAttribute("UseFrameOffset").AsBool());
336 
337  this->EnableMotor(
338  MotorNode.GetAttribute("Enabled").AsBool(),
339  MotorNode.GetAttribute("TargetVelocity").AsReal(),
340  MotorNode.GetAttribute("MaxImpulse").AsReal() );
341 
342  this->SetLimit(
343  LimitNode.GetAttribute("Low").AsReal(),
344  LimitNode.GetAttribute("High").AsReal(),
345  LimitNode.GetAttribute("Softness").AsReal(),
346  LimitNode.GetAttribute("BiasFactor").AsReal(),
347  LimitNode.GetAttribute("RelaxationFactor").AsReal() );
348  }else{
349  DeSerializeError("find usable serialization version",SerializableName());
350  }
351  }else{
352  DeSerializeError(String("find correct class to deserialize, found a ")+OneNode.Name(),SerializableName());
353  }
354  }
355 
357  { return String("HingeConstraint"); }
358 
359  }//Physics
360 }//Mezzanine
361 
362 ///////////////////////////////////////////////////////////////////////////////
363 // Class External << Operators for streaming or assignment
364 
365 std::ostream& operator << (std::ostream& stream, const Mezzanine::Physics::HingeConstraint& x)
366 {
367  Mezzanine::Serialize(stream,x);
368  return stream;
369 }
370 
371 std::istream& operator >> (std::istream& stream, Mezzanine::Physics::HingeConstraint& x)
372  { return Mezzanine::DeSerialize(stream, x); }
373 
374 void operator >> (const Mezzanine::XML::Node& OneNode, Mezzanine::Physics::HingeConstraint& x)
375  { x.ProtoDeSerialize(OneNode); }
376 
377 #endif