46b53d07efc6f68f0989ae283b47a05425c6c6cd
[blender.git] / source / gameengine / Ketsji / KX_ConvertPhysicsObjects.cpp
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL 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.
10  *
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.
15  *
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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19  *
20  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
21  * All rights reserved.
22  *
23  * The Original Code is: all of this file.
24  *
25  * Contributor(s): none yet.
26  *
27  * ***** END GPL LICENSE BLOCK *****
28  */
29 #ifdef WIN32
30 #pragma warning (disable : 4786)
31 #endif
32
33 #include "MT_assert.h"
34
35 // defines USE_ODE to choose physics engine
36 #include "KX_ConvertPhysicsObject.h"
37 #include "KX_GameObject.h"
38 #include "RAS_MeshObject.h"
39 #include "KX_Scene.h"
40 #include "SYS_System.h"
41
42 #include "PHY_Pro.h" //todo cleanup
43 #include "KX_ClientObjectInfo.h"
44
45 #include "GEN_Map.h"
46 #include "GEN_HashedPtr.h"
47
48 #include "KX_PhysicsEngineEnums.h"
49 #include "PHY_Pro.h"
50
51 #include "KX_MotionState.h" // bridge between motionstate and scenegraph node
52
53 #ifdef USE_ODE
54
55 #include "KX_OdePhysicsController.h"
56 #include "OdePhysicsEnvironment.h"
57 #endif //USE_ODE
58
59
60 // USE_SUMO_SOLID is defined in headerfile KX_ConvertPhysicsObject.h
61 #ifdef USE_SUMO_SOLID
62
63
64 #include "SumoPhysicsEnvironment.h"
65 #include "KX_SumoPhysicsController.h"
66
67
68 // sumo physics specific
69 #include "SM_Object.h"
70 #include "SM_FhObject.h"
71 #include "SM_Scene.h"
72 #include "SM_ClientObjectInfo.h"
73
74 #include "KX_SumoPhysicsController.h"
75
76 struct KX_PhysicsInstance
77 {
78         DT_VertexBaseHandle     m_vertexbase;
79         RAS_DisplayArray*       m_darray;
80         RAS_IPolyMaterial*      m_material;
81
82         KX_PhysicsInstance(DT_VertexBaseHandle vertex_base, RAS_DisplayArray *darray, RAS_IPolyMaterial* mat)
83                 : m_vertexbase(vertex_base),
84                 m_darray(darray),
85                 m_material(mat)
86         {
87         }
88
89         ~KX_PhysicsInstance()
90         {
91                 DT_DeleteVertexBase(m_vertexbase);
92         }
93 };
94
95 static GEN_Map<GEN_HashedPtr,DT_ShapeHandle> map_gamemesh_to_sumoshape;
96 static GEN_Map<GEN_HashedPtr, KX_PhysicsInstance*> map_gamemesh_to_instance;
97
98 // forward declarations
99 static void     BL_RegisterSumoObject(KX_GameObject* gameobj,class SM_Scene* sumoScene,class SM_Object* sumoObj,const STR_String& matname,bool isDynamic,bool isActor);
100 static DT_ShapeHandle CreateShapeFromMesh(RAS_MeshObject* meshobj, bool polytope);
101
102 void    KX_ConvertSumoObject(   KX_GameObject* gameobj,
103                 RAS_MeshObject* meshobj,
104                 KX_Scene* kxscene,
105                 PHY_ShapeProps* kxshapeprops,
106                 PHY_MaterialProps*      kxmaterial,
107                 struct  KX_ObjectProperties*    objprop)
108
109
110 {
111         SM_ShapeProps* smprop = new SM_ShapeProps;
112
113         smprop->m_ang_drag = kxshapeprops->m_ang_drag;
114         smprop->m_do_anisotropic = kxshapeprops->m_do_anisotropic;
115         smprop->m_do_fh = kxshapeprops->m_do_fh;
116         smprop->m_do_rot_fh = kxshapeprops->m_do_rot_fh ;
117         smprop->m_friction_scaling[0]  = kxshapeprops->m_friction_scaling[0];
118         smprop->m_friction_scaling[1]  = kxshapeprops->m_friction_scaling[1];
119         smprop->m_friction_scaling[2]  = kxshapeprops->m_friction_scaling[2];
120         smprop->m_inertia = MT_Vector3(1., 1., 1.) * kxshapeprops->m_inertia;
121         smprop->m_lin_drag = kxshapeprops->m_lin_drag;
122         smprop->m_mass = kxshapeprops->m_mass;
123         smprop->m_radius = objprop->m_radius;
124
125
126         SM_MaterialProps* smmaterial = new SM_MaterialProps;
127
128         smmaterial->m_fh_damping = kxmaterial->m_fh_damping;
129         smmaterial->m_fh_distance = kxmaterial->m_fh_distance;
130         smmaterial->m_fh_normal = kxmaterial->m_fh_normal;
131         smmaterial->m_fh_spring = kxmaterial->m_fh_spring;
132         smmaterial->m_friction = kxmaterial->m_friction;
133         smmaterial->m_restitution = kxmaterial->m_restitution;
134
135         SumoPhysicsEnvironment* sumoEnv =
136                 (SumoPhysicsEnvironment*)kxscene->GetPhysicsEnvironment();
137
138         SM_Scene*       sceneptr = sumoEnv->GetSumoScene();
139
140         SM_Object*      sumoObj=NULL;
141
142         if (objprop->m_dyna && objprop->m_isactor)
143         {
144                 DT_ShapeHandle shape = NULL;
145                 bool polytope = false;
146                 switch (objprop->m_boundclass)
147                 {
148                         case KX_BOUNDBOX:
149                                 shape = DT_NewBox(objprop->m_boundobject.box.m_extends[0], 
150                                                 objprop->m_boundobject.box.m_extends[1], 
151                                                 objprop->m_boundobject.box.m_extends[2]);
152                                 smprop->m_inertia.scale(objprop->m_boundobject.box.m_extends[0]*objprop->m_boundobject.box.m_extends[0],
153                                                 objprop->m_boundobject.box.m_extends[1]*objprop->m_boundobject.box.m_extends[1],
154                                                 objprop->m_boundobject.box.m_extends[2]*objprop->m_boundobject.box.m_extends[2]);
155                                 smprop->m_inertia *= smprop->m_mass/MT_Vector3(objprop->m_boundobject.box.m_extends).length();
156                                 break;
157                         case KX_BOUNDCYLINDER:
158                                 shape = DT_NewCylinder(smprop->m_radius, objprop->m_boundobject.c.m_height);
159                                 smprop->m_inertia.scale(smprop->m_mass*smprop->m_radius*smprop->m_radius,
160                                                 smprop->m_mass*smprop->m_radius*smprop->m_radius,
161                                                 smprop->m_mass*objprop->m_boundobject.c.m_height*objprop->m_boundobject.c.m_height);
162                                 break;
163                         case KX_BOUNDCONE:
164                                 shape = DT_NewCone(objprop->m_radius, objprop->m_boundobject.c.m_height);
165                                 smprop->m_inertia.scale(smprop->m_mass*smprop->m_radius*smprop->m_radius,
166                                                 smprop->m_mass*smprop->m_radius*smprop->m_radius,
167                                                 smprop->m_mass*objprop->m_boundobject.c.m_height*objprop->m_boundobject.c.m_height);
168                                 break;
169                                 /* Dynamic mesh objects.  WARNING! slow. */
170                         case KX_BOUNDPOLYTOPE:
171                                 polytope = true;
172                                 // fall through
173                         case KX_BOUNDMESH:
174                                 if (meshobj && meshobj->NumPolygons() > 0)
175                                 {
176                                         if ((shape = CreateShapeFromMesh(meshobj, polytope)))
177                                         {
178                                                 // TODO: calculate proper inertia
179                                                 smprop->m_inertia *= smprop->m_mass*smprop->m_radius*smprop->m_radius;
180                                                 break;
181                                         }
182                                 }
183                                 /* If CreateShapeFromMesh fails, fall through and use sphere */
184                         default:
185                         case KX_BOUNDSPHERE:
186                                 shape = DT_NewSphere(objprop->m_radius);
187                                 smprop->m_inertia *= smprop->m_mass*smprop->m_radius*smprop->m_radius;
188                                 break;
189
190                 }
191
192                 sumoObj = new SM_Object(shape, !objprop->m_ghost?smmaterial:NULL,smprop,NULL);
193
194                 sumoObj->setRigidBody(objprop->m_angular_rigidbody?true:false);
195
196                 BL_RegisterSumoObject(gameobj,sceneptr,sumoObj,"",true, true);
197
198         } 
199         else {
200                 // non physics object
201                 if (meshobj)
202                 {
203                         int numpolys = meshobj->NumPolygons();
204                         {
205
206                                 DT_ShapeHandle complexshape=0;
207                                 bool polytope = false;
208
209                                 switch (objprop->m_boundclass)
210                                 {
211                                         case KX_BOUNDBOX:
212                                                 complexshape = DT_NewBox(objprop->m_boundobject.box.m_extends[0], objprop->m_boundobject.box.m_extends[1], objprop->m_boundobject.box.m_extends[2]);
213                                                 break;
214                                         case KX_BOUNDSPHERE:
215                                                 complexshape = DT_NewSphere(objprop->m_boundobject.c.m_radius);
216                                                 break;
217                                         case KX_BOUNDCYLINDER:
218                                                 complexshape = DT_NewCylinder(objprop->m_boundobject.c.m_radius, objprop->m_boundobject.c.m_height);
219                                                 break;
220                                         case KX_BOUNDCONE:
221                                                 complexshape = DT_NewCone(objprop->m_boundobject.c.m_radius, objprop->m_boundobject.c.m_height);
222                                                 break;
223                                         case KX_BOUNDPOLYTOPE:
224                                                 polytope = true;
225                                                 // fall through
226                                         default:
227                                         case KX_BOUNDMESH:
228                                                 if (numpolys>0)
229                                                 {
230                                                         complexshape = CreateShapeFromMesh(meshobj, polytope);
231                                                         //std::cout << "Convert Physics Mesh: " << meshobj->GetName() << std::endl;
232 /*                                                      if (!complexshape) 
233                                                         {
234                                                                 // Something has to be done here - if the object has no polygons, it will not be able to have
235                                                                 //   sensors attached to it. 
236                                                                 DT_Vector3 pt = {0., 0., 0.};
237                                                                 complexshape = DT_NewSphere(1.0);
238                                                                 objprop->m_ghost = evilObject = true;
239                                                         } */
240                                                 }
241                                                 break;
242                                 }
243                                 
244                                 if (complexshape)
245                                 {
246                                         SM_Object *dynamicParent = NULL;
247
248                                         if (objprop->m_dynamic_parent)
249                                         {
250                                                 // problem is how to find the dynamic parent
251                                                 // in the scenegraph
252                                                 KX_SumoPhysicsController* sumoctrl = 
253                                                 (KX_SumoPhysicsController*)
254                                                         objprop->m_dynamic_parent->GetPhysicsController();
255
256                                                 if (sumoctrl)
257                                                 {
258                                                         dynamicParent = sumoctrl->GetSumoObject();
259                                                 }
260
261                                                 MT_assert(dynamicParent);
262                                         }
263                                 
264                                         
265                                         sumoObj = new SM_Object(complexshape,!objprop->m_ghost?smmaterial:NULL,NULL, dynamicParent);    
266                                         const STR_String& matname=meshobj->GetMaterialName(0);
267
268                                         
269                                         BL_RegisterSumoObject(gameobj,sceneptr,
270                                                 sumoObj,
271                                                 matname,
272                                                 objprop->m_dyna,
273                                                 objprop->m_isactor);
274                                 }
275                         }
276                 }
277         }
278
279         // physics object get updated here !
280
281         
282         // lazy evaluation because we might not support scaling !gameobj->UpdateTransform();
283
284         if (objprop->m_in_active_layer && sumoObj)
285         {
286                 sceneptr->add(*sumoObj);
287         }
288
289 }
290
291
292
293 static void     BL_RegisterSumoObject(
294         KX_GameObject* gameobj,
295         class SM_Scene* sumoScene,
296         class SM_Object* sumoObj,
297         const STR_String& matname,
298         bool isDynamic,
299         bool isActor) 
300 {
301                 PHY_IMotionState* motionstate = new KX_MotionState(gameobj->GetSGNode());
302
303                 // need easy access, not via 'node' etc.
304                 KX_SumoPhysicsController* physicscontroller = new KX_SumoPhysicsController(sumoScene,sumoObj,motionstate,isDynamic);
305                 gameobj->SetPhysicsController(physicscontroller,isDynamic);
306
307                 
308                 if (!gameobj->getClientInfo())
309                         std::cout << "BL_RegisterSumoObject: WARNING: Object " << gameobj->GetName() << " has no client info" << std::endl;
310                 physicscontroller->setNewClientInfo(gameobj->getClientInfo());
311                 
312
313                 gameobj->GetSGNode()->AddSGController(physicscontroller);
314
315                 gameobj->getClientInfo()->m_type = (isActor ? KX_ClientObjectInfo::ACTOR : KX_ClientObjectInfo::STATIC);
316
317                 // store materialname in auxinfo, needed for touchsensors
318                 gameobj->getClientInfo()->m_auxilary_info = (matname.Length() ? (void*)(matname.ReadPtr()+2) : NULL);
319
320                 physicscontroller->SetObject(gameobj->GetSGNode());
321 }
322
323 static DT_ShapeHandle InstancePhysicsComplex(RAS_MeshObject* meshobj, RAS_DisplayArray *darray, RAS_IPolyMaterial *mat)
324 {
325         // instance a mesh from a single vertex array & material
326         const RAS_TexVert *vertex_array = &darray->m_vertex[0];
327         DT_VertexBaseHandle vertex_base = DT_NewVertexBase(vertex_array[0].getXYZ(), sizeof(RAS_TexVert));
328         
329         DT_ShapeHandle shape = DT_NewComplexShape(vertex_base);
330         
331         std::vector<DT_Index> indices;
332         for (int p = 0; p < meshobj->NumPolygons(); p++)
333         {
334                 RAS_Polygon* poly = meshobj->GetPolygon(p);
335         
336                 // only add polygons that have the collisionflag set
337                 if (poly->IsCollider())
338                 {
339                         DT_Begin();
340                           DT_VertexIndex(poly->GetVertexOffset(0));
341                           DT_VertexIndex(poly->GetVertexOffset(1));
342                           DT_VertexIndex(poly->GetVertexOffset(2));
343                         DT_End();
344                         
345                         // tesselate
346                         if (poly->VertexCount() == 4)
347                         {
348                                 DT_Begin();
349                                   DT_VertexIndex(poly->GetVertexOffset(0));
350                                   DT_VertexIndex(poly->GetVertexOffset(2));
351                                   DT_VertexIndex(poly->GetVertexOffset(3));
352                                 DT_End();
353                         }
354                 }
355         }
356
357         //DT_VertexIndices(indices.size(), &indices[0]);
358         DT_EndComplexShape();
359         
360         map_gamemesh_to_instance.insert(GEN_HashedPtr(meshobj), new KX_PhysicsInstance(vertex_base, darray, mat));
361         return shape;
362 }
363
364 static DT_ShapeHandle InstancePhysicsPolytope(RAS_MeshObject* meshobj, RAS_DisplayArray *darray, RAS_IPolyMaterial *mat)
365 {
366         // instance a mesh from a single vertex array & material
367         const RAS_TexVert *vertex_array = &darray->m_vertex[0];
368         DT_VertexBaseHandle vertex_base = DT_NewVertexBase(vertex_array[0].getXYZ(), sizeof(RAS_TexVert));
369         
370         std::vector<DT_Index> indices;
371         for (int p = 0; p < meshobj->NumPolygons(); p++)
372         {
373                 RAS_Polygon* poly = meshobj->GetPolygon(p);
374         
375                 // only add polygons that have the collisionflag set
376                 if (poly->IsCollider())
377                 {
378                         indices.push_back(poly->GetVertexOffset(0));
379                         indices.push_back(poly->GetVertexOffset(1));
380                         indices.push_back(poly->GetVertexOffset(2));
381                         
382                         if (poly->VertexCount() == 4)
383                                 indices.push_back(poly->GetVertexOffset(3));
384                 }
385         }
386
387         DT_ShapeHandle shape = DT_NewPolytope(vertex_base);
388         DT_VertexIndices(indices.size(), &indices[0]);
389         DT_EndPolytope();
390         
391         map_gamemesh_to_instance.insert(GEN_HashedPtr(meshobj), new KX_PhysicsInstance(vertex_base, darray, mat));
392         return shape;
393 }
394
395 // This will have to be a method in a class somewhere...
396 // Update SOLID with a changed physics mesh.
397 // not used... yet.
398 bool KX_ReInstanceShapeFromMesh(RAS_MeshObject* meshobj)
399 {
400         KX_PhysicsInstance *instance = *map_gamemesh_to_instance[GEN_HashedPtr(meshobj)];
401         if (instance)
402         {
403                 const RAS_TexVert *vertex_array = &instance->m_darray->m_vertex[0];
404                 DT_ChangeVertexBase(instance->m_vertexbase, vertex_array[0].getXYZ());
405                 return true;
406         }
407         return false;
408 }
409
410 static DT_ShapeHandle CreateShapeFromMesh(RAS_MeshObject* meshobj, bool polytope)
411 {
412
413         DT_ShapeHandle *shapeptr = map_gamemesh_to_sumoshape[GEN_HashedPtr(meshobj)];
414         // Mesh has already been converted: reuse
415         if (shapeptr)
416         {
417                 return *shapeptr;
418         }
419         
420         // Mesh has no polygons!
421         int numpolys = meshobj->NumPolygons();
422         if (!numpolys)
423         {
424                 return NULL;
425         }
426         
427         // Count the number of collision polygons and check they all come from the same 
428         // vertex array
429         int numvalidpolys = 0;
430         RAS_DisplayArray *darray = NULL;
431         RAS_IPolyMaterial *poly_material = NULL;
432         bool reinstance = true;
433
434         for (int p=0; p<numpolys; p++)
435         {
436                 RAS_Polygon* poly = meshobj->GetPolygon(p);
437         
438                 // only add polygons that have the collisionflag set
439                 if (poly->IsCollider())
440                 {
441                         // check polygon is from the same vertex array
442                         if (poly->GetDisplayArray() != darray)
443                         {
444                                 if (darray == NULL)
445                                         darray = poly->GetDisplayArray();
446                                 else
447                                 {
448                                         reinstance = false;
449                                         darray = NULL;
450                                 }
451                         }
452                         
453                         // check poly is from the same material
454                         if (poly->GetMaterial()->GetPolyMaterial() != poly_material)
455                         {
456                                 if (poly_material)
457                                 {
458                                         reinstance = false;
459                                         poly_material = NULL;
460                                 }
461                                 else
462                                         poly_material = poly->GetMaterial()->GetPolyMaterial();
463                         }
464                         
465                         // count the number of collision polys
466                         numvalidpolys++;
467                         
468                         // We have one collision poly, and we can't reinstance, so we
469                         // might as well break here.
470                         if (!reinstance)
471                                 break;
472                 }
473         }
474         
475         // No collision polygons
476         if (numvalidpolys < 1)
477                 return NULL;
478         
479         DT_ShapeHandle shape;
480         if (reinstance)
481         {
482                 if (polytope)
483                         shape = InstancePhysicsPolytope(meshobj, darray, poly_material);
484                 else
485                         shape = InstancePhysicsComplex(meshobj, darray, poly_material);
486         }
487         else
488         {
489                 if (polytope)
490                 {
491                         std::cout << "CreateShapeFromMesh: " << meshobj->GetName() << " is not suitable for polytope." << std::endl;
492                         if (!poly_material)
493                                 std::cout << "                     Check mesh materials." << std::endl;
494                         if (darray == NULL)
495                                 std::cout << "                     Check number of vertices." << std::endl;
496                 }
497                 
498                 shape = DT_NewComplexShape(NULL);
499                         
500                 numvalidpolys = 0;
501         
502                 for (int p2=0; p2<numpolys; p2++)
503                 {
504                         RAS_Polygon* poly = meshobj->GetPolygon(p2);
505                 
506                         // only add polygons that have the collisionflag set
507                         if (poly->IsCollider())
508                         {   /* We have to tesselate here because SOLID can only raycast triangles */
509                            DT_Begin();
510                                 /* V1, V2, V3 */
511                                 DT_Vertex(poly->GetVertex(2)->getXYZ());
512                                 DT_Vertex(poly->GetVertex(1)->getXYZ());
513                                 DT_Vertex(poly->GetVertex(0)->getXYZ());
514                                 
515                                 numvalidpolys++;
516                            DT_End();
517                                 
518                                 if (poly->VertexCount() == 4)
519                                 {
520                                    DT_Begin();
521                                         /* V1, V3, V4 */
522                                         DT_Vertex(poly->GetVertex(3)->getXYZ());
523                                         DT_Vertex(poly->GetVertex(2)->getXYZ());
524                                         DT_Vertex(poly->GetVertex(0)->getXYZ());
525                                 
526                                         numvalidpolys++;
527                                    DT_End();
528                                 }
529                 
530                         }
531                 }
532                 
533                 DT_EndComplexShape();
534         }
535
536         if (numvalidpolys > 0)
537         {
538                 map_gamemesh_to_sumoshape.insert(GEN_HashedPtr(meshobj),shape);
539                 return shape;
540         }
541
542         delete shape;
543         return NULL;
544 }
545
546 void    KX_ClearSumoSharedShapes()
547 {
548         int numshapes = map_gamemesh_to_sumoshape.size();
549         int i;
550         for (i=0;i<numshapes ;i++)
551         {
552                 DT_ShapeHandle shape = *map_gamemesh_to_sumoshape.at(i);
553                 DT_DeleteShape(shape);
554         }
555         
556         map_gamemesh_to_sumoshape.clear();
557         
558         for (i=0; i < map_gamemesh_to_instance.size(); i++)
559                 delete *map_gamemesh_to_instance.at(i);
560         
561         map_gamemesh_to_instance.clear();
562 }
563
564
565
566
567
568 #endif //USE_SUMO_SOLID
569
570
571 #ifdef USE_ODE
572
573 void    KX_ConvertODEEngineObject(KX_GameObject* gameobj,
574                                                          RAS_MeshObject* meshobj,
575                                                          KX_Scene* kxscene,
576                                                         struct  PHY_ShapeProps* shapeprops,
577                                                         struct  PHY_MaterialProps*      smmaterial,
578                                                         struct  KX_ObjectProperties*    objprop)
579 {
580         
581         // not yet, future extension :)
582         bool dyna=objprop->m_dyna;
583         bool fullRigidBody= ( objprop->m_dyna && objprop->m_angular_rigidbody) != 0;
584         bool phantom = objprop->m_ghost;
585         class PHY_IMotionState* motionstate = new KX_MotionState(gameobj->GetSGNode());
586
587         class ODEPhysicsEnvironment* odeEnv =
588                 (ODEPhysicsEnvironment*)kxscene->GetPhysicsEnvironment();
589
590         dxSpace* space = odeEnv->GetOdeSpace();
591         dxWorld* world = odeEnv->GetOdeWorld();
592
593         bool isSphere = false;
594
595         switch (objprop->m_boundclass)
596         {
597         case KX_BOUNDBOX:
598                 {
599
600                                 KX_OdePhysicsController* physicscontroller = 
601                                         new KX_OdePhysicsController(
602                                         dyna,
603                                         fullRigidBody,
604                                         phantom,
605                                         motionstate,
606                                         space,
607                                         world,
608                                         shapeprops->m_mass,
609                                         smmaterial->m_friction,
610                                         smmaterial->m_restitution,
611                                         isSphere,
612                                         objprop->m_boundobject.box.m_center,
613                                         objprop->m_boundobject.box.m_extends,
614                                         objprop->m_boundobject.c.m_radius
615                                         );
616
617                                 gameobj->SetPhysicsController(physicscontroller);
618                                 physicscontroller->setNewClientInfo(gameobj->getClientInfo());                                          
619                                 gameobj->GetSGNode()->AddSGController(physicscontroller);
620
621                                 bool isActor = objprop->m_isactor;
622                                 STR_String materialname;
623                                 if (meshobj)
624                                         materialname = meshobj->GetMaterialName(0);
625
626                                 const char* matname = materialname.ReadPtr();
627
628
629                                 physicscontroller->SetObject(gameobj->GetSGNode());
630
631                                 break;
632                         }
633         default:
634                 {
635                 }
636         };
637
638 }
639
640
641 #endif // USE_ODE
642
643
644 #ifdef USE_BULLET
645
646 #include "CcdPhysicsEnvironment.h"
647 #include "CcdPhysicsController.h"
648 #include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h"
649
650 #include "KX_BulletPhysicsController.h"
651 #include "btBulletDynamicsCommon.h"
652
653                                                         #ifdef WIN32
654 #if _MSC_VER >= 1310
655 //only use SIMD Hull code under Win32
656 //#define TEST_HULL 1
657 #ifdef TEST_HULL
658 #define USE_HULL 1
659 //#define TEST_SIMD_HULL 1
660
661 #include "NarrowPhaseCollision/Hull.h"
662 #endif //#ifdef TEST_HULL
663
664 #endif //_MSC_VER 
665 #endif //WIN32
666
667
668 // forward declarations
669
670 void    KX_ConvertBulletObject( class   KX_GameObject* gameobj,
671         class   RAS_MeshObject* meshobj,
672         class   KX_Scene* kxscene,
673         struct  PHY_ShapeProps* shapeprops,
674         struct  PHY_MaterialProps*      smmaterial,
675         struct  KX_ObjectProperties*    objprop)
676 {
677
678         CcdPhysicsEnvironment* env = (CcdPhysicsEnvironment*)kxscene->GetPhysicsEnvironment();
679         assert(env);
680         
681
682         bool isbulletdyna = false;
683         CcdConstructionInfo ci;
684         class PHY_IMotionState* motionstate = new KX_MotionState(gameobj->GetSGNode());
685         class CcdShapeConstructionInfo *shapeInfo = new CcdShapeConstructionInfo();
686
687         
688
689         if (!objprop->m_dyna)
690         {
691                 ci.m_collisionFlags |= btCollisionObject::CF_STATIC_OBJECT;
692         }
693         if (objprop->m_ghost)
694         {
695                 ci.m_collisionFlags |= btCollisionObject::CF_NO_CONTACT_RESPONSE;
696         }
697
698         ci.m_MotionState = motionstate;
699         ci.m_gravity = btVector3(0,0,0);
700         ci.m_localInertiaTensor =btVector3(0,0,0);
701         ci.m_mass = objprop->m_dyna ? shapeprops->m_mass : 0.f;
702         ci.m_margin = objprop->m_margin;
703         shapeInfo->m_radius = objprop->m_radius;
704         isbulletdyna = objprop->m_dyna;
705         
706         ci.m_localInertiaTensor = btVector3(ci.m_mass/3.f,ci.m_mass/3.f,ci.m_mass/3.f);
707         
708         btCollisionShape* bm = 0;
709
710         switch (objprop->m_boundclass)
711         {
712         case KX_BOUNDSPHERE:
713                 {
714                         //float radius = objprop->m_radius;
715                         //btVector3 inertiaHalfExtents (
716                         //      radius,
717                         //      radius,
718                         //      radius);
719                         
720                         //blender doesn't support multisphere, but for testing:
721
722                         //bm = new MultiSphereShape(inertiaHalfExtents,,&trans.getOrigin(),&radius,1);
723                         shapeInfo->m_shapeType = PHY_SHAPE_SPHERE;
724                         bm = shapeInfo->CreateBulletShape();
725                         break;
726                 };
727         case KX_BOUNDBOX:
728                 {
729                         shapeInfo->m_halfExtend.setValue(
730                                 objprop->m_boundobject.box.m_extends[0],
731                                 objprop->m_boundobject.box.m_extends[1],
732                                 objprop->m_boundobject.box.m_extends[2]);
733
734                         shapeInfo->m_halfExtend /= 2.0;
735                         shapeInfo->m_halfExtend = shapeInfo->m_halfExtend.absolute();
736                         shapeInfo->m_shapeType = PHY_SHAPE_BOX;
737                         bm = shapeInfo->CreateBulletShape();
738                         break;
739                 };
740         case KX_BOUNDCYLINDER:
741                 {
742                         shapeInfo->m_halfExtend.setValue(
743                                 objprop->m_boundobject.c.m_radius,
744                                 objprop->m_boundobject.c.m_radius,
745                                 objprop->m_boundobject.c.m_height * 0.5f
746                         );
747                         shapeInfo->m_shapeType = PHY_SHAPE_CYLINDER;
748                         bm = shapeInfo->CreateBulletShape();
749                         break;
750                 }
751
752         case KX_BOUNDCONE:
753                 {
754                         shapeInfo->m_radius = objprop->m_boundobject.c.m_radius;
755                         shapeInfo->m_height = objprop->m_boundobject.c.m_height;
756                         shapeInfo->m_shapeType = PHY_SHAPE_CONE;
757                         bm = shapeInfo->CreateBulletShape();
758                         break;
759                 }
760         case KX_BOUNDPOLYTOPE:
761                 {
762                         shapeInfo->SetMesh(meshobj, true);
763                         bm = shapeInfo->CreateBulletShape();
764                         break;
765                 }
766         case KX_BOUNDMESH:
767                 {
768                         if (!ci.m_mass)
769                         {                               
770                                 // mesh shapes can be shared, check first if we already have a shape on that mesh
771                                 class CcdShapeConstructionInfo *sharedShapeInfo = CcdShapeConstructionInfo::FindMesh(meshobj, false);
772                                 if (sharedShapeInfo != NULL) 
773                                 {
774                                         delete shapeInfo;
775                                         shapeInfo = sharedShapeInfo;
776                                         shapeInfo->AddRef();
777                                 } else
778                                 {
779                                         shapeInfo->SetMesh(meshobj, false);
780                                 }
781                                 bm = shapeInfo->CreateBulletShape();
782                                 //no moving concave meshes, so don't bother calculating inertia
783                                 //bm->calculateLocalInertia(ci.m_mass,ci.m_localInertiaTensor);
784                         }
785
786                         break;
787                 }
788         }
789
790
791 //      ci.m_localInertiaTensor.setValue(0.1f,0.1f,0.1f);
792
793         if (!bm)
794         {
795                 delete motionstate;
796                 delete shapeInfo;
797                 return;
798         }
799
800         bm->setMargin(ci.m_margin);
801
802
803                 if (objprop->m_isCompoundChild)
804                 {
805                         //find parent, compound shape and add to it
806                         //take relative transform into account!
807                         KX_BulletPhysicsController* parentCtrl = (KX_BulletPhysicsController*)objprop->m_dynamic_parent->GetPhysicsController();
808                         assert(parentCtrl);
809                         CcdShapeConstructionInfo* parentShapeInfo = parentCtrl->GetShapeInfo();
810                         btRigidBody* rigidbody = parentCtrl->GetRigidBody();
811                         btCollisionShape* colShape = rigidbody->getCollisionShape();
812                         assert(colShape->isCompound());
813                         btCompoundShape* compoundShape = (btCompoundShape*)colShape;
814
815                         // compute the local transform from parent, this may include a parent inverse node
816                         SG_Node* gameNode = gameobj->GetSGNode();
817                         SG_Node* parentInverseNode = gameNode->GetSGParent();
818                         if (parentInverseNode && parentInverseNode->GetSGClientObject() != NULL)
819                                 // this is not a parent inverse node, cancel it
820                                 parentInverseNode = NULL;
821                         // now combine the parent inverse node and the game node
822                         MT_Point3 childPos = gameNode->GetLocalPosition();
823                         MT_Matrix3x3 childRot = gameNode->GetLocalOrientation();
824                         MT_Vector3 childScale = gameNode->GetLocalScale();
825                         if (parentInverseNode)
826                         {
827                                 const MT_Point3& parentInversePos = parentInverseNode->GetLocalPosition();
828                                 const MT_Matrix3x3& parentInverseRot = parentInverseNode->GetLocalOrientation();
829                                 const MT_Vector3& parentInverseScale = parentInverseNode->GetLocalScale();
830                                 childRot =  parentInverseRot * childRot;
831                                 childScale = parentInverseScale * childScale;
832                                 childPos = parentInversePos+parentInverseScale*(parentInverseRot*childPos);
833                         }
834
835                         shapeInfo->m_childScale.setValue(childScale.x(),childScale.y(),childScale.z());
836                         bm->setLocalScaling(shapeInfo->m_childScale);
837                         
838                         shapeInfo->m_childTrans.setOrigin(btVector3(childPos.x(),childPos.y(),childPos.z()));
839                         float rotval[12];
840                         childRot.getValue(rotval);
841                         btMatrix3x3 newRot;
842                         newRot.setValue(rotval[0],rotval[1],rotval[2],rotval[4],rotval[5],rotval[6],rotval[8],rotval[9],rotval[10]);
843                         newRot = newRot.transpose();
844
845                         shapeInfo->m_childTrans.setBasis(newRot);
846                         parentShapeInfo->AddShape(shapeInfo);   
847                         
848                         compoundShape->addChildShape(shapeInfo->m_childTrans,bm);
849                         //do some recalc?
850                         //recalc inertia for rigidbody
851                         if (!rigidbody->isStaticOrKinematicObject())
852                         {
853                                 btVector3 localInertia;
854                                 float mass = 1.f/rigidbody->getInvMass();
855                                 compoundShape->calculateLocalInertia(mass,localInertia);
856                                 rigidbody->setMassProps(mass,localInertia);
857                         }
858                         return;
859                 }
860
861                 if (objprop->m_hasCompoundChildren)
862                 {
863                         // create a compound shape info
864                         CcdShapeConstructionInfo *compoundShapeInfo = new CcdShapeConstructionInfo();
865                         compoundShapeInfo->m_shapeType = PHY_SHAPE_COMPOUND;
866                         compoundShapeInfo->AddShape(shapeInfo);
867                         // create the compound shape manually as we already have the child shape
868                         btCompoundShape* compoundShape = new btCompoundShape();
869                         compoundShape->addChildShape(shapeInfo->m_childTrans,bm);
870                         // now replace the shape
871                         bm = compoundShape;
872                         shapeInfo = compoundShapeInfo;
873                 }
874
875
876
877
878
879
880 #ifdef TEST_SIMD_HULL
881         if (bm->IsPolyhedral())
882         {
883                 PolyhedralConvexShape* polyhedron = static_cast<PolyhedralConvexShape*>(bm);
884                 if (!polyhedron->m_optionalHull)
885                 {
886                         //first convert vertices in 'Point3' format
887                         int numPoints = polyhedron->GetNumVertices();
888                         Point3* points = new Point3[numPoints+1];
889                         //first 4 points should not be co-planar, so add central point to satisfy MakeHull
890                         points[0] = Point3(0.f,0.f,0.f);
891                         
892                         btVector3 vertex;
893                         for (int p=0;p<numPoints;p++)
894                         {
895                                 polyhedron->GetVertex(p,vertex);
896                                 points[p+1] = Point3(vertex.getX(),vertex.getY(),vertex.getZ());
897                         }
898
899                         Hull* hull = Hull::MakeHull(numPoints+1,points);
900                         polyhedron->m_optionalHull = hull;
901                 }
902
903         }
904 #endif //TEST_SIMD_HULL
905
906
907         ci.m_collisionShape = bm;
908         ci.m_shapeInfo = shapeInfo;
909         ci.m_friction = smmaterial->m_friction;//tweak the friction a bit, so the default 0.5 works nice
910         ci.m_restitution = smmaterial->m_restitution;
911         ci.m_physicsEnv = env;
912         // drag / damping is inverted
913         ci.m_linearDamping = 1.f - shapeprops->m_lin_drag;
914         ci.m_angularDamping = 1.f - shapeprops->m_ang_drag;
915         //need a bit of damping, else system doesn't behave well
916         ci.m_inertiaFactor = shapeprops->m_inertia/0.4f;//defaults to 0.4, don't want to change behaviour
917         ci.m_collisionFilterGroup = (isbulletdyna) ? short(CcdConstructionInfo::DefaultFilter) : short(CcdConstructionInfo::StaticFilter);
918         ci.m_collisionFilterMask = (isbulletdyna) ? short(CcdConstructionInfo::AllFilter) : short(CcdConstructionInfo::AllFilter ^ CcdConstructionInfo::StaticFilter);
919         ci.m_bRigid = objprop->m_dyna && objprop->m_angular_rigidbody;
920         ci.m_bSoft = objprop->m_softbody;
921         MT_Vector3 scaling = gameobj->NodeGetWorldScaling();
922         ci.m_scaling.setValue(scaling[0], scaling[1], scaling[2]);
923         KX_BulletPhysicsController* physicscontroller = new KX_BulletPhysicsController(ci,isbulletdyna);
924         // shapeInfo is reference counted, decrement now as we don't use it anymore
925         if (shapeInfo)
926                 shapeInfo->Release();
927
928         if (objprop->m_in_active_layer)
929         {
930                 env->addCcdPhysicsController( physicscontroller);
931         }
932
933         
934
935         gameobj->SetPhysicsController(physicscontroller,isbulletdyna);
936         physicscontroller->setNewClientInfo(gameobj->getClientInfo());          
937         {
938                 btRigidBody* rbody = physicscontroller->GetRigidBody();
939
940                 if (rbody && objprop->m_disableSleeping)
941                         rbody->setActivationState(DISABLE_DEACTIVATION);
942         }
943         
944         //Now done directly in ci.m_collisionFlags so that it propagates to replica
945         //if (objprop->m_ghost)
946         //{
947         //      rbody->setCollisionFlags(rbody->getCollisionFlags() | btCollisionObject::CF_NO_CONTACT_RESPONSE);
948         //}
949         
950         if (objprop->m_dyna && !objprop->m_angular_rigidbody)
951         {
952                 /*
953                 //setting the inertia could achieve similar results to constraint the up
954                 //but it is prone to instability, so use special 'Angular' constraint
955                 btVector3 inertia = physicscontroller->GetRigidBody()->getInvInertiaDiagLocal();
956                 inertia.setX(0.f);
957                 inertia.setZ(0.f);
958
959                 physicscontroller->GetRigidBody()->setInvInertiaDiagLocal(inertia);
960                 physicscontroller->GetRigidBody()->updateInertiaTensor();
961                 */
962
963                 //env->createConstraint(physicscontroller,0,PHY_ANGULAR_CONSTRAINT,0,0,0,0,0,1);
964         
965                 //Now done directly in ci.m_bRigid so that it propagates to replica
966                 //physicscontroller->GetRigidBody()->setAngularFactor(0.f);
967                 ;
968         }
969
970         bool isActor = objprop->m_isactor;
971         gameobj->getClientInfo()->m_type = (isActor ? KX_ClientObjectInfo::ACTOR : KX_ClientObjectInfo::STATIC);
972         // store materialname in auxinfo, needed for touchsensors
973         if (meshobj)
974         {
975                 const STR_String& matname=meshobj->GetMaterialName(0);
976                 gameobj->getClientInfo()->m_auxilary_info = (matname.Length() ? (void*)(matname.ReadPtr()+2) : NULL);
977         } else
978         {
979                 gameobj->getClientInfo()->m_auxilary_info = 0;
980         }
981
982
983         gameobj->GetSGNode()->AddSGController(physicscontroller);
984
985         STR_String materialname;
986         if (meshobj)
987                 materialname = meshobj->GetMaterialName(0);
988
989         physicscontroller->SetObject(gameobj->GetSGNode());
990
991 }
992
993
994 void    KX_ClearBulletSharedShapes()
995 {
996 }
997
998 #endif
999