MezzanineEngine 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
constraint.h
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 _physicsconstraint_h
41 #define _physicsconstraint_h
42 
43 #include "crossplatformexport.h"
44 #include "datatypes.h"
45 #include "quaternion.h"
46 #include "transform.h"
47 #include "vector3.h"
48 
49 class btRigidBody;
50 class btTypedConstraint;
51 
52 namespace Mezzanine
53 {
54  namespace Physics
55  {
56  class RigidProxy;
57 
58  /// @enum ConstraintParam
59  /// @brief Used by constraints for setting some parameters.
60  /// @details See the constraint class documentation for more details.
62  {
63  Con_ERP = 1, ///< ERP values adjust how fast the errors in the constraints are reduced.
64  Con_Stop_ERP = 2,
65  Con_CFM = 3, ///< CFM values adds some small value to the main diagonal on the constraint matrix to prevent degenerate matrices.
66  Con_Stop_CFM = 4
67  };
68 
69  /// @brief Get a Constraint Parameter as a String.
70  /// @param Param The Parameter to get as a String.
71  /// @return A String That contains the name of a ConstraintParam.
73 
74  /// @brief Convert A string that might be ConstraintParam to one.
75  /// @param Param A String that should be storing, a constraint param name.
76  /// @return if the name matches on of the constraintParams exactly, return that one.
77  /// @throw If the Param does not match a type exactly, then this will throw an exception.
79 
80  /// @brief How many ConstraintParam Exist.
81  /// @details Used in some algorithms and we didn't want it to look like a magic so we defined it here.
82  const int ConstraintParamCount = 4;
83 
84  /// @internal
85  /// @brief used to help convert string to the axis they indicate
86  /// @param it it is the character that is passed in to indicate what the axis is. This should be the [4] character or the 5 character of the string.
87  /// @return this returns an int that indicates the Axis for the string.
88  int char4ToAxis(char it);
89 
90  ///////////////////////////////////////////////////////////////////////////////
91  /// @class Constraint
92  /// @headerfile constraint.h
93  /// @brief This is the base class for all constraints supported.
94  /// @details This class provides the basis for all the other constraints. This is
95  /// also a virtual class and provides no constraint properties of it's own, thus
96  /// shouldn't/can't be called on manually. \n \n
97  /// Any class implementing a this must implement at least these functions to
98  /// create a minimally functiontal constraint: \n
99  /// - GetConstraintBase() const - Return A pointer to the bullet constraint they use
100  /// - SetPivotALocation(const Vector3&) - Set Location of pivot Relative to A
101  /// - SetPivotALocation(const Vector3&) - Set Location of pivot Relative to B
102  /// - GetPivotALocation() const - Get Location of pivot Relative to A
103  /// - GetPivotBLocation() const - Get Location of pivot Relative to B
104  /// - ValidParamOnAxis(int Axis) const - What parameters can be changed on the given Axis
105  /// - ValidLinearAxis() const - Which Axis Suppport Translation
106  /// - ValidAngularAxis() const - Which axis support Rotation
107  /// - HasParamBeenSet(ConstraintParam Param, int Axis) const - Has a the given param on the given axis been set
108  ///
109  /// It is advisable to re-implement a few more functions as well, these all have implementation writtens in terms of
110  /// of the function that must be implemented, but the genericity of them may impede performance.
111  /// - ValidAxis() const - Full List of all valid Axis. Combines the lists from ValidLinearAxis() const and ValidAngularAxis() const.
112  /// - IsParamValidOnAxis(ConstraintParam, int) const - Uses the other function to check Axis and then check if the param is valid there
113  /// - ValidParams() const - A list of Parameters every Axis on this constraint implements
114  ///
115  ///
116  ///////////////////////////////////////////////////////////////////////////////
118  {
119  protected:
120  friend class PhysicsManager;
121 
122  /// @internal
123  /// @brief The first Collidable this constraint applies to.
125  /// @internal
126  /// @brief The second Collidable this constraint applies to.
128 
129  /// @internal
130  /// @brief Sets the Internal Proxy pointers.
131  void SetBodies(RigidProxy* Prox1, RigidProxy* Prox2);
132  /// @internal
133  /// @brief Sets the Internal Proxy pointers.
134  void SetBodies(RigidProxy* Prox1);
135  /// @internal
136  /// @brief No initialization constructor.
137  /// @details This is protected to prevent creating an instance of this directly.
138  Constraint();
139  public:
140  ////////////////////////////////////////////////////////////////////////////////
141  // Constraint Core Functionality
142  /// @brief Class destructor.
143  /// @details The class destructor.
144  virtual ~Constraint();
145 
146  /// @brief Gets the first Proxy this constraint applies to.
147  /// @return Returns a pointer to the first Proxy this constraint applies to.
148  virtual RigidProxy* GetProxyA() const;
149  /// @brief Gets the second Proxy this constraint applies to.
150  /// @return Returns a pointer to the second Proxy this constraint applies to.
151  virtual RigidProxy* GetProxyB() const;
152 
153  ///////////////////////////////////////////////////////////////////////////////
154  // Constraint Parameters
155  /// @brief Used to Store lists of param for return types
156  typedef std::vector<ConstraintParam> ParamList;
157  /// @brief Used to Store lists of Int Axis for return types
158  /// @details In general Axis will come in groups of three, such as 0,1,2, or 0,1,2,3,4,5 which could represent X,Y, and Z or multiple grousp of X,Y, and Z. These Axis
159  /// can represent Linear/Translation or Angular/Rotation information. Some Constraints support values that affect all constraints, this is usually represented a -1.
160  typedef std::vector<int> AxisList;
161 
162  /// @brief Get a sorted (low to high) list of Parameters that are valid on this Axis
163  /// @details Parameters returned from this will work on the given axis even if they are not valid on any other axis. There is no guarantee that the Parameters
164  /// will be uniquely stored per an axis. There is no guarantee that changing one parameter will not change another.
165  /// @param Axis the Axis to check.
166  /// @return A Paramlist with all the valid parameters for this axis.
167  virtual ParamList ValidParamOnAxis(int Axis) const = 0;
168  /// @brief Get a sorted (low to high) list of all axis that operate linearly (that lock sliding/translation)
169  /// @warning Odd behaviors, maybe even undefined behavior can happen if This returns a matching Axis to a Linear Axis. Any given axis should only be one or the other
170  /// @return An Axislist with the Axis this constraint linearly supports.
171  virtual AxisList ValidLinearAxis() const = 0;
172  /// @brief Get A list sorted (low to high) of all axis that operate Angularly (that lock sliding/translation)
173  /// @warning Odd behaviors, maybe even undefined behavior can happen if This returns a matching Axis to a Linear Axis. Any given axis should only be one or the other
174  /// @return An Axislist with the Axis this constraint Angularly supports.
175  virtual AxisList ValidAngularAxis() const = 0;
176  /// @brief Has the given Param on the Given Axis been set yet.
177  /// @param Param The parameter to Check
178  /// @param Axis The Axis on which to check the param
179  /// @details This will probably have to implement the same logic aas what is in the respective get/setparam function of each constraint http://bulletphysics.com/Bullet/BulletFull/classbtTypedConstraint.html#a11f44dd743b59bc05e25d500456e2559
180  /// @return True if it has been set, false if it has.
181  virtual bool HasParamBeenSet(ConstraintParam Param, int Axis) const = 0;
182  /// @brief Get a sorted (low to high) list of All Valid Axis
183  /// @details This is implemented using ValidLinearAxis and ValidAngularAxis, Derived versions of this class may wish to make a more specialized
184  /// implementation of this method that doesn't have the overhead of passing around 3 vectors by value.
185  /// @return An Axislist with all the Axis this constraint supports.
186  virtual AxisList ValidAxis() const
187  {
188  AxisList Ang = this->ValidAngularAxis();
189  AxisList Lin = this->ValidLinearAxis();
190  Lin.insert(Lin.end()-1,Ang.begin(),Ang.end()); // just kinda stick the two together and return that, no checking is performed for uniqueness.
191  sort(Lin.begin(),Lin.end()); // Usually the Linear axis are 0,1,2 and the angular are 3,4,5 so hopefully, this will hardly ever need to do work.
192  return Lin;
193  }
194  /// @brief Is a certain Parameter valid on a certain axis
195  /// @param Param The Parameter to Check
196  /// @param Axis The Axis to Check
197  /// @details This is implemented using ValidParamOnAxis, Derived versions of this class may wish to make a more specialized
198  /// implementation of this method.
199  /// @return True if Param is valid on Axis, and Axis is valid. If anything is invalid this returns false.
200  virtual bool IsParamValidOnAxis(ConstraintParam Param, int Axis) const
201  {
202  ParamList Supported = ValidParamOnAxis(Axis);
203  if(size_t(ConstraintParamCount) == Supported.size()) // no need to check deeper, because everything is supported
204  {
205  return true;
206  }else{
207  if(Supported.size())
208  {
209  return ( std::find(Supported.begin(),Supported.end(),Param) != Supported.end() ); // should return true if found
210  }else{
211  return false; // size is 0 of course it is not supported
212  }
213  }
214  }
215  /// @brief Get A sorted (low to high) list of Parameters that are valid on all Axis
216  /// @details This is implemented using ValidAxis and ValidParamOnAxis, Derived versions of this class may wish to make a more specialized
217  /// implementation of this method that doesn't have the overhead of passing around many vectors by value and executing slow loops. Most
218  /// likely all of these constraint Parameter and axis functions could be replaced with some fairly simple switch statements and statically
219  /// coded values that are specific to the kind of constraint.
220  /// @return A Paramlist with the parameters valid on all axis.
221  virtual ParamList ValidParams() const
222  {
223  AxisList AllAxis = this->ValidAxis();
224  ParamList Results;
225  if(AllAxis.size()) //If we have no Axis, the we have no valid Parameters.
226  {
227  Results = this->ValidParamOnAxis(*(AllAxis.begin())); // Let's start off with whatever the first Axis Support, then we will trim from here.
228 
229  if(AllAxis.size()>1) //if the constraint only support one axis then we already have our answer, and we don't want to run of the end of the Paramlist
230  {
231  for(AxisList::iterator AxisIter = AllAxis.begin()+1; AllAxis.end()!=AxisIter; ++AxisIter) //For each axis after the first
232  {
233  for(int ParamID = Results.size(); ParamID<=0; --ParamID) // We start at the back and work by index because reverse erase does no accept rever iterators, and
234  {
235  if (!IsParamValidOnAxis(Results.at(ParamID),*AxisIter)) // if an Item is erase near the beginning, it changes all the items after, making forward iteration logic that
236  { Results.erase( Results.begin()+ParamID ); } // erases needlessly complicated, and potentially expensive depending on the Vector implementation
237  }
238  }
239  }
240  }
241  sort(Results.begin(),Results.end());
242  return Results;
243  }
244 
245  /// @brief Provides override of constraint parameters.
246  /// @details Parameters such as ERP(Error Reduction Parameter) and CFM(Constraint Force Mixing) can be altered with this function. Optionally provide axis.
247  /// @param Param The parameter to override.
248  /// @param Value The new value for the parameter.
249  /// @param Axis Optional axis.
250  virtual void SetParam(ConstraintParam Param, Real Value, int Axis=-1);
251  /// @brief Gets value of constraint parameters.
252  /// @details See SetParam() for clarification. Gets information on constraint parameters.
253  /// @param Para, The parameter to get information for.
254  /// @param Axis Optional axis.
255  /// @return Returns the value for the requested parameter.
256  virtual Real GetParam(ConstraintParam Param, int Axis=-1) const;
257 
258  /// @brief Get the Bullet constraint that this class encapsulates.
259  /// @return A pointer to the btTypedConstraint that stores the underlying constraint.
260  virtual btTypedConstraint* GetConstraintBase() const = 0;
261 
262  ///////////////////////////////////////////////////////////////////////////////
263  // Constraint Serialization
264 
265  /// @brief Convert this class to an XML::Node ready for serialization
266  /// @param CurrentRoot The point in the XML hierarchy that all this vectorw should be appended to.
267  /// @details This stores each Actor's name and every constraint parameter on each if it has been set.
268  /// This should allow for looking up the required actors in the Actor Manager. This should also prevent
269  /// any interference with different values and minimize the size of the serialized version
270  virtual void ProtoSerialize(XML::Node& CurrentRoot) const;
271  /// @brief Take the data stored in an XML and overwrite this instance of this object with it
272  /// @param OneNode and XML::Node containing the data.
273  /// @details This should only be run once all the actors have finishes being deserialized. This will fail
274  /// if the actors it expects are not present.
275  virtual void ProtoDeSerialize(const XML::Node& OneNode);
276  /// @brief Get the name of the the XML tag this class will leave behind as its instances are serialized.
277  /// @return A string containing "Constraint"
278  static String SerializableName();
279  };// ©onstraint
280  }//Physics
281 }//Mezzanine
282 
283 ///////////////////////////////////////////////////////////////////////////////
284 // Class External << Operators for streaming or assignment
285 
286 /// @brief Convert a constraint to XML and send it down a stream.
287 /// @param stream The stream to send it down.
288 /// @param x The constraint to send down.
289 /// @return This returns the output stream to allow operator chaining.
290 std::ostream& MEZZ_LIB operator << (std::ostream& stream, const Mezzanine::Physics::Constraint& x);
291 /// @brief Get a constraint from an XML stream.
292 /// @param stream The stream to get it out of.
293 /// @param x The it you will get out of the stream.
294 /// @return This returns the input stream to allow operator chaining.
295 std::istream& MEZZ_LIB operator >> (std::istream& stream, Mezzanine::Physics::Constraint& x);
296 /// @brief Converts an XML Node into a functional in memory construct.
297 /// @param OneNode The xml node that contains the deserialize class instance.
298 /// @param x The class instance to overwrite witht the proto serialized version in the node.
299 void operator >> (const Mezzanine::XML::Node& OneNode, Mezzanine::Physics::Constraint& x);
300 
301 #endif