-fixes in player: draw physics debugging, only render frames when actually updated...
[blender-staging.git] / source / gameengine / Physics / Bullet / CcdPhysicsController.cpp
1 /*
2 Bullet Continuous Collision Detection and Physics Library
3 Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
4
5 This software is provided 'as-is', without any express or implied warranty.
6 In no event will the authors be held liable for any damages arising from the use of this software.
7 Permission is granted to anyone to use this software for any purpose, 
8 including commercial applications, and to alter it and redistribute it freely, 
9 subject to the following restrictions:
10
11 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
12 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
13 3. This notice may not be removed or altered from any source distribution.
14 */
15
16 #include "CcdPhysicsController.h"
17 #include "btBulletDynamicsCommon.h"
18
19 #include "PHY_IMotionState.h"
20 #include "CcdPhysicsEnvironment.h"
21
22
23 class BP_Proxy;
24
25 ///todo: fill all the empty CcdPhysicsController methods, hook them up to the btRigidBody class
26
27 //'temporarily' global variables
28 //float gDeactivationTime = 2.f;
29 //bool  gDisableDeactivation = false;
30 extern float gDeactivationTime;
31 extern bool gDisableDeactivation;
32
33
34 float gLinearSleepingTreshold = 0.8f;
35 float gAngularSleepingTreshold = 1.0f;
36
37
38 btVector3 startVel(0,0,0);//-10000);
39 CcdPhysicsController::CcdPhysicsController (const CcdConstructionInfo& ci)
40 :m_cci(ci)
41 {
42         m_collisionDelay = 0;
43         m_newClientInfo = 0;
44         
45         m_MotionState = ci.m_MotionState;
46         m_bulletMotionState = 0;
47         
48         
49         CreateRigidbody();
50         
51
52         
53         #ifdef WIN32
54         if (m_body->getInvMass())
55                 m_body->setLinearVelocity(startVel);
56         #endif
57
58 }
59
60 btTransform     CcdPhysicsController::GetTransformFromMotionState(PHY_IMotionState* motionState)
61 {
62         btTransform trans;
63         float tmp[3];
64         motionState->getWorldPosition(tmp[0],tmp[1],tmp[2]);
65         trans.setOrigin(btVector3(tmp[0],tmp[1],tmp[2]));
66
67         btQuaternion orn;
68         motionState->getWorldOrientation(orn[0],orn[1],orn[2],orn[3]);
69         trans.setRotation(orn);
70         return trans;
71
72 }
73
74 class   BlenderBulletMotionState : public btMotionState
75 {
76         PHY_IMotionState*       m_blenderMotionState;
77
78 public:
79
80         BlenderBulletMotionState(PHY_IMotionState* bms)
81                 :m_blenderMotionState(bms)
82         {
83
84         }
85
86         virtual void    getWorldTransform(btTransform& worldTrans ) const
87         {
88                 float pos[3];
89                 float quatOrn[4];
90
91                 m_blenderMotionState->getWorldPosition(pos[0],pos[1],pos[2]);
92                 m_blenderMotionState->getWorldOrientation(quatOrn[0],quatOrn[1],quatOrn[2],quatOrn[3]);
93                 worldTrans.setOrigin(btVector3(pos[0],pos[1],pos[2]));
94                 worldTrans.setBasis(btMatrix3x3(btQuaternion(quatOrn[0],quatOrn[1],quatOrn[2],quatOrn[3])));
95         }
96
97         virtual void    setWorldTransform(const btTransform& worldTrans)
98         {
99                 m_blenderMotionState->setWorldPosition(worldTrans.getOrigin().getX(),worldTrans.getOrigin().getY(),worldTrans.getOrigin().getZ());
100                 btQuaternion rotQuat = worldTrans.getRotation();
101                 m_blenderMotionState->setWorldOrientation(rotQuat[0],rotQuat[1],rotQuat[2],rotQuat[3]);
102                 m_blenderMotionState->calculateWorldTransformations();
103         }
104
105 };
106
107 void CcdPhysicsController::CreateRigidbody()
108 {
109
110         btTransform trans = GetTransformFromMotionState(m_cci.m_MotionState);
111
112         m_bulletMotionState = new BlenderBulletMotionState(m_cci.m_MotionState);
113
114         m_body = new btRigidBody(m_cci.m_mass,
115                 m_bulletMotionState,
116                 m_cci.m_collisionShape,
117                 m_cci.m_localInertiaTensor * m_cci.m_inertiaFactor,
118                 m_cci.m_linearDamping,m_cci.m_angularDamping,
119                 m_cci.m_friction,m_cci.m_restitution);
120
121         
122
123         //
124         // init the rigidbody properly
125         //
126         
127         //setMassProps this also sets collisionFlags
128         //convert collision flags!
129
130         m_body->setCollisionFlags(m_body->getCollisionFlags() | m_cci.m_collisionFlags);
131         
132         m_body->setGravity( m_cci.m_gravity);
133         m_body->setDamping(m_cci.m_linearDamping, m_cci.m_angularDamping);
134
135 }
136
137 CcdPhysicsController::~CcdPhysicsController()
138 {
139         //will be reference counted, due to sharing
140         if (m_cci.m_physicsEnv)
141                 m_cci.m_physicsEnv->removeCcdPhysicsController(this);
142
143         delete m_MotionState;
144         if (m_bulletMotionState)
145                 delete m_bulletMotionState;
146         delete m_body;
147 }
148
149                 /**
150                         SynchronizeMotionStates ynchronizes dynas, kinematic and deformable entities (and do 'late binding')
151                 */
152 bool            CcdPhysicsController::SynchronizeMotionStates(float time)
153 {
154         //sync non-static to motionstate, and static from motionstate (todo: add kinematic etc.)
155
156         if (!m_body->isStaticObject())
157         {
158                 const btVector3& worldPos = m_body->getCenterOfMassPosition();
159                 m_MotionState->setWorldPosition(worldPos[0],worldPos[1],worldPos[2]);
160                 
161                 const btQuaternion& worldquat = m_body->getOrientation();
162                 m_MotionState->setWorldOrientation(worldquat[0],worldquat[1],worldquat[2],worldquat[3]);
163
164                 m_MotionState->calculateWorldTransformations();
165
166                 float scale[3];
167                 m_MotionState->getWorldScaling(scale[0],scale[1],scale[2]);
168                 btVector3 scaling(scale[0],scale[1],scale[2]);
169                 GetCollisionShape()->setLocalScaling(scaling);
170         } else
171         {
172                 btVector3 worldPos;
173                 btQuaternion worldquat;
174
175 /*              m_MotionState->getWorldPosition(worldPos[0],worldPos[1],worldPos[2]);
176                 m_MotionState->getWorldOrientation(worldquat[0],worldquat[1],worldquat[2],worldquat[3]);
177                 btTransform oldTrans = m_body->getCenterOfMassTransform();
178                 btTransform newTrans(worldquat,worldPos);
179                                 
180                 m_body->setCenterOfMassTransform(newTrans);
181                 //need to keep track of previous position for friction effects...
182                 
183                 m_MotionState->calculateWorldTransformations();
184 */
185                 float scale[3];
186                 m_MotionState->getWorldScaling(scale[0],scale[1],scale[2]);
187                 btVector3 scaling(scale[0],scale[1],scale[2]);
188                 GetCollisionShape()->setLocalScaling(scaling);
189         }
190         return true;
191
192 }
193
194                 /**
195                         WriteMotionStateToDynamics synchronizes dynas, kinematic and deformable entities (and do 'late binding')
196                 */
197                 
198 void            CcdPhysicsController::WriteMotionStateToDynamics(bool nondynaonly)
199 {
200
201 }
202 void            CcdPhysicsController::WriteDynamicsToMotionState()
203 {
204 }
205                 // controller replication
206 void            CcdPhysicsController::PostProcessReplica(class PHY_IMotionState* motionstate,class PHY_IPhysicsController* parentctrl)
207 {
208         m_MotionState = motionstate;
209
210         
211
212         m_body = 0;
213         CreateRigidbody();
214         
215         m_cci.m_physicsEnv->addCcdPhysicsController(this);
216
217
218 /*      SM_Object* dynaparent=0;
219         SumoPhysicsController* sumoparentctrl = (SumoPhysicsController* )parentctrl;
220         
221         if (sumoparentctrl)
222         {
223                 dynaparent = sumoparentctrl->GetSumoObject();
224         }
225         
226         SM_Object* orgsumoobject = m_sumoObj;
227         
228         
229         m_sumoObj       =       new SM_Object(
230                 orgsumoobject->getShapeHandle(), 
231                 orgsumoobject->getMaterialProps(),                      
232                 orgsumoobject->getShapeProps(),
233                 dynaparent);
234         
235         m_sumoObj->setRigidBody(orgsumoobject->isRigidBody());
236         
237         m_sumoObj->setMargin(orgsumoobject->getMargin());
238         m_sumoObj->setPosition(orgsumoobject->getPosition());
239         m_sumoObj->setOrientation(orgsumoobject->getOrientation());
240         //if it is a dyna, register for a callback
241         m_sumoObj->registerCallback(*this);
242         
243         m_sumoScene->add(* (m_sumoObj));
244         */
245
246
247
248 }
249
250                 // kinematic methods
251 void            CcdPhysicsController::RelativeTranslate(float dlocX,float dlocY,float dlocZ,bool local)
252 {
253         if (m_body)
254         {
255                 m_body->activate(true);
256                 if (m_body->isStaticObject())
257                 {
258                         m_body->setCollisionFlags(m_body->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT);
259                 }
260
261
262                 btVector3 dloc(dlocX,dlocY,dlocZ);
263                 btTransform xform = m_body->getCenterOfMassTransform();
264
265                 if (local)
266                 {
267                         dloc = xform.getBasis()*dloc;
268                 }
269
270                 xform.setOrigin(xform.getOrigin() + dloc);
271                 m_body->setCenterOfMassTransform(xform);
272         }
273
274 }
275
276 void            CcdPhysicsController::RelativeRotate(const float rotval[9],bool local)
277 {
278         if (m_body )
279         {
280                 m_body->activate(true);
281                 if (m_body->isStaticObject())
282                 {
283                         m_body->setCollisionFlags(m_body->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT);
284                 }
285
286                 btMatrix3x3 drotmat(    rotval[0],rotval[1],rotval[2],
287                                                                 rotval[4],rotval[5],rotval[6],
288                                                                 rotval[8],rotval[9],rotval[10]);
289
290
291                 btMatrix3x3 currentOrn;
292                 GetWorldOrientation(currentOrn);
293
294                 btTransform xform = m_body->getCenterOfMassTransform();
295
296                 xform.setBasis(xform.getBasis()*(local ? 
297                 drotmat : (currentOrn.inverse() * drotmat * currentOrn)));
298
299                 m_body->setCenterOfMassTransform(xform);
300         }
301
302 }
303
304 void CcdPhysicsController::GetWorldOrientation(btMatrix3x3& mat)
305 {
306         float orn[4];
307         m_MotionState->getWorldOrientation(orn[0],orn[1],orn[2],orn[3]);
308         btQuaternion quat(orn[0],orn[1],orn[2],orn[3]);
309         mat.setRotation(quat);
310 }
311
312 void            CcdPhysicsController::getOrientation(float &quatImag0,float &quatImag1,float &quatImag2,float &quatReal)
313 {
314         btQuaternion q = m_body->getCenterOfMassTransform().getRotation();
315         quatImag0 = q[0];
316         quatImag1 = q[1];
317         quatImag2 = q[2];
318         quatReal = q[3];
319 }
320 void            CcdPhysicsController::setOrientation(float quatImag0,float quatImag1,float quatImag2,float quatReal)
321 {
322         m_body->activate(true);
323         if (m_body->isStaticObject())
324         {
325                 m_body->setCollisionFlags(m_body->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT);
326         }
327
328         m_MotionState->setWorldOrientation(quatImag0,quatImag1,quatImag2,quatReal);
329         btTransform xform  = m_body->getCenterOfMassTransform();
330         xform.setRotation(btQuaternion(quatImag0,quatImag1,quatImag2,quatReal));
331         m_body->setCenterOfMassTransform(xform);
332
333 }
334
335 void            CcdPhysicsController::setPosition(float posX,float posY,float posZ)
336 {
337         m_body->activate(true);
338         if (m_body->isStaticObject())
339         {
340                 m_body->setCollisionFlags(m_body->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT);
341         }
342         m_MotionState->setWorldPosition(posX,posY,posZ);
343         btTransform xform  = m_body->getCenterOfMassTransform();
344         xform.setOrigin(btVector3(posX,posY,posZ));
345         m_body->setCenterOfMassTransform(xform);
346
347 }
348 void            CcdPhysicsController::resolveCombinedVelocities(float linvelX,float linvelY,float linvelZ,float angVelX,float angVelY,float angVelZ)
349 {
350 }
351
352 void            CcdPhysicsController::getPosition(PHY__Vector3& pos) const
353 {
354         const btTransform& xform = m_body->getCenterOfMassTransform();
355         pos[0] = xform.getOrigin().x();
356         pos[1] = xform.getOrigin().y();
357         pos[2] = xform.getOrigin().z();
358 }
359
360 void            CcdPhysicsController::setScaling(float scaleX,float scaleY,float scaleZ)
361 {
362         if (!btFuzzyZero(m_cci.m_scaling.x()-scaleX) ||
363                 !btFuzzyZero(m_cci.m_scaling.y()-scaleY) ||
364                 !btFuzzyZero(m_cci.m_scaling.z()-scaleZ))
365         {
366                 m_cci.m_scaling = btVector3(scaleX,scaleY,scaleZ);
367
368                 if (m_body && m_body->getCollisionShape())
369                 {
370                         m_body->getCollisionShape()->setLocalScaling(m_cci.m_scaling);
371                         
372                         //printf("no inertia recalc for fixed objects with mass=0\n");
373                         if (m_cci.m_mass)
374                         {
375                                 m_body->getCollisionShape()->calculateLocalInertia(m_cci.m_mass, m_cci.m_localInertiaTensor);
376                                 m_body->setMassProps(m_cci.m_mass, m_cci.m_localInertiaTensor * m_cci.m_inertiaFactor);
377                         } 
378                         
379                 }
380         }
381 }
382                 
383                 // physics methods
384 void            CcdPhysicsController::ApplyTorque(float torqueX,float torqueY,float torqueZ,bool local)
385 {
386         btVector3 torque(torqueX,torqueY,torqueZ);
387         btTransform xform = m_body->getCenterOfMassTransform();
388         if (torque.length2() > (SIMD_EPSILON*SIMD_EPSILON))
389         {
390                 m_body->activate();
391         }
392         if (local)
393         {
394                 torque  = xform.getBasis()*torque;
395         }
396         m_body->applyTorque(torque);
397 }
398
399 void            CcdPhysicsController::ApplyForce(float forceX,float forceY,float forceZ,bool local)
400 {
401         btVector3 force(forceX,forceY,forceZ);
402         
403         if (force.length2() > (SIMD_EPSILON*SIMD_EPSILON))
404         {
405                 m_body->activate();
406         }
407
408
409         btTransform xform = m_body->getCenterOfMassTransform();
410         if (local)
411         {
412                 force   = xform.getBasis()*force;
413         }
414         m_body->applyCentralForce(force);
415 }
416 void            CcdPhysicsController::SetAngularVelocity(float ang_velX,float ang_velY,float ang_velZ,bool local)
417 {
418         btVector3 angvel(ang_velX,ang_velY,ang_velZ);
419         if (angvel.length2() > (SIMD_EPSILON*SIMD_EPSILON))
420         {
421                 m_body->activate(true);
422         }
423
424         {
425                 btTransform xform = m_body->getCenterOfMassTransform();
426                 if (local)
427                 {
428                         angvel  = xform.getBasis()*angvel;
429                 }
430
431                 m_body->setAngularVelocity(angvel);
432         }
433
434 }
435 void            CcdPhysicsController::SetLinearVelocity(float lin_velX,float lin_velY,float lin_velZ,bool local)
436 {
437
438         btVector3 linVel(lin_velX,lin_velY,lin_velZ);
439         if (linVel.length2() > (SIMD_EPSILON*SIMD_EPSILON))
440         {
441                 m_body->activate(true);
442         }
443         
444         {
445                 btTransform xform = m_body->getCenterOfMassTransform();
446                 if (local)
447                 {
448                         linVel  = xform.getBasis()*linVel;
449                 }
450                 m_body->setLinearVelocity(linVel);
451         }
452 }
453 void            CcdPhysicsController::applyImpulse(float attachX,float attachY,float attachZ, float impulseX,float impulseY,float impulseZ)
454 {
455         btVector3 impulse(impulseX,impulseY,impulseZ);
456
457         if (impulse.length2() > (SIMD_EPSILON*SIMD_EPSILON))
458         {
459                 m_body->activate();
460                 
461                 btVector3 pos(attachX,attachY,attachZ);
462
463                 m_body->activate();
464
465                 m_body->applyImpulse(impulse,pos);
466         }
467
468 }
469 void            CcdPhysicsController::SetActive(bool active)
470 {
471 }
472                 // reading out information from physics
473 void            CcdPhysicsController::GetLinearVelocity(float& linvX,float& linvY,float& linvZ)
474 {
475         const btVector3& linvel = this->m_body->getLinearVelocity();
476         linvX = linvel.x();
477         linvY = linvel.y();
478         linvZ = linvel.z();
479
480 }
481
482 void            CcdPhysicsController::GetAngularVelocity(float& angVelX,float& angVelY,float& angVelZ)
483 {
484         const btVector3& angvel= m_body->getAngularVelocity();
485         angVelX = angvel.x();
486         angVelY = angvel.y();
487         angVelZ = angvel.z();
488 }
489
490 void            CcdPhysicsController::GetVelocity(const float posX,const float posY,const float posZ,float& linvX,float& linvY,float& linvZ)
491 {
492         btVector3 pos(posX,posY,posZ);
493         btVector3 rel_pos = pos-m_body->getCenterOfMassPosition();
494         btVector3 linvel = m_body->getVelocityInLocalPoint(rel_pos);
495         linvX = linvel.x();
496         linvY = linvel.y();
497         linvZ = linvel.z();
498 }
499 void            CcdPhysicsController::getReactionForce(float& forceX,float& forceY,float& forceZ)
500 {
501 }
502
503                 // dyna's that are rigidbody are free in orientation, dyna's with non-rigidbody are restricted 
504 void            CcdPhysicsController::setRigidBody(bool rigid)
505 {
506         if (!rigid)
507         {
508                 //fake it for now
509                 btVector3 inertia = m_body->getInvInertiaDiagLocal();
510                 inertia[1] = 0.f;
511                 m_body->setInvInertiaDiagLocal(inertia);
512                 m_body->updateInertiaTensor();
513         }
514 }
515
516                 // clientinfo for raycasts for example
517 void*           CcdPhysicsController::getNewClientInfo()
518 {
519         return m_newClientInfo;
520 }
521 void            CcdPhysicsController::setNewClientInfo(void* clientinfo)
522 {
523         m_newClientInfo = clientinfo;
524 }
525
526
527 void    CcdPhysicsController::UpdateDeactivation(float timeStep)
528 {
529         m_body->updateDeactivation( timeStep);
530 }
531
532 bool CcdPhysicsController::wantsSleeping()
533 {
534
535         return m_body->wantsSleeping();
536 }
537
538 PHY_IPhysicsController* CcdPhysicsController::GetReplica()
539 {
540         //very experimental, shape sharing is not implemented yet.
541         //just support btSphereShape/ConeShape for now
542
543         CcdConstructionInfo cinfo = m_cci;
544         if (cinfo.m_collisionShape)
545         {
546                 switch (cinfo.m_collisionShape->getShapeType())
547                 {
548                 case SPHERE_SHAPE_PROXYTYPE:
549                         {
550                                 btSphereShape* orgShape = (btSphereShape*)cinfo.m_collisionShape;
551                                 cinfo.m_collisionShape = new btSphereShape(*orgShape);
552                                 break;
553                         }
554
555                         case CONE_SHAPE_PROXYTYPE:
556                         {
557                                 btConeShape* orgShape = (btConeShape*)cinfo.m_collisionShape;
558                                 cinfo.m_collisionShape = new btConeShape(*orgShape);
559                                 break;
560                         }
561
562
563                 default:
564                         {
565                                 return 0;
566                         }
567                 }
568         }
569
570         cinfo.m_MotionState = new DefaultMotionState();
571
572         CcdPhysicsController* replica = new CcdPhysicsController(cinfo);
573         return replica;
574 }
575
576 ///////////////////////////////////////////////////////////
577 ///A small utility class, DefaultMotionState
578 ///
579 ///////////////////////////////////////////////////////////
580
581 DefaultMotionState::DefaultMotionState()
582 {
583         m_worldTransform.setIdentity();
584         m_localScaling.setValue(1.f,1.f,1.f);
585 }
586
587
588 DefaultMotionState::~DefaultMotionState()
589 {
590
591 }
592
593 void    DefaultMotionState::getWorldPosition(float& posX,float& posY,float& posZ)
594 {
595         posX = m_worldTransform.getOrigin().x();
596         posY = m_worldTransform.getOrigin().y();
597         posZ = m_worldTransform.getOrigin().z();
598 }
599
600 void    DefaultMotionState::getWorldScaling(float& scaleX,float& scaleY,float& scaleZ)
601 {
602         scaleX = m_localScaling.getX();
603         scaleY = m_localScaling.getY();
604         scaleZ = m_localScaling.getZ();
605 }
606
607 void    DefaultMotionState::getWorldOrientation(float& quatIma0,float& quatIma1,float& quatIma2,float& quatReal)
608 {
609         quatIma0 = m_worldTransform.getRotation().x();
610         quatIma1 = m_worldTransform.getRotation().y();
611         quatIma2 = m_worldTransform.getRotation().z();
612         quatReal = m_worldTransform.getRotation()[3];
613 }
614                 
615 void    DefaultMotionState::setWorldPosition(float posX,float posY,float posZ)
616 {
617         btPoint3 pos(posX,posY,posZ);
618         m_worldTransform.setOrigin( pos );
619 }
620
621 void    DefaultMotionState::setWorldOrientation(float quatIma0,float quatIma1,float quatIma2,float quatReal)
622 {
623         btQuaternion orn(quatIma0,quatIma1,quatIma2,quatReal);
624         m_worldTransform.setRotation( orn );
625 }
626                 
627 void    DefaultMotionState::calculateWorldTransformations()
628 {
629
630 }
631