4 * ***** BEGIN GPL/BL DUAL 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. 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
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.
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.
23 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
24 * All rights reserved.
26 * The Original Code is: all of this file.
28 * Contributor(s): none yet.
30 * ***** END GPL/BL DUAL LICENSE BLOCK *****
33 #pragma warning (disable : 4786)
36 // defines USE_ODE to choose physics engine
37 #include "KX_ConvertPhysicsObject.h"
38 #include "KX_GameObject.h"
39 #include "RAS_MeshObject.h"
41 #include "SYS_System.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
60 #include "KX_OdePhysicsController.h"
61 #include "OdePhysicsEnvironment.h"
65 // USE_SUMO_SOLID is defined in headerfile KX_ConvertPhysicsObject.h
68 #include "SumoPhysicsEnvironment.h"
69 #include "KX_SumoPhysicsController.h"
72 // sumo physics specific
73 #include "SM_Object.h"
74 #include "SM_FhObject.h"
76 #include "SM_ClientObjectInfo.h"
78 #include "KX_SumoPhysicsController.h"
80 static GEN_Map<GEN_HashedPtr,DT_ShapeHandle> map_gamemesh_to_sumoshape;
82 // forward declarations
83 void BL_RegisterSumoObject(KX_GameObject* gameobj,class SM_Scene* sumoScene,class SM_Object* sumoObj,const STR_String& matname,bool isDynamic,bool isActor);
84 DT_ShapeHandle CreateShapeFromMesh(RAS_MeshObject* meshobj);
87 void KX_ConvertSumoObject( KX_GameObject* gameobj,
88 RAS_MeshObject* meshobj,
90 PHY_ShapeProps* kxshapeprops,
91 PHY_MaterialProps* kxmaterial,
92 struct KX_ObjectProperties* objprop)
96 SM_ShapeProps* smprop = new SM_ShapeProps;
98 smprop->m_ang_drag = kxshapeprops->m_ang_drag;
99 smprop->m_do_anisotropic = kxshapeprops->m_do_anisotropic;
100 smprop->m_do_fh = kxshapeprops->m_do_fh;
101 smprop->m_do_rot_fh = kxshapeprops->m_do_rot_fh ;
102 smprop->m_friction_scaling[0] = kxshapeprops->m_friction_scaling[0];
103 smprop->m_friction_scaling[1] = kxshapeprops->m_friction_scaling[1];
104 smprop->m_friction_scaling[2] = kxshapeprops->m_friction_scaling[2];
105 smprop->m_inertia = MT_Vector3(1., 1., 1.) * kxshapeprops->m_inertia;
106 smprop->m_lin_drag = kxshapeprops->m_lin_drag;
107 smprop->m_mass = kxshapeprops->m_mass;
108 smprop->m_radius = objprop->m_radius;
111 SM_MaterialProps* smmaterial = new SM_MaterialProps;
113 smmaterial->m_fh_damping = kxmaterial->m_fh_damping;
114 smmaterial->m_fh_distance = kxmaterial->m_fh_distance;
115 smmaterial->m_fh_normal = kxmaterial->m_fh_normal;
116 smmaterial->m_fh_spring = kxmaterial->m_fh_spring;
117 smmaterial->m_friction = kxmaterial->m_friction;
118 smmaterial->m_restitution = kxmaterial->m_restitution;
120 SumoPhysicsEnvironment* sumoEnv =
121 (SumoPhysicsEnvironment*)kxscene->GetPhysicsEnvironment();
123 SM_Scene* sceneptr = sumoEnv->GetSumoScene();
125 SM_Object* sumoObj=NULL;
127 if (objprop->m_dyna && objprop->m_isactor)
129 DT_ShapeHandle shape = NULL;
130 switch (objprop->m_boundclass)
133 shape = DT_NewBox(objprop->m_boundobject.box.m_extends[0],
134 objprop->m_boundobject.box.m_extends[1],
135 objprop->m_boundobject.box.m_extends[2]);
136 smprop->m_inertia.scale(objprop->m_boundobject.box.m_extends[0]*objprop->m_boundobject.box.m_extends[0],
137 objprop->m_boundobject.box.m_extends[1]*objprop->m_boundobject.box.m_extends[1],
138 objprop->m_boundobject.box.m_extends[2]*objprop->m_boundobject.box.m_extends[2]);
139 smprop->m_inertia *= smprop->m_mass/MT_Vector3(objprop->m_boundobject.box.m_extends).length();
141 case KX_BOUNDCYLINDER:
142 shape = DT_NewCylinder(smprop->m_radius, objprop->m_boundobject.c.m_height);
143 smprop->m_inertia.scale(smprop->m_mass*smprop->m_radius*smprop->m_radius,
144 smprop->m_mass*smprop->m_radius*smprop->m_radius,
145 smprop->m_mass*objprop->m_boundobject.c.m_height*objprop->m_boundobject.c.m_height);
148 shape = DT_NewCone(objprop->m_radius, objprop->m_boundobject.c.m_height);
149 smprop->m_inertia.scale(smprop->m_mass*smprop->m_radius*smprop->m_radius,
150 smprop->m_mass*smprop->m_radius*smprop->m_radius,
151 smprop->m_mass*objprop->m_boundobject.c.m_height*objprop->m_boundobject.c.m_height);
153 /* Dynamic mesh objects. WARNING! slow. */
155 if (meshobj && meshobj->NumPolygons() > 0)
157 if ((shape = CreateShapeFromMesh(meshobj)))
159 // TODO: calculate proper inertia
160 smprop->m_inertia *= smprop->m_mass*smprop->m_radius*smprop->m_radius;
164 /* If CreateShapeFromMesh fails, fall through and use sphere */
167 shape = DT_NewSphere(objprop->m_radius);
168 smprop->m_inertia *= smprop->m_mass*smprop->m_radius*smprop->m_radius;
173 sumoObj = new SM_Object(shape, !objprop->m_ghost?smmaterial:NULL,smprop,NULL);
175 sumoObj->setRigidBody(objprop->m_angular_rigidbody?true:false);
177 BL_RegisterSumoObject(gameobj,sceneptr,sumoObj,"",true, true);
181 // non physics object
184 int numpolys = meshobj->NumPolygons();
187 DT_ShapeHandle complexshape=0;
189 switch (objprop->m_boundclass)
192 complexshape = DT_NewBox(objprop->m_boundobject.box.m_extends[0], objprop->m_boundobject.box.m_extends[1], objprop->m_boundobject.box.m_extends[2]);
195 complexshape = DT_NewSphere(objprop->m_boundobject.c.m_radius);
197 case KX_BOUNDCYLINDER:
198 complexshape = DT_NewCylinder(objprop->m_boundobject.c.m_radius, objprop->m_boundobject.c.m_height);
201 complexshape = DT_NewCone(objprop->m_boundobject.c.m_radius, objprop->m_boundobject.c.m_height);
207 complexshape = CreateShapeFromMesh(meshobj);
208 //std::cout << "Convert Physics Mesh: " << meshobj->GetName() << std::endl;
209 /* if (!complexshape)
211 // Something has to be done here - if the object has no polygons, it will not be able to have
212 // sensors attached to it.
213 DT_Vector3 pt = {0., 0., 0.};
214 complexshape = DT_NewSphere(1.0);
215 objprop->m_ghost = evilObject = true;
223 SM_Object *dynamicParent = NULL;
225 if (objprop->m_dynamic_parent)
227 // problem is how to find the dynamic parent
229 KX_SumoPhysicsController* sumoctrl =
230 (KX_SumoPhysicsController*)
231 objprop->m_dynamic_parent->GetPhysicsController();
235 dynamicParent = sumoctrl->GetSumoObject();
238 assert(dynamicParent);
242 sumoObj = new SM_Object(complexshape,!objprop->m_ghost?smmaterial:NULL,NULL, dynamicParent);
243 const STR_String& matname=meshobj->GetMaterialName(0);
246 BL_RegisterSumoObject(gameobj,sceneptr,
256 // physics object get updated here !
259 // lazy evaluation because we might not support scaling !gameobj->UpdateTransform();
261 if (objprop->m_in_active_layer && sumoObj)
263 sceneptr->add(*sumoObj);
270 void BL_RegisterSumoObject(
271 KX_GameObject* gameobj,
272 class SM_Scene* sumoScene,
273 class SM_Object* sumoObj,
274 const STR_String& matname,
278 PHY_IMotionState* motionstate = new KX_MotionState(gameobj->GetSGNode());
280 // need easy access, not via 'node' etc.
281 KX_SumoPhysicsController* physicscontroller = new KX_SumoPhysicsController(sumoScene,sumoObj,motionstate,isDynamic);
282 gameobj->SetPhysicsController(physicscontroller);
283 physicscontroller->setClientInfo(gameobj);
285 if (!gameobj->getClientInfo())
286 std::cout << "BL_RegisterSumoObject: WARNING: Object " << gameobj->GetName() << " has no client info" << std::endl;
287 sumoObj->setClientObject(gameobj->getClientInfo());
289 gameobj->GetSGNode()->AddSGController(physicscontroller);
291 gameobj->getClientInfo()->m_type = (isActor ? KX_ClientObjectInfo::ACTOR : KX_ClientObjectInfo::STATIC);
293 // store materialname in auxinfo, needed for touchsensors
294 gameobj->getClientInfo()->m_auxilary_info = (matname.Length() ? (void*)(matname.ReadPtr()+2) : NULL);
296 physicscontroller->SetObject(gameobj->GetSGNode());
299 DT_ShapeHandle CreateShapeFromMesh(RAS_MeshObject* meshobj)
302 DT_ShapeHandle *shapeptr = map_gamemesh_to_sumoshape[GEN_HashedPtr(meshobj)];
308 int numpolys = meshobj->NumPolygons();
313 int numvalidpolys = 0;
315 for (int p=0; p<numpolys; p++)
317 RAS_Polygon* poly = meshobj->GetPolygon(p);
319 // only add polygons that have the collisionflag set
320 if (poly->IsCollider())
327 if (numvalidpolys < 1)
330 DT_ShapeHandle shape = DT_NewComplexShape(NULL);
335 for (int p2=0; p2<numpolys; p2++)
337 RAS_Polygon* poly = meshobj->GetPolygon(p2);
339 // only add polygons that have the collisionflag set
340 if (poly->IsCollider())
341 { /* We have to tesselate here because SOLID can only raycast triangles */
345 meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray,
346 poly->GetVertexIndexBase().m_indexarray[2],
347 poly->GetMaterial()->GetPolyMaterial())->xyz().getValue(pt);
350 meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray,
351 poly->GetVertexIndexBase().m_indexarray[1],
352 poly->GetMaterial()->GetPolyMaterial())->xyz().getValue(pt);
355 meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray,
356 poly->GetVertexIndexBase().m_indexarray[0],
357 poly->GetMaterial()->GetPolyMaterial())->xyz().getValue(pt);
363 if (poly->VertexCount() == 4)
367 meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray,
368 poly->GetVertexIndexBase().m_indexarray[3],
369 poly->GetMaterial()->GetPolyMaterial())->xyz().getValue(pt);
372 meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray,
373 poly->GetVertexIndexBase().m_indexarray[2],
374 poly->GetMaterial()->GetPolyMaterial())->xyz().getValue(pt);
377 meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray,
378 poly->GetVertexIndexBase().m_indexarray[0],
379 poly->GetMaterial()->GetPolyMaterial())->xyz().getValue(pt);
389 DT_EndComplexShape();
391 if (numvalidpolys > 0)
393 map_gamemesh_to_sumoshape.insert(GEN_HashedPtr(meshobj),shape);
402 void KX_ClearSumoSharedShapes()
404 int numshapes = map_gamemesh_to_sumoshape.size();
405 for (int i=0;i<numshapes ;i++)
407 DT_ShapeHandle shape = *map_gamemesh_to_sumoshape.at(i);
408 DT_DeleteShape(shape);
411 map_gamemesh_to_sumoshape.clear();
418 #endif //USE_SUMO_SOLID
423 void KX_ConvertODEEngineObject(KX_GameObject* gameobj,
424 RAS_MeshObject* meshobj,
426 struct PHY_ShapeProps* shapeprops,
427 struct PHY_MaterialProps* smmaterial,
428 struct KX_ObjectProperties* objprop)
430 // not yet, future extension :)
431 bool dyna=objprop->m_dyna;
432 bool fullRigidBody= ( objprop->m_dyna && objprop->m_angular_rigidbody) != 0;
433 bool phantom = objprop->m_ghost;
434 class PHY_IMotionState* motionstate = new KX_MotionState(gameobj->GetSGNode());
436 class ODEPhysicsEnvironment* odeEnv =
437 (ODEPhysicsEnvironment*)kxscene->GetPhysicsEnvironment();
439 dxSpace* space = odeEnv->GetOdeSpace();
440 dxWorld* world = odeEnv->GetOdeWorld();
442 if (!objprop->m_implicitsphere &&
443 MT_fuzzyZero(objprop->m_boundingbox.m_extends[0]) ||
444 MT_fuzzyZero(objprop->m_boundingbox.m_extends[1]) ||
445 MT_fuzzyZero(objprop->m_boundingbox.m_extends[2])
452 KX_OdePhysicsController* physicscontroller =
453 new KX_OdePhysicsController(
461 smmaterial->m_friction,
462 smmaterial->m_restitution,
463 objprop->m_implicitsphere,
464 objprop->m_boundingbox.m_center,
465 objprop->m_boundingbox.m_extends,
469 gameobj->SetPhysicsController(physicscontroller);
470 physicscontroller->setClientInfo(gameobj);
471 gameobj->GetSGNode()->AddSGController(physicscontroller);
473 bool isActor = objprop->m_isactor;
474 STR_String materialname;
476 materialname = meshobj->GetMaterialName(0);
478 const char* matname = materialname.ReadPtr();
481 physicscontroller->SetObject(gameobj->GetSGNode());