Delete all SOLID shapes at the end of the game engine. They were all being leaked!
[blender-staging.git] / source / gameengine / Ketsji / KX_ConvertPhysicsObjects.cpp
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 #ifdef WIN32
33 #pragma warning (disable : 4786)
34 #endif
35
36 // defines USE_ODE to choose physics engine
37 #include "KX_ConvertPhysicsObject.h"
38 #include "KX_GameObject.h"
39 #include "RAS_MeshObject.h"
40 #include "KX_Scene.h"
41 #include "SYS_System.h"
42
43 #include "PHY_Pro.h" //todo cleanup
44 #include "KX_ClientObjectInfo.h"
45
46 #include "GEN_Map.h"
47 #include "GEN_HashedPtr.h"
48
49 #include "KX_PhysicsEngineEnums.h"
50 #include "PHY_Pro.h"
51
52 #include "KX_MotionState.h" // bridge between motionstate and scenegraph node
53
54 #ifdef HAVE_CONFIG_H
55 #include <config.h>
56 #endif
57
58 #ifdef USE_ODE
59
60 #include "KX_OdePhysicsController.h"
61 #include "OdePhysicsEnvironment.h"
62 #endif //USE_ODE
63
64
65 // USE_SUMO_SOLID is defined in headerfile KX_ConvertPhysicsObject.h
66 #ifdef USE_SUMO_SOLID
67
68 #include "SumoPhysicsEnvironment.h"
69 #include "KX_SumoPhysicsController.h"
70
71
72 // sumo physics specific
73 #include "SM_Object.h"
74 #include "SM_FhObject.h"
75 #include "SM_Scene.h"
76 #include "SM_ClientObjectInfo.h"
77
78 #include "KX_SumoPhysicsController.h"
79
80 static GEN_Map<GEN_HashedPtr,DT_ShapeHandle> map_gamemesh_to_sumoshape;
81
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);
85
86
87 void    KX_ConvertSumoObject(   KX_GameObject* gameobj,
88                                 RAS_MeshObject* meshobj,
89                                 KX_Scene* kxscene,
90                                 PHY_ShapeProps* kxshapeprops,
91                                 PHY_MaterialProps*      kxmaterial,
92                                 struct  KX_ObjectProperties*    objprop)
93
94
95 {
96         SM_ShapeProps* smprop = new SM_ShapeProps;
97
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;
109
110
111         SM_MaterialProps* smmaterial = new SM_MaterialProps;
112
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;
119
120         SumoPhysicsEnvironment* sumoEnv =
121                 (SumoPhysicsEnvironment*)kxscene->GetPhysicsEnvironment();
122
123         SM_Scene*       sceneptr = sumoEnv->GetSumoScene();
124
125         SM_Object*      sumoObj=NULL;
126
127         if (objprop->m_dyna && objprop->m_isactor)
128         {
129                 DT_ShapeHandle shape = NULL;
130                 switch (objprop->m_boundclass)
131                 {
132                         case KX_BOUNDBOX:
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();
140                                 break;
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);
146                                 break;
147                         case KX_BOUNDCONE:
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);
152                                 break;
153                         /* Dynamic mesh objects.  WARNING! slow. */
154                         case KX_BOUNDMESH:
155                                 if (meshobj && meshobj->NumPolygons() > 0)
156                                 {
157                                         if ((shape = CreateShapeFromMesh(meshobj)))
158                                         {
159                                                 // TODO: calculate proper inertia
160                                                 smprop->m_inertia *= smprop->m_mass*smprop->m_radius*smprop->m_radius;
161                                                 break;
162                                         }
163                                 }
164                                 /* If CreateShapeFromMesh fails, fall through and use sphere */
165                         default:
166                         case KX_BOUNDSPHERE:
167                                 shape = DT_NewSphere(objprop->m_radius);
168                                 smprop->m_inertia *= smprop->m_mass*smprop->m_radius*smprop->m_radius;
169                                 break;
170                                 
171                 }
172                 
173                 sumoObj = new SM_Object(shape, !objprop->m_ghost?smmaterial:NULL,smprop,NULL);
174                 
175                 sumoObj->setRigidBody(objprop->m_angular_rigidbody?true:false);
176                 
177                 BL_RegisterSumoObject(gameobj,sceneptr,sumoObj,"",true, true);
178                 
179         } 
180         else {
181                 // non physics object
182                 if (meshobj)
183                 {
184                         int numpolys = meshobj->NumPolygons();
185                         {
186
187                                 DT_ShapeHandle complexshape=0;
188
189                                 switch (objprop->m_boundclass)
190                                 {
191                                         case KX_BOUNDBOX:
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]);
193                                                 break;
194                                         case KX_BOUNDSPHERE:
195                                                 complexshape = DT_NewSphere(objprop->m_boundobject.c.m_radius);
196                                                 break;
197                                         case KX_BOUNDCYLINDER:
198                                                 complexshape = DT_NewCylinder(objprop->m_boundobject.c.m_radius, objprop->m_boundobject.c.m_height);
199                                                 break;
200                                         case KX_BOUNDCONE:
201                                                 complexshape = DT_NewCone(objprop->m_boundobject.c.m_radius, objprop->m_boundobject.c.m_height);
202                                                 break;
203                                         default:
204                                         case KX_BOUNDMESH:
205                                                 if (numpolys>0)
206                                                 {
207                                                         complexshape = CreateShapeFromMesh(meshobj);
208                                                         //std::cout << "Convert Physics Mesh: " << meshobj->GetName() << std::endl;
209 /*                                                      if (!complexshape) 
210                                                         {
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;
216                                                         } */
217                                                 }
218                                                 break;
219                                 }
220                                 
221                                 if (complexshape)
222                                 {
223                                         SM_Object *dynamicParent = NULL;
224
225                                         if (objprop->m_dynamic_parent)
226                                         {
227                                                 // problem is how to find the dynamic parent
228                                                 // in the scenegraph
229                                                 KX_SumoPhysicsController* sumoctrl = 
230                                                 (KX_SumoPhysicsController*)
231                                                         objprop->m_dynamic_parent->GetPhysicsController();
232
233                                                 if (sumoctrl)
234                                                 {
235                                                         dynamicParent = sumoctrl->GetSumoObject();
236                                                 }
237
238                                                 assert(dynamicParent);
239                                         }
240                                 
241                                         
242                                         sumoObj = new SM_Object(complexshape,!objprop->m_ghost?smmaterial:NULL,NULL, dynamicParent);    
243                                         const STR_String& matname=meshobj->GetMaterialName(0);
244
245                                         
246                                         BL_RegisterSumoObject(gameobj,sceneptr,
247                                                 sumoObj,
248                                                 matname,
249                                                 objprop->m_dyna,
250                                                 objprop->m_isactor);
251                                 }
252                         }
253                 }
254         }
255
256         // physics object get updated here !
257
258         
259         // lazy evaluation because we might not support scaling !gameobj->UpdateTransform();
260
261         if (objprop->m_in_active_layer && sumoObj)
262         {
263                 sceneptr->add(*sumoObj);
264         }
265
266 }
267
268
269
270 void    BL_RegisterSumoObject(
271         KX_GameObject* gameobj,
272         class SM_Scene* sumoScene,
273         class SM_Object* sumoObj,
274         const STR_String& matname,
275         bool isDynamic,
276         bool isActor) 
277 {
278                 PHY_IMotionState* motionstate = new KX_MotionState(gameobj->GetSGNode());
279
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);
284                 
285                 if (!gameobj->getClientInfo())
286                         std::cout << "BL_RegisterSumoObject: WARNING: Object " << gameobj->GetName() << " has no client info" << std::endl;
287                 sumoObj->setClientObject(gameobj->getClientInfo());
288
289                 gameobj->GetSGNode()->AddSGController(physicscontroller);
290
291                 gameobj->getClientInfo()->m_type = (isActor ? KX_ClientObjectInfo::ACTOR : KX_ClientObjectInfo::STATIC);
292
293                 // store materialname in auxinfo, needed for touchsensors
294                 gameobj->getClientInfo()->m_auxilary_info = (matname.Length() ? (void*)(matname.ReadPtr()+2) : NULL);
295
296                 physicscontroller->SetObject(gameobj->GetSGNode());
297 }
298
299 DT_ShapeHandle CreateShapeFromMesh(RAS_MeshObject* meshobj)
300 {
301
302         DT_ShapeHandle *shapeptr = map_gamemesh_to_sumoshape[GEN_HashedPtr(meshobj)];
303         if (shapeptr)
304         {
305                 return *shapeptr;
306         }
307         
308         int numpolys = meshobj->NumPolygons();
309         if (!numpolys)
310         {
311                 return NULL;
312         }
313         int numvalidpolys = 0;
314
315         for (int p=0; p<numpolys; p++)
316         {
317                 RAS_Polygon* poly = meshobj->GetPolygon(p);
318         
319                 // only add polygons that have the collisionflag set
320                 if (poly->IsCollider())
321                 {
322                         numvalidpolys++;
323                         break;
324                 }
325         }
326         
327         if (numvalidpolys < 1)
328                 return NULL;
329         
330         DT_ShapeHandle shape = DT_NewComplexShape(NULL);
331         
332         
333         numvalidpolys = 0;
334
335         for (int p2=0; p2<numpolys; p2++)
336         {
337                 RAS_Polygon* poly = meshobj->GetPolygon(p2);
338         
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 */
342                     DT_Begin();
343                         DT_Vector3 pt;
344                         /* V1 */
345                         meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray, 
346                                 poly->GetVertexIndexBase().m_indexarray[2],
347                                 poly->GetMaterial()->GetPolyMaterial())->xyz().getValue(pt);
348                         DT_Vertex(pt);
349                         /* V2 */
350                         meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray, 
351                                 poly->GetVertexIndexBase().m_indexarray[1],
352                                 poly->GetMaterial()->GetPolyMaterial())->xyz().getValue(pt);
353                         DT_Vertex(pt);
354                         /* V3 */
355                         meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray, 
356                                 poly->GetVertexIndexBase().m_indexarray[0],
357                                 poly->GetMaterial()->GetPolyMaterial())->xyz().getValue(pt);
358                         DT_Vertex(pt);
359                         
360                         numvalidpolys++;
361                     DT_End();
362                         
363                         if (poly->VertexCount() == 4)
364                         {
365                             DT_Begin();
366                                 /* V1 */
367                                 meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray, 
368                                         poly->GetVertexIndexBase().m_indexarray[3],
369                                         poly->GetMaterial()->GetPolyMaterial())->xyz().getValue(pt);
370                                 DT_Vertex(pt);
371                                 /* V3 */
372                                 meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray, 
373                                         poly->GetVertexIndexBase().m_indexarray[2],
374                                         poly->GetMaterial()->GetPolyMaterial())->xyz().getValue(pt);
375                                 DT_Vertex(pt);
376                                 /* V4 */
377                                 meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray, 
378                                         poly->GetVertexIndexBase().m_indexarray[0],
379                                         poly->GetMaterial()->GetPolyMaterial())->xyz().getValue(pt);
380                                 DT_Vertex(pt);
381                         
382                                 numvalidpolys++;
383                             DT_End();
384                         }
385         
386                 }
387         }
388         
389         DT_EndComplexShape();
390
391         if (numvalidpolys > 0)
392         {
393                 map_gamemesh_to_sumoshape.insert(GEN_HashedPtr(meshobj),shape);
394                 return shape;
395         }
396
397         delete shape;
398         return NULL;
399 }
400
401
402 void    KX_ClearSumoSharedShapes()
403 {
404         int numshapes = map_gamemesh_to_sumoshape.size();
405         for (int i=0;i<numshapes ;i++)
406         {
407                 DT_ShapeHandle shape = *map_gamemesh_to_sumoshape.at(i);
408                 DT_DeleteShape(shape);
409         }
410         
411         map_gamemesh_to_sumoshape.clear();
412 }
413
414
415
416
417
418 #endif //USE_SUMO_SOLID
419
420
421 #ifdef USE_ODE
422
423 void    KX_ConvertODEEngineObject(KX_GameObject* gameobj,
424                                                          RAS_MeshObject* meshobj,
425                                                          KX_Scene* kxscene,
426                                                         struct  PHY_ShapeProps* shapeprops,
427                                                         struct  PHY_MaterialProps*      smmaterial,
428                                                         struct  KX_ObjectProperties*    objprop)
429 {
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());
435
436         class ODEPhysicsEnvironment* odeEnv =
437                 (ODEPhysicsEnvironment*)kxscene->GetPhysicsEnvironment();
438
439         dxSpace* space = odeEnv->GetOdeSpace();
440         dxWorld* world = odeEnv->GetOdeWorld();
441
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])
446                 )
447         {
448
449         } else
450         {
451
452                 KX_OdePhysicsController* physicscontroller = 
453                         new KX_OdePhysicsController(
454                         dyna,
455                         fullRigidBody,
456                         phantom,
457                         motionstate,
458                         space,
459                         world,
460                         shapeprops->m_mass,
461                         smmaterial->m_friction,
462                         smmaterial->m_restitution,
463                         objprop->m_implicitsphere,
464                         objprop->m_boundingbox.m_center,
465                         objprop->m_boundingbox.m_extends,
466                         objprop->m_radius
467                         );
468
469                 gameobj->SetPhysicsController(physicscontroller);
470                 physicscontroller->setClientInfo(gameobj);                                              
471                 gameobj->GetSGNode()->AddSGController(physicscontroller);
472
473                 bool isActor = objprop->m_isactor;
474                 STR_String materialname;
475                 if (meshobj)
476                         materialname = meshobj->GetMaterialName(0);
477
478                 const char* matname = materialname.ReadPtr();
479
480
481                 physicscontroller->SetObject(gameobj->GetSGNode());
482                                 
483         }
484 }
485
486
487 #endif // USE_ODE