a6e7daadb2c04bbc1d61df1b848d0d5a7a5e8e37
[blender.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 #pragma warning (disable : 4786)
33
34 // defines USE_ODE to choose physics engine
35 #include "KX_ConvertPhysicsObject.h"
36 #include "KX_GameObject.h"
37 #include "RAS_MeshObject.h"
38 #include "KX_Scene.h"
39 #include "SYS_System.h"
40
41 #include "PHY_Pro.h" //todo cleanup
42 #include "KX_ClientObjectInfo.h"
43
44 #include "GEN_Map.h"
45 #include "GEN_HashedPtr.h"
46
47 #include "KX_PhysicsEngineEnums.h"
48 #include "PHY_Pro.h"
49
50 #include "KX_MotionState.h" // bridge between motionstate and scenegraph node
51
52 #ifdef HAVE_CONFIG_H
53 #include <config.h>
54 #endif
55
56 #ifdef USE_ODE
57
58 #include "KX_OdePhysicsController.h"
59 #include "OdePhysicsEnvironment.h"
60 #endif //USE_ODE
61
62
63 // USE_SUMO_SOLID is defined in headerfile KX_ConvertPhysicsObject.h
64 #ifdef USE_SUMO_SOLID
65
66
67 #include "SumoPhysicsEnvironment.h"
68 #include "KX_SumoPhysicsController.h"
69
70
71 // sumo physics specific
72 #include "SM_Object.h"
73 #include "SM_FhObject.h"
74 #include "SM_Scene.h"
75 #include "SM_ClientObjectInfo.h"
76
77 #include "KX_SumoPhysicsController.h"
78
79 GEN_Map<GEN_HashedPtr,DT_ShapeHandle> map_gamemesh_to_sumoshape;
80
81 // forward declarations
82 void    BL_RegisterSumoObject(KX_GameObject* gameobj,class SM_Scene* sumoScene,DT_SceneHandle solidscene,class SM_Object* sumoObj,const char* matname,bool isDynamic,bool isActor);
83 DT_ShapeHandle CreateShapeFromMesh(RAS_MeshObject* meshobj);
84
85
86 void    KX_ConvertSumoObject(   class   KX_GameObject* gameobj,
87                                                         class   RAS_MeshObject* meshobj,
88                                                         class   KX_Scene* kxscene,
89                                                         PHY_ShapeProps* kxshapeprops,
90                                                         PHY_MaterialProps*      kxmaterial,
91                                                         struct  KX_ObjectProperties*    objprop)
92
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 = kxshapeprops->m_inertia;
106         smprop->m_lin_drag = kxshapeprops->m_lin_drag;
107         smprop->m_mass = kxshapeprops->m_mass;
108
109
110         SM_MaterialProps* smmaterial = new SM_MaterialProps;
111
112         smmaterial->m_fh_damping = kxmaterial->m_fh_damping;
113         smmaterial->m_fh_distance = kxmaterial->m_fh_distance;
114         smmaterial->m_fh_normal = kxmaterial->m_fh_normal;
115         smmaterial->m_fh_spring = kxmaterial->m_fh_spring;
116         smmaterial->m_friction = kxmaterial->m_friction;
117         smmaterial->m_restitution = kxmaterial->m_restitution;
118
119         class SumoPhysicsEnvironment* sumoEnv =
120                 (SumoPhysicsEnvironment*)kxscene->GetPhysicsEnvironment();
121
122         SM_Scene*       sceneptr = sumoEnv->GetSumoScene();
123
124
125
126         SM_Object*      sumoObj=NULL;
127
128         if (objprop->m_dyna)
129         {
130                 
131                 DT_ShapeHandle shape    =       DT_Sphere(0.0);
132
133                 if (objprop->m_ghost)
134                 {
135
136                         sumoObj                                 =       new SM_Object(shape,NULL,smprop,NULL);
137                 } else
138                 {
139                         sumoObj                                 =       new SM_Object(shape,smmaterial,smprop,NULL);
140                 }
141                 
142                 double radius =                 objprop->m_radius;
143                 
144                 MT_Scalar margin = radius;//0.5;
145                 sumoObj->setMargin(margin);
146                 
147                 //if (bRigidBody) 
148                 //{
149                         if (objprop->m_in_active_layer)
150                         {
151                                 DT_AddObject(sumoEnv->GetSolidScene(),
152                                         sumoObj->getObjectHandle());
153                         }
154                 //}
155                 
156                 if (objprop->m_angular_rigidbody)
157                 {
158                         sumoObj->setRigidBody(true);
159                 } else
160                 {
161                         sumoObj->setRigidBody(false);
162                 }
163
164                 bool isDynamic = true;
165                 bool isActor = true;
166
167                 BL_RegisterSumoObject(gameobj,sceneptr,sumoEnv->GetSolidScene(),sumoObj,NULL,isDynamic,isActor);
168                 
169         } 
170         else {
171                 // non physics object
172                 if (meshobj)
173                 {
174                         int numpolys = meshobj->NumPolygons();
175
176                         {
177
178                                 DT_ShapeHandle complexshape=0;
179
180                                 if (objprop->m_implicitbox)
181                                 {
182                                         complexshape = DT_Box(objprop->m_boundingbox.m_extends[0],objprop->m_boundingbox.m_extends[1],objprop->m_boundingbox.m_extends[2]);
183                                 } else
184                                 {
185                                         if (numpolys>0)
186                                         {
187                                                 complexshape    =       CreateShapeFromMesh(meshobj);
188                                         }
189                                 }
190                                 
191                                 if (complexshape)
192                                 {
193                                         SM_Object *dynamicParent = NULL;
194
195                                         if (objprop->m_dynamic_parent)
196                                         {
197                                                 // problem is how to find the dynamic parent
198                                                 // in the scenegraph
199                                                 KX_SumoPhysicsController* sumoctrl = 
200                                                 (KX_SumoPhysicsController*)
201                                                         objprop->m_dynamic_parent->GetPhysicsController();
202
203                                                 if (sumoctrl)
204                                                 {
205                                                         dynamicParent = sumoctrl->GetSumoObject();
206                                                 }
207
208                                                 assert(dynamicParent);
209                                         }
210                                 
211                                         
212                                         if (objprop->m_ghost)
213                                         {
214                                                 sumoObj = new SM_Object(complexshape,NULL,NULL, dynamicParent); 
215                                         } else
216                                         {
217                                                 sumoObj = new SM_Object(complexshape,smmaterial,NULL, dynamicParent);   
218                                         }
219                                         
220                                         if (objprop->m_in_active_layer)
221                                         {
222                                                 DT_AddObject(sumoEnv->GetSolidScene(),
223                                                         sumoObj->getObjectHandle());
224                                         }
225                                         
226                                         
227                                         const STR_String& matname=meshobj->GetMaterialName(0);
228
229                                         
230                                         BL_RegisterSumoObject(gameobj,sceneptr,
231                                                 sumoEnv->GetSolidScene(),sumoObj,
232                                                 matname.ReadPtr(),
233                                                 objprop->m_dyna,
234                                                 objprop->m_isactor);
235
236                                 }
237                         }
238                 }
239         }
240
241         // physics object get updated here !
242
243         
244         // lazy evaluation because we might not support scaling !gameobj->UpdateTransform();
245
246         if (objprop->m_in_active_layer && sumoObj)
247         {
248                 sceneptr->add(*sumoObj);
249         }
250
251 }
252
253
254
255 void    BL_RegisterSumoObject(KX_GameObject* gameobj,class SM_Scene* sumoScene,DT_SceneHandle solidscene,class SM_Object* sumoObj,const char* matname,bool isDynamic,bool isActor) {
256
257
258
259                 //gameobj->SetDynamic(isDynamic);
260
261                 PHY_IMotionState* motionstate = new KX_MotionState(gameobj->GetSGNode());
262
263                 // need easy access, not via 'node' etc.
264                 KX_SumoPhysicsController* physicscontroller = new KX_SumoPhysicsController(sumoScene,solidscene,sumoObj,motionstate,isDynamic);
265                 gameobj->SetPhysicsController(physicscontroller);
266                 physicscontroller->setClientInfo(gameobj);
267
268                 gameobj->GetSGNode()->AddSGController(physicscontroller);
269
270                 //gameobj->GetClientInfo()->m_type = (isActor ? 1 : 0);
271                 //gameobj->GetClientInfo()->m_clientobject = gameobj;
272
273                 // store materialname in auxinfo, needed for touchsensors
274                 //gameobj->GetClientInfo()->m_auxilary_info = (matname? (void*)(matname+2) : NULL);
275
276                 physicscontroller->SetObject(gameobj->GetSGNode());
277                                 
278                 //gameobj->SetDynamicsScaling(MT_Vector3(1.0, 1.0, 1.0));
279
280 };
281
282
283
284 DT_ShapeHandle CreateShapeFromMesh(RAS_MeshObject* meshobj)
285 {
286
287         DT_ShapeHandle* shapeptr = map_gamemesh_to_sumoshape[GEN_HashedPtr(meshobj)];
288         if (shapeptr)
289         {
290                 return *shapeptr;
291         }
292         
293         // todo: shared meshes
294         DT_ShapeHandle shape = DT_NewComplexShape();
295         int p=0;
296         int numpolys = meshobj->NumPolygons();
297         if (!numpolys)
298         {
299                 return NULL;
300         }
301         int numvalidpolys = 0;
302
303
304
305         for (p=0;p<meshobj->m_triangle_indices.size();p++)
306         {
307                 RAS_TriangleIndex& idx = meshobj->m_triangle_indices[p];
308                 
309                 // only add polygons that have the collisionflag set
310                 if (idx.m_collider)
311                 {
312                         DT_Begin();
313                         for (int v=0;v<3;v++)
314                         {
315                                 int num = meshobj->m_xyz_index_to_vertex_index_mapping[idx.m_index[v]].size();
316                                 if (num != 1)
317                                 {
318                                         int i=0;
319                                 }
320                                 RAS_MatArrayIndex& vertindex = meshobj->m_xyz_index_to_vertex_index_mapping[idx.m_index[v]][0];
321
322                                 numvalidpolys++;
323         
324                                 {
325                                         const MT_Point3& pt = meshobj->GetVertex(vertindex.m_array, 
326                                                                                                           vertindex.m_index,
327                                                                                                           (RAS_IPolyMaterial*)vertindex.m_matid)->xyz();
328                                         DT_Vertex(pt[0],pt[1],pt[2]);
329                                 }
330                         }
331                         DT_End();
332                 }
333         }
334
335         DT_EndComplexShape();
336
337         if (numvalidpolys > 0)
338         {
339                 map_gamemesh_to_sumoshape.insert(GEN_HashedPtr(meshobj),shape);
340                 return shape;
341         }
342
343         // memleak... todo: delete shape
344         return NULL;
345 }
346
347
348 void    KX_ClearSumoSharedShapes()
349 {
350         int numshapes = map_gamemesh_to_sumoshape.size();
351         for (int i=0;i<numshapes ;i++)
352         {
353                 DT_ShapeHandle shape = *map_gamemesh_to_sumoshape.at(i);
354                 DT_DeleteShape(shape);
355         }
356         
357         map_gamemesh_to_sumoshape.clear();
358 }
359
360
361
362
363
364 #endif //USE_SUMO_SOLID
365
366
367 #ifdef USE_ODE
368
369 void    KX_ConvertODEEngineObject(KX_GameObject* gameobj,
370                                                          RAS_MeshObject* meshobj,
371                                                          KX_Scene* kxscene,
372                                                         struct  PHY_ShapeProps* shapeprops,
373                                                         struct  PHY_MaterialProps*      smmaterial,
374                                                         struct  KX_ObjectProperties*    objprop)
375 {
376         // not yet, future extension :)
377         bool dyna=objprop->m_dyna;
378         bool fullRigidBody= ( objprop->m_dyna && objprop->m_angular_rigidbody) != 0;
379         bool phantom = objprop->m_ghost;
380         class PHY_IMotionState* motionstate = new KX_MotionState(gameobj->GetSGNode());
381
382         class ODEPhysicsEnvironment* odeEnv =
383                 (ODEPhysicsEnvironment*)kxscene->GetPhysicsEnvironment();
384
385         dxSpace* space = odeEnv->GetOdeSpace();
386         dxWorld* world = odeEnv->GetOdeWorld();
387
388         if (!objprop->m_implicitsphere &&
389                 MT_fuzzyZero(objprop->m_boundingbox.m_extends[0]) ||
390                 MT_fuzzyZero(objprop->m_boundingbox.m_extends[1]) ||
391                 MT_fuzzyZero(objprop->m_boundingbox.m_extends[2])
392                 )
393         {
394
395         } else
396         {
397
398                 KX_OdePhysicsController* physicscontroller = 
399                         new KX_OdePhysicsController(
400                         dyna,
401                         fullRigidBody,
402                         phantom,
403                         motionstate,
404                         space,
405                         world,
406                         shapeprops->m_mass,
407                         smmaterial->m_friction,
408                         smmaterial->m_restitution,
409                         objprop->m_implicitsphere,
410                         objprop->m_boundingbox.m_center,
411                         objprop->m_boundingbox.m_extends,
412                         objprop->m_radius
413                         );
414
415                 gameobj->SetPhysicsController(physicscontroller);
416                 physicscontroller->setClientInfo(gameobj);                                              
417                 gameobj->GetSGNode()->AddSGController(physicscontroller);
418
419                 bool isActor = objprop->m_isactor;
420                 STR_String materialname;
421                 if (meshobj)
422                         materialname = meshobj->GetMaterialName(0);
423
424                 const char* matname = materialname.ReadPtr();
425
426
427                 physicscontroller->SetObject(gameobj->GetSGNode());
428                                 
429         }
430 }
431
432
433 #endif // USE_ODE