4 * ***** BEGIN GPL LICENSE BLOCK *****
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.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
21 * All rights reserved.
23 * The Original Code is: all of this file.
25 * Contributor(s): none yet.
27 * ***** END GPL LICENSE BLOCK *****
29 #if defined(WIN32) && !defined(FREE_WINDOWS)
30 #pragma warning (disable : 4786)
33 #include "MT_assert.h"
35 #include "KX_SoftBodyDeformer.h"
36 #include "KX_ConvertPhysicsObject.h"
37 #include "BL_DeformableGameObject.h"
38 #include "RAS_MeshObject.h"
40 #include "SYS_System.h"
41 #include "BulletSoftBody/btSoftBody.h"
43 #include "PHY_Pro.h" //todo cleanup
44 #include "KX_ClientObjectInfo.h"
47 #include "GEN_HashedPtr.h"
49 #include "KX_PhysicsEngineEnums.h"
52 #include "KX_MotionState.h" // bridge between motionstate and scenegraph node
55 #include "BKE_DerivedMesh.h"
60 #include "CcdPhysicsEnvironment.h"
61 #include "CcdPhysicsController.h"
62 #include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h"
64 #include "KX_BulletPhysicsController.h"
65 #include "btBulletDynamicsCommon.h"
69 //only use SIMD Hull code under Win32
73 //#define TEST_SIMD_HULL 1
75 #include "NarrowPhaseCollision/Hull.h"
76 #endif //#ifdef TEST_HULL
83 // forward declarations
85 void KX_ConvertBulletObject( class KX_GameObject* gameobj,
86 class RAS_MeshObject* meshobj,
87 struct DerivedMesh* dm,
88 class KX_Scene* kxscene,
89 struct PHY_ShapeProps* shapeprops,
90 struct PHY_MaterialProps* smmaterial,
91 struct KX_ObjectProperties* objprop)
94 CcdPhysicsEnvironment* env = (CcdPhysicsEnvironment*)kxscene->GetPhysicsEnvironment();
98 bool isbulletdyna = false;
99 bool isbulletsensor = false;
100 bool useGimpact = false;
101 CcdConstructionInfo ci;
102 class PHY_IMotionState* motionstate = new KX_MotionState(gameobj->GetSGNode());
103 class CcdShapeConstructionInfo *shapeInfo = new CcdShapeConstructionInfo();
106 if (!objprop->m_dyna)
108 ci.m_collisionFlags |= btCollisionObject::CF_STATIC_OBJECT;
110 if (objprop->m_ghost)
112 ci.m_collisionFlags |= btCollisionObject::CF_NO_CONTACT_RESPONSE;
115 ci.m_MotionState = motionstate;
116 ci.m_gravity = btVector3(0,0,0);
117 ci.m_localInertiaTensor =btVector3(0,0,0);
118 ci.m_mass = objprop->m_dyna ? shapeprops->m_mass : 0.f;
119 ci.m_clamp_vel_min = shapeprops->m_clamp_vel_min;
120 ci.m_clamp_vel_max = shapeprops->m_clamp_vel_max;
121 ci.m_margin = objprop->m_margin;
122 shapeInfo->m_radius = objprop->m_radius;
123 isbulletdyna = objprop->m_dyna;
124 isbulletsensor = objprop->m_sensor;
125 useGimpact = ((isbulletdyna || isbulletsensor) && !objprop->m_softbody);
127 ci.m_localInertiaTensor = btVector3(ci.m_mass/3.f,ci.m_mass/3.f,ci.m_mass/3.f);
129 btCollisionShape* bm = 0;
131 switch (objprop->m_boundclass)
135 //float radius = objprop->m_radius;
136 //btVector3 inertiaHalfExtents (
141 //blender doesn't support multisphere, but for testing:
143 //bm = new MultiSphereShape(inertiaHalfExtents,,&trans.getOrigin(),&radius,1);
144 shapeInfo->m_shapeType = PHY_SHAPE_SPHERE;
145 bm = shapeInfo->CreateBulletShape(ci.m_margin);
150 shapeInfo->m_halfExtend.setValue(
151 objprop->m_boundobject.box.m_extends[0],
152 objprop->m_boundobject.box.m_extends[1],
153 objprop->m_boundobject.box.m_extends[2]);
155 shapeInfo->m_halfExtend /= 2.0;
156 shapeInfo->m_halfExtend = shapeInfo->m_halfExtend.absolute();
157 shapeInfo->m_shapeType = PHY_SHAPE_BOX;
158 bm = shapeInfo->CreateBulletShape(ci.m_margin);
161 case KX_BOUNDCYLINDER:
163 shapeInfo->m_halfExtend.setValue(
164 objprop->m_boundobject.c.m_radius,
165 objprop->m_boundobject.c.m_radius,
166 objprop->m_boundobject.c.m_height * 0.5f
168 shapeInfo->m_shapeType = PHY_SHAPE_CYLINDER;
169 bm = shapeInfo->CreateBulletShape(ci.m_margin);
175 shapeInfo->m_radius = objprop->m_boundobject.c.m_radius;
176 shapeInfo->m_height = objprop->m_boundobject.c.m_height;
177 shapeInfo->m_shapeType = PHY_SHAPE_CONE;
178 bm = shapeInfo->CreateBulletShape(ci.m_margin);
181 case KX_BOUNDPOLYTOPE:
183 shapeInfo->SetMesh(meshobj, dm,true);
184 bm = shapeInfo->CreateBulletShape(ci.m_margin);
187 case KX_BOUNDCAPSULE:
189 shapeInfo->m_radius = objprop->m_boundobject.c.m_radius;
190 shapeInfo->m_height = objprop->m_boundobject.c.m_height;
191 shapeInfo->m_shapeType = PHY_SHAPE_CAPSULE;
192 bm = shapeInfo->CreateBulletShape(ci.m_margin);
197 // mesh shapes can be shared, check first if we already have a shape on that mesh
198 class CcdShapeConstructionInfo *sharedShapeInfo = CcdShapeConstructionInfo::FindMesh(meshobj, dm, false);
199 if (sharedShapeInfo != NULL)
201 shapeInfo->Release();
202 shapeInfo = sharedShapeInfo;
206 shapeInfo->SetMesh(meshobj, dm, false);
209 // Soft bodies require welding. Only avoid remove doubles for non-soft bodies!
210 if (objprop->m_softbody)
212 shapeInfo->setVertexWeldingThreshold1(objprop->m_soft_welding); //todo: expose this to the UI
215 bm = shapeInfo->CreateBulletShape(ci.m_margin, useGimpact, !objprop->m_softbody);
216 //should we compute inertia for dynamic shape?
217 //bm->calculateLocalInertia(ci.m_mass,ci.m_localInertiaTensor);
224 // ci.m_localInertiaTensor.setValue(0.1f,0.1f,0.1f);
229 shapeInfo->Release();
233 //bm->setMargin(ci.m_margin);
236 if (objprop->m_isCompoundChild)
238 //find parent, compound shape and add to it
239 //take relative transform into account!
240 KX_BulletPhysicsController* parentCtrl = (KX_BulletPhysicsController*)objprop->m_dynamic_parent->GetPhysicsController();
242 CcdShapeConstructionInfo* parentShapeInfo = parentCtrl->GetShapeInfo();
243 btRigidBody* rigidbody = parentCtrl->GetRigidBody();
244 btCollisionShape* colShape = rigidbody->getCollisionShape();
245 assert(colShape->isCompound());
246 btCompoundShape* compoundShape = (btCompoundShape*)colShape;
248 // compute the local transform from parent, this may include several node in the chain
249 SG_Node* gameNode = gameobj->GetSGNode();
250 SG_Node* parentNode = objprop->m_dynamic_parent->GetSGNode();
251 // relative transform
252 MT_Vector3 parentScale = parentNode->GetWorldScaling();
253 parentScale[0] = MT_Scalar(1.0)/parentScale[0];
254 parentScale[1] = MT_Scalar(1.0)/parentScale[1];
255 parentScale[2] = MT_Scalar(1.0)/parentScale[2];
256 MT_Vector3 relativeScale = gameNode->GetWorldScaling() * parentScale;
257 MT_Matrix3x3 parentInvRot = parentNode->GetWorldOrientation().transposed();
258 MT_Vector3 relativePos = parentInvRot*((gameNode->GetWorldPosition()-parentNode->GetWorldPosition())*parentScale);
259 MT_Matrix3x3 relativeRot = parentInvRot*gameNode->GetWorldOrientation();
261 shapeInfo->m_childScale.setValue(relativeScale[0],relativeScale[1],relativeScale[2]);
262 bm->setLocalScaling(shapeInfo->m_childScale);
263 shapeInfo->m_childTrans.getOrigin().setValue(relativePos[0],relativePos[1],relativePos[2]);
265 relativeRot.getValue(rot);
266 shapeInfo->m_childTrans.getBasis().setFromOpenGLSubMatrix(rot);
268 parentShapeInfo->AddShape(shapeInfo);
269 compoundShape->addChildShape(shapeInfo->m_childTrans,bm);
271 //recalc inertia for rigidbody
272 if (!rigidbody->isStaticOrKinematicObject())
274 btVector3 localInertia;
275 float mass = 1.f/rigidbody->getInvMass();
276 compoundShape->calculateLocalInertia(mass,localInertia);
277 rigidbody->setMassProps(mass,localInertia);
279 shapeInfo->Release();
280 // delete motionstate as it's not used
285 if (objprop->m_hasCompoundChildren)
287 // create a compound shape info
288 CcdShapeConstructionInfo *compoundShapeInfo = new CcdShapeConstructionInfo();
289 compoundShapeInfo->m_shapeType = PHY_SHAPE_COMPOUND;
290 compoundShapeInfo->AddShape(shapeInfo);
291 // create the compound shape manually as we already have the child shape
292 btCompoundShape* compoundShape = new btCompoundShape();
293 compoundShape->addChildShape(shapeInfo->m_childTrans,bm);
294 // now replace the shape
296 shapeInfo->Release();
297 shapeInfo = compoundShapeInfo;
305 #ifdef TEST_SIMD_HULL
306 if (bm->IsPolyhedral())
308 PolyhedralConvexShape* polyhedron = static_cast<PolyhedralConvexShape*>(bm);
309 if (!polyhedron->m_optionalHull)
311 //first convert vertices in 'Point3' format
312 int numPoints = polyhedron->GetNumVertices();
313 Point3* points = new Point3[numPoints+1];
314 //first 4 points should not be co-planar, so add central point to satisfy MakeHull
315 points[0] = Point3(0.f,0.f,0.f);
318 for (int p=0;p<numPoints;p++)
320 polyhedron->GetVertex(p,vertex);
321 points[p+1] = Point3(vertex.getX(),vertex.getY(),vertex.getZ());
324 Hull* hull = Hull::MakeHull(numPoints+1,points);
325 polyhedron->m_optionalHull = hull;
329 #endif //TEST_SIMD_HULL
332 ci.m_collisionShape = bm;
333 ci.m_shapeInfo = shapeInfo;
334 ci.m_friction = smmaterial->m_friction;//tweak the friction a bit, so the default 0.5 works nice
335 ci.m_restitution = smmaterial->m_restitution;
336 ci.m_physicsEnv = env;
337 // drag / damping is inverted
338 ci.m_linearDamping = 1.f - shapeprops->m_lin_drag;
339 ci.m_angularDamping = 1.f - shapeprops->m_ang_drag;
340 //need a bit of damping, else system doesn't behave well
341 ci.m_inertiaFactor = shapeprops->m_inertia/0.4f;//defaults to 0.4, don't want to change behaviour
343 ci.m_do_anisotropic = shapeprops->m_do_anisotropic;
344 ci.m_anisotropicFriction.setValue(shapeprops->m_friction_scaling[0],shapeprops->m_friction_scaling[1],shapeprops->m_friction_scaling[2]);
349 ci.m_do_fh = shapeprops->m_do_fh;
350 ci.m_do_rot_fh = shapeprops->m_do_rot_fh ;
351 ci.m_fh_damping = smmaterial->m_fh_damping;
352 ci.m_fh_distance = smmaterial->m_fh_distance;
353 ci.m_fh_normal = smmaterial->m_fh_normal;
354 ci.m_fh_spring = smmaterial->m_fh_spring;
355 ci.m_radius = objprop->m_radius;
359 ci.m_gamesoftFlag = objprop->m_gamesoftFlag;
360 ci.m_soft_linStiff = objprop->m_soft_linStiff;
361 ci.m_soft_angStiff = objprop->m_soft_angStiff; /* angular stiffness 0..1 */
362 ci.m_soft_volume= objprop->m_soft_volume; /* volume preservation 0..1 */
364 ci.m_soft_viterations= objprop->m_soft_viterations; /* Velocities solver iterations */
365 ci.m_soft_piterations= objprop->m_soft_piterations; /* Positions solver iterations */
366 ci.m_soft_diterations= objprop->m_soft_diterations; /* Drift solver iterations */
367 ci.m_soft_citerations= objprop->m_soft_citerations; /* Cluster solver iterations */
369 ci.m_soft_kSRHR_CL= objprop->m_soft_kSRHR_CL; /* Soft vs rigid hardness [0,1] (cluster only) */
370 ci.m_soft_kSKHR_CL= objprop->m_soft_kSKHR_CL; /* Soft vs kinetic hardness [0,1] (cluster only) */
371 ci.m_soft_kSSHR_CL= objprop->m_soft_kSSHR_CL; /* Soft vs soft hardness [0,1] (cluster only) */
372 ci.m_soft_kSR_SPLT_CL= objprop->m_soft_kSR_SPLT_CL; /* Soft vs rigid impulse split [0,1] (cluster only) */
374 ci.m_soft_kSK_SPLT_CL= objprop->m_soft_kSK_SPLT_CL; /* Soft vs rigid impulse split [0,1] (cluster only) */
375 ci.m_soft_kSS_SPLT_CL= objprop->m_soft_kSS_SPLT_CL; /* Soft vs rigid impulse split [0,1] (cluster only) */
376 ci.m_soft_kVCF= objprop->m_soft_kVCF; /* Velocities correction factor (Baumgarte) */
377 ci.m_soft_kDP= objprop->m_soft_kDP; /* Damping coefficient [0,1] */
379 ci.m_soft_kDG= objprop->m_soft_kDG; /* Drag coefficient [0,+inf] */
380 ci.m_soft_kLF= objprop->m_soft_kLF; /* Lift coefficient [0,+inf] */
381 ci.m_soft_kPR= objprop->m_soft_kPR; /* Pressure coefficient [-inf,+inf] */
382 ci.m_soft_kVC= objprop->m_soft_kVC; /* Volume conversation coefficient [0,+inf] */
384 ci.m_soft_kDF= objprop->m_soft_kDF; /* Dynamic friction coefficient [0,1] */
385 ci.m_soft_kMT= objprop->m_soft_kMT; /* Pose matching coefficient [0,1] */
386 ci.m_soft_kCHR= objprop->m_soft_kCHR; /* Rigid contacts hardness [0,1] */
387 ci.m_soft_kKHR= objprop->m_soft_kKHR; /* Kinetic contacts hardness [0,1] */
389 ci.m_soft_kSHR= objprop->m_soft_kSHR; /* Soft contacts hardness [0,1] */
390 ci.m_soft_kAHR= objprop->m_soft_kAHR; /* Anchors hardness [0,1] */
391 ci.m_soft_collisionflags= objprop->m_soft_collisionflags; /* Vertex/Face or Signed Distance Field(SDF) or Clusters, Soft versus Soft or Rigid */
392 ci.m_soft_numclusteriterations= objprop->m_soft_numclusteriterations; /* number of iterations to refine collision clusters*/
395 ci.m_collisionFilterGroup =
396 (isbulletsensor) ? short(CcdConstructionInfo::SensorFilter) :
397 (isbulletdyna) ? short(CcdConstructionInfo::DefaultFilter) :
398 short(CcdConstructionInfo::StaticFilter);
399 ci.m_collisionFilterMask =
400 (isbulletsensor) ? short(CcdConstructionInfo::AllFilter ^ CcdConstructionInfo::SensorFilter) :
401 (isbulletdyna) ? short(CcdConstructionInfo::AllFilter) :
402 short(CcdConstructionInfo::AllFilter ^ CcdConstructionInfo::StaticFilter);
403 ci.m_bRigid = objprop->m_dyna && objprop->m_angular_rigidbody;
405 ci.m_contactProcessingThreshold = objprop->m_contactProcessingThreshold;//todo: expose this in advanced settings, just like margin, default to 10000 or so
406 ci.m_bSoft = objprop->m_softbody;
407 ci.m_bSensor = isbulletsensor;
408 ci.m_bGimpact = useGimpact;
409 MT_Vector3 scaling = gameobj->NodeGetWorldScaling();
410 ci.m_scaling.setValue(scaling[0], scaling[1], scaling[2]);
411 KX_BulletPhysicsController* physicscontroller = new KX_BulletPhysicsController(ci,isbulletdyna,isbulletsensor,objprop->m_hasCompoundChildren);
412 // shapeInfo is reference counted, decrement now as we don't use it anymore
414 shapeInfo->Release();
416 gameobj->SetPhysicsController(physicscontroller,isbulletdyna);
417 // don't add automatically sensor object, they are added when a collision sensor is registered
418 if (!isbulletsensor && objprop->m_in_active_layer)
420 env->addCcdPhysicsController( physicscontroller);
422 physicscontroller->setNewClientInfo(gameobj->getClientInfo());
424 btRigidBody* rbody = physicscontroller->GetRigidBody();
428 if (objprop->m_angular_rigidbody)
430 btVector3 linearFactor(
431 objprop->m_lockXaxis? 0 : 1,
432 objprop->m_lockYaxis? 0 : 1,
433 objprop->m_lockZaxis? 0 : 1);
434 btVector3 angularFactor(
435 objprop->m_lockXRotaxis? 0 : 1,
436 objprop->m_lockYRotaxis? 0 : 1,
437 objprop->m_lockZRotaxis? 0 : 1);
438 rbody->setLinearFactor(linearFactor);
439 rbody->setAngularFactor(angularFactor);
442 if (rbody && objprop->m_disableSleeping)
444 rbody->setActivationState(DISABLE_DEACTIVATION);
449 CcdPhysicsController* parentCtrl = objprop->m_dynamic_parent ? (KX_BulletPhysicsController*)objprop->m_dynamic_parent->GetPhysicsController() : 0;
450 physicscontroller->setParentCtrl(parentCtrl);
453 //Now done directly in ci.m_collisionFlags so that it propagates to replica
454 //if (objprop->m_ghost)
456 // rbody->setCollisionFlags(rbody->getCollisionFlags() | btCollisionObject::CF_NO_CONTACT_RESPONSE);
459 if (objprop->m_dyna && !objprop->m_angular_rigidbody)
462 //setting the inertia could achieve similar results to constraint the up
463 //but it is prone to instability, so use special 'Angular' constraint
464 btVector3 inertia = physicscontroller->GetRigidBody()->getInvInertiaDiagLocal();
468 physicscontroller->GetRigidBody()->setInvInertiaDiagLocal(inertia);
469 physicscontroller->GetRigidBody()->updateInertiaTensor();
472 //env->createConstraint(physicscontroller,0,PHY_ANGULAR_CONSTRAINT,0,0,0,0,0,1);
474 //Now done directly in ci.m_bRigid so that it propagates to replica
475 //physicscontroller->GetRigidBody()->setAngularFactor(0.f);
479 bool isActor = objprop->m_isactor;
480 gameobj->getClientInfo()->m_type =
481 (isbulletsensor) ? ((isActor) ? KX_ClientObjectInfo::OBACTORSENSOR : KX_ClientObjectInfo::OBSENSOR) :
482 (isActor) ? KX_ClientObjectInfo::ACTOR : KX_ClientObjectInfo::STATIC;
483 // store materialname in auxinfo, needed for touchsensors
486 const STR_String& matname=meshobj->GetMaterialName(0);
487 gameobj->getClientInfo()->m_auxilary_info = (matname.Length() ? (void*)(matname.ReadPtr()+2) : NULL);
490 gameobj->getClientInfo()->m_auxilary_info = 0;
494 gameobj->GetSGNode()->AddSGController(physicscontroller);
496 STR_String materialname;
498 materialname = meshobj->GetMaterialName(0);
500 physicscontroller->SetObject(gameobj->GetSGNode());
503 ///test for soft bodies
504 if (objprop->m_softbody && physicscontroller)
506 btSoftBody* softBody = physicscontroller->GetSoftBody();
507 if (softBody && gameobj->GetMesh(0))//only the first mesh, if any
509 //should be a mesh then, so add a soft body deformer
510 KX_SoftBodyDeformer* softbodyDeformer = new KX_SoftBodyDeformer( gameobj->GetMesh(0),(BL_DeformableGameObject*)gameobj);
511 gameobj->SetDeformer(softbodyDeformer);
519 void KX_ClearBulletSharedShapes()
523 /* Refresh the physics object from either an object or a mesh.
524 * gameobj must be valid
525 * from_gameobj and from_meshobj can be NULL
527 * when setting the mesh, the following vars get priority
528 * 1) from_meshobj - creates the phys mesh from RAS_MeshObject
529 * 2) from_gameobj - creates the phys mesh from the DerivedMesh where possible, else the RAS_MeshObject
530 * 3) gameobj - update the phys mesh from DerivedMesh or RAS_MeshObject
532 * Most of the logic behind this is in shapeInfo->UpdateMesh(...)
534 bool KX_ReInstanceBulletShapeFromMesh(KX_GameObject *gameobj, KX_GameObject *from_gameobj, RAS_MeshObject* from_meshobj)
536 KX_BulletPhysicsController *spc= static_cast<KX_BulletPhysicsController*>((gameobj->GetPhysicsController()));
537 CcdShapeConstructionInfo *shapeInfo;
539 /* if this is the child of a compound shape this can happen
540 * dont support compound shapes for now */
544 shapeInfo = spc->GetShapeInfo();
546 if(shapeInfo->m_shapeType != PHY_SHAPE_MESH/* || spc->GetSoftBody()*/)
549 spc->DeleteControllerShape();
551 if(from_gameobj==NULL && from_meshobj==NULL)
552 from_gameobj= gameobj;
554 /* updates the arrays used for making the new bullet mesh */
555 shapeInfo->UpdateMesh(from_gameobj, from_meshobj);
557 /* create the new bullet mesh */
558 CcdConstructionInfo& cci = spc->getConstructionInfo();
559 btCollisionShape* bm= shapeInfo->CreateBulletShape(cci.m_margin, cci.m_bGimpact, !cci.m_bSoft);
561 spc->ReplaceControllerShape(bm);