Speed up the physics engine: hook the SOLID broad phase, so we can either reject...
[blender.git] / source / gameengine / Physics / Sumo / Fuzzics / include / SM_Object.h
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version. The Blender
10  * Foundation also sells licenses for use in proprietary software under
11  * the Blender License.  See http://www.blender.org/BL/ for information
12  * about this.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software Foundation,
21  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22  *
23  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
24  * All rights reserved.
25  *
26  * The Original Code is: all of this file.
27  *
28  * Contributor(s): none yet.
29  *
30  * ***** END GPL/BL DUAL LICENSE BLOCK *****
31  */
32 #ifndef SM_OBJECT_H
33 #define SM_OBJECT_H
34
35 #include <vector>
36
37 #include <SOLID/SOLID.h>
38
39 #include "SM_Callback.h"
40 #include "SM_MotionState.h"
41 #include <stdio.h>
42
43 class SM_FhObject;
44
45 /** Properties of dynamic objects */
46 struct SM_ShapeProps {
47         MT_Scalar  m_mass;                  ///< Total mass
48         MT_Scalar  m_radius;                ///< Bound sphere size
49         MT_Vector3 m_inertia;               ///< Inertia, should be a tensor some time 
50         MT_Scalar  m_lin_drag;              ///< Linear drag (air, water) 0 = concrete, 1 = vacuum 
51         MT_Scalar  m_ang_drag;              ///< Angular drag
52         MT_Scalar  m_friction_scaling[3];   ///< Scaling for anisotropic friction. Component in range [0, 1]   
53         bool       m_do_anisotropic;        ///< Should I do anisotropic friction? 
54         bool       m_do_fh;                 ///< Should the object have a linear Fh spring?
55         bool       m_do_rot_fh;             ///< Should the object have an angular Fh spring?
56 };
57
58
59 /** Properties of collidable objects (non-ghost objects) */
60 struct SM_MaterialProps {
61         MT_Scalar m_restitution;           ///< restitution of energy after a collision 0 = inelastic, 1 = elastic
62         MT_Scalar m_friction;              ///< Coulomb friction (= ratio between the normal en maximum friction force)
63         MT_Scalar m_fh_spring;             ///< Spring constant (both linear and angular)
64         MT_Scalar m_fh_damping;            ///< Damping factor (linear and angular) in range [0, 1]
65         MT_Scalar m_fh_distance;           ///< The range above the surface where Fh is active.    
66         bool      m_fh_normal;             ///< Should the object slide off slopes?
67 };
68
69 class SM_ClientObject
70 {
71 public:
72         SM_ClientObject() {}
73         virtual ~SM_ClientObject() {}
74         
75         virtual bool hasCollisionCallback() = 0;
76 };
77
78 /**
79  * SM_Object is an internal part of the Sumo physics engine.
80  *
81  * It encapsulates an object in the physics scene, and is responsible
82  * for calculating the collision response of objects.
83  */
84 class SM_Object : public SM_MotionState {
85 public:
86         SM_Object() ;
87         SM_Object(
88                 DT_ShapeHandle shape, 
89                 const SM_MaterialProps *materialProps,
90                 const SM_ShapeProps *shapeProps,
91                 SM_Object *dynamicParent
92         );
93         virtual ~SM_Object();
94
95         bool isDynamic() const;  
96
97         /* nzc experimental. There seem to be two places where kinematics
98          * are evaluated: proceedKinematic (called from SM_Scene) and
99          * proceed() in this object. I'll just try and bunge these out for
100          * now.  */
101
102         void suspend(void);
103         void resume(void);
104
105         void suspendDynamics();
106         
107         void restoreDynamics();
108         
109         bool isGhost() const;
110
111         void suspendMaterial();
112         
113         void restoreMaterial();
114         
115         SM_FhObject *getFhObject() const;
116         
117         void registerCallback(SM_Callback& callback);
118
119         void calcXform();
120         void notifyClient();
121         void updateInvInertiaTensor();
122
123     
124         // Save the current state information for use in the 
125         // velocity computation in the next frame.  
126
127         void proceedKinematic(MT_Scalar timeStep);
128
129         void saveReactionForce(MT_Scalar timeStep) ;
130         
131         void clearForce() ;
132
133         void clearMomentum() ;
134         
135         void setMargin(MT_Scalar margin) ;
136         
137         MT_Scalar getMargin() const ;
138         
139         const SM_MaterialProps *getMaterialProps() const ;
140         
141         const SM_ShapeProps *getShapeProps() const ;
142         
143         void setPosition(const MT_Point3& pos);
144         void setOrientation(const MT_Quaternion& orn);
145         void setScaling(const MT_Vector3& scaling);
146         
147
148         /**
149          * set an external velocity. This velocity complements
150          * the physics velocity. So setting it does not override the
151          * physics velocity. It is your responsibility to clear 
152          * this external velocity. This velocity is not subject to 
153          * friction or damping.
154          */
155         void setExternalLinearVelocity(const MT_Vector3& lin_vel) ;
156         void addExternalLinearVelocity(const MT_Vector3& lin_vel) ;
157
158         /** Override the physics velocity */
159         void addLinearVelocity(const MT_Vector3& lin_vel);
160         void setLinearVelocity(const MT_Vector3& lin_vel);
161
162         /**
163          * Set an external angular velocity. This velocity complemetns
164          * the physics angular velocity so does not override it. It is
165          * your responsibility to clear this velocity. This velocity
166          * is not subject to friction or damping.
167          */
168         void setExternalAngularVelocity(const MT_Vector3& ang_vel) ;
169         void addExternalAngularVelocity(const MT_Vector3& ang_vel);
170
171         /** Override the physics angular velocity */
172         void addAngularVelocity(const MT_Vector3& ang_vel);
173         void setAngularVelocity(const MT_Vector3& ang_vel);
174
175         /** Clear the external velocities */
176         void clearCombinedVelocities();
177
178         /** 
179          * Tell the physics system to combine the external velocity
180          * with the physics velocity. 
181          */
182         void resolveCombinedVelocities(
183                 const MT_Vector3 & lin_vel,
184                 const MT_Vector3 & ang_vel
185         ) ;
186
187
188
189         MT_Scalar getInvMass() const;
190
191         const MT_Vector3& getInvInertia() const ;
192         
193         const MT_Matrix3x3& getInvInertiaTensor() const;
194
195         void applyForceField(const MT_Vector3& accel) ;
196         
197         void applyCenterForce(const MT_Vector3& force) ;
198         
199         void applyTorque(const MT_Vector3& torque) ;
200         
201         /**
202          * Apply an impulse to the object.  The impulse will be split into
203          * angular and linear components.
204          * @param attach point to apply the impulse to (in world coordinates)
205          */
206         void applyImpulse(const MT_Point3& attach, const MT_Vector3& impulse) ;
207         
208         /**
209          * Applies an impulse through the centre of this object. (ie the angular
210          * velocity will not change.
211          */
212         void applyCenterImpulse(const MT_Vector3& impulse);
213         /**
214          * Applies an angular impulse.
215          */
216         void applyAngularImpulse(const MT_Vector3& impulse);
217         
218         MT_Point3 getWorldCoord(const MT_Point3& local) const;
219         MT_Point3 getLocalCoord(const MT_Point3& world) const;
220     
221         MT_Vector3 getVelocity(const MT_Point3& local) const;
222
223
224         const MT_Vector3& getReactionForce() const ;
225
226         void getMatrix(double *m) const ;
227
228         const double *getMatrix() const ;
229
230         // Still need this???
231         const MT_Transform&  getScaledTransform()  const; 
232
233         DT_ObjectHandle getObjectHandle() const ;
234         DT_ShapeHandle getShapeHandle() const ;
235
236         SM_Object *getDynamicParent() ;
237
238         void integrateForces(MT_Scalar timeStep);
239         void integrateMomentum(MT_Scalar timeSteo);
240
241         void setRigidBody(bool is_rigid_body) ;
242
243         bool isRigidBody() const ;
244
245         // This is the callback for handling collisions of dynamic objects
246         static 
247                 DT_Bool 
248         boing(
249                 void *client_data,  
250                 void *object1,
251                 void *object2,
252                 const DT_CollData *coll_data
253         );
254
255         static 
256                 DT_Bool 
257         fix(
258                 void *client_data,  
259                 void *object1,
260                 void *object2,
261                 const DT_CollData *coll_data
262         );
263         
264         
265         SM_ClientObject *getClientObject() { return m_client_object; }
266         void setClientObject(SM_ClientObject *client_object) { m_client_object = client_object; }
267         
268         void relax();
269         
270         void backup() {
271                 m_pos = m_prev_state.getPosition();
272                 m_orn = m_prev_state.getOrientation();
273                 m_xform = m_prev_xform;
274         }
275 private:
276
277         // Tweak parameters
278         static MT_Scalar ImpulseThreshold;
279
280         // return the actual linear_velocity of this object this 
281         // is the addition of m_combined_lin_vel and m_lin_vel.
282
283         const 
284                 MT_Vector3
285         actualLinVelocity(
286         ) const ;
287
288         const 
289                 MT_Vector3
290         actualAngVelocity(
291         ) const ;
292         
293         void dynamicCollision(const MT_Point3 &local2, 
294                 const MT_Vector3 &normal, 
295                 MT_Scalar dist, 
296                 const MT_Vector3 &rel_vel,
297                 MT_Scalar restitution,
298                 MT_Scalar friction_factor,
299                 MT_Scalar invMass
300         );
301
302         typedef std::vector<SM_Callback *> T_CallbackList;
303
304
305         T_CallbackList          m_callbackList;    // Each object can have multiple callbacks from the client (=game engine)
306         SM_Object              *m_dynamicParent;   // Collisions between parent and children are ignored
307
308     // as the collision callback now has only information
309         // on an SM_Object, there must be a way that the SM_Object client
310         // can identify it's clientdata after a collision
311         SM_ClientObject        *m_client_object;
312
313         DT_ShapeHandle          m_shape;                 // Shape for collision detection
314
315         // Material and shape properties are not owned by this class.
316
317         const SM_MaterialProps *m_materialProps;         
318         const SM_MaterialProps *m_materialPropsBackup;   // Backup in case the object temporarily becomes a ghost.
319         const SM_ShapeProps    *m_shapeProps;           
320         const SM_ShapeProps    *m_shapePropsBackup;      // Backup in case the object's dynamics is temporarily suspended
321         DT_ObjectHandle         m_object;                // A handle to the corresponding object in SOLID.
322         MT_Scalar               m_margin;                // Offset for the object's shape (also for collision detection)
323         MT_Vector3              m_scaling;               // Non-uniform scaling of the object's shape
324
325         double                  m_ogl_matrix[16];        // An OpenGL-type 4x4 matrix      
326         MT_Transform            m_xform;                 // The object's local coordinate system
327         MT_Transform            m_prev_xform;            // The object's local coordinate system in the previous frame
328         SM_MotionState          m_prev_state;            // The object's motion state in the previous frame
329         MT_Scalar               m_timeStep;              // The duration of the last frame 
330
331         MT_Vector3              m_reaction_impulse;      // The accumulated impulse resulting from collisions
332         MT_Vector3              m_reaction_force;        // The reaction force derived from the reaction impulse   
333
334         unsigned int            m_kinematic      : 1;    // Have I been displaced (translated, rotated, scaled) in this frame? 
335         unsigned int            m_prev_kinematic : 1;    // Have I been displaced (translated, rotated, scaled) in the previous frame? 
336         unsigned int            m_is_rigid_body  : 1;    // Should friction give me a change in angular momentum?
337
338         MT_Vector3              m_lin_mom;               // Linear momentum (linear velocity times mass)
339         MT_Vector3              m_ang_mom;               // Angular momentum (angualr velocity times inertia)
340         MT_Vector3              m_force;                 // Force on center of mass (afffects linear momentum)
341         MT_Vector3              m_torque;                // Torque around center of mass (affects angualr momentum)
342         
343         MT_Vector3              m_error;                 // Error in position:- amount object must be moved to prevent intersection with scene
344
345         // Here are the values of externally set linear and angular
346         // velocity. These are updated from the outside
347         // (actuators and python) each frame and combined with the
348         // physics values. At the end of each frame (at the end of a
349         // call to proceed) they are set to zero. This allows the
350         // outside world to contribute to the velocity of an object
351         // but still have it react to physics. 
352
353         MT_Vector3                              m_combined_lin_vel;
354         MT_Vector3                              m_combined_ang_vel;
355
356         // The force and torque are the accumulated forces and torques applied by the client (game logic, python).
357
358         SM_FhObject            *m_fh_object;             // The ray object used for Fh
359         bool                    m_suspended;             // Is this object frozen?
360         
361         // Mass properties
362         MT_Scalar               m_inv_mass;              // 1/mass
363         MT_Vector3              m_inv_inertia;           // [1/inertia_x, 1/inertia_y, 1/inertia_z]
364         MT_Matrix3x3            m_inv_inertia_tensor;    // Inverse Inertia Tensor
365 };
366
367 #endif
368