- enabled compound collision objects, requires 'clear parent inverse'
[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 #include "MT_assert.h"
37
38 // defines USE_ODE to choose physics engine
39 #include "KX_ConvertPhysicsObject.h"
40 #include "KX_GameObject.h"
41 #include "RAS_MeshObject.h"
42 #include "KX_Scene.h"
43 #include "SYS_System.h"
44
45 #include "PHY_Pro.h" //todo cleanup
46 #include "KX_ClientObjectInfo.h"
47
48 #include "GEN_Map.h"
49 #include "GEN_HashedPtr.h"
50
51 #include "KX_PhysicsEngineEnums.h"
52 #include "PHY_Pro.h"
53
54 #include "KX_MotionState.h" // bridge between motionstate and scenegraph node
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 struct KX_PhysicsInstance
80 {
81         DT_VertexBaseHandle     m_vertexbase;
82         int                     m_vtxarray;
83         RAS_IPolyMaterial*      m_material;
84         
85         KX_PhysicsInstance(DT_VertexBaseHandle vertex_base, int vtxarray, RAS_IPolyMaterial* mat)
86                 : m_vertexbase(vertex_base),
87                   m_vtxarray(vtxarray),
88                   m_material(mat)
89         {
90         }
91         
92         ~KX_PhysicsInstance()
93         {
94                 DT_DeleteVertexBase(m_vertexbase);
95         }
96 };
97
98 static GEN_Map<GEN_HashedPtr,DT_ShapeHandle> map_gamemesh_to_sumoshape;
99 static GEN_Map<GEN_HashedPtr, KX_PhysicsInstance*> map_gamemesh_to_instance;
100
101 // forward declarations
102 static void     BL_RegisterSumoObject(KX_GameObject* gameobj,class SM_Scene* sumoScene,class SM_Object* sumoObj,const STR_String& matname,bool isDynamic,bool isActor);
103 static DT_ShapeHandle CreateShapeFromMesh(RAS_MeshObject* meshobj, bool polytope);
104
105 void    KX_ConvertSumoObject(   KX_GameObject* gameobj,
106                                 RAS_MeshObject* meshobj,
107                                 KX_Scene* kxscene,
108                                 PHY_ShapeProps* kxshapeprops,
109                                 PHY_MaterialProps*      kxmaterial,
110                                 struct  KX_ObjectProperties*    objprop)
111
112
113 {
114         SM_ShapeProps* smprop = new SM_ShapeProps;
115
116         smprop->m_ang_drag = kxshapeprops->m_ang_drag;
117         smprop->m_do_anisotropic = kxshapeprops->m_do_anisotropic;
118         smprop->m_do_fh = kxshapeprops->m_do_fh;
119         smprop->m_do_rot_fh = kxshapeprops->m_do_rot_fh ;
120         smprop->m_friction_scaling[0]  = kxshapeprops->m_friction_scaling[0];
121         smprop->m_friction_scaling[1]  = kxshapeprops->m_friction_scaling[1];
122         smprop->m_friction_scaling[2]  = kxshapeprops->m_friction_scaling[2];
123         smprop->m_inertia = MT_Vector3(1., 1., 1.) * kxshapeprops->m_inertia;
124         smprop->m_lin_drag = kxshapeprops->m_lin_drag;
125         smprop->m_mass = kxshapeprops->m_mass;
126         smprop->m_radius = objprop->m_radius;
127
128
129         SM_MaterialProps* smmaterial = new SM_MaterialProps;
130
131         smmaterial->m_fh_damping = kxmaterial->m_fh_damping;
132         smmaterial->m_fh_distance = kxmaterial->m_fh_distance;
133         smmaterial->m_fh_normal = kxmaterial->m_fh_normal;
134         smmaterial->m_fh_spring = kxmaterial->m_fh_spring;
135         smmaterial->m_friction = kxmaterial->m_friction;
136         smmaterial->m_restitution = kxmaterial->m_restitution;
137
138         SumoPhysicsEnvironment* sumoEnv =
139                 (SumoPhysicsEnvironment*)kxscene->GetPhysicsEnvironment();
140
141         SM_Scene*       sceneptr = sumoEnv->GetSumoScene();
142
143         SM_Object*      sumoObj=NULL;
144
145         if (objprop->m_dyna && objprop->m_isactor)
146         {
147                 DT_ShapeHandle shape = NULL;
148                 bool polytope = false;
149                 switch (objprop->m_boundclass)
150                 {
151                         case KX_BOUNDBOX:
152                                 shape = DT_NewBox(objprop->m_boundobject.box.m_extends[0], 
153                                                 objprop->m_boundobject.box.m_extends[1], 
154                                                 objprop->m_boundobject.box.m_extends[2]);
155                                 smprop->m_inertia.scale(objprop->m_boundobject.box.m_extends[0]*objprop->m_boundobject.box.m_extends[0],
156                                         objprop->m_boundobject.box.m_extends[1]*objprop->m_boundobject.box.m_extends[1],
157                                         objprop->m_boundobject.box.m_extends[2]*objprop->m_boundobject.box.m_extends[2]);
158                                 smprop->m_inertia *= smprop->m_mass/MT_Vector3(objprop->m_boundobject.box.m_extends).length();
159                                 break;
160                         case KX_BOUNDCYLINDER:
161                                 shape = DT_NewCylinder(smprop->m_radius, objprop->m_boundobject.c.m_height);
162                                 smprop->m_inertia.scale(smprop->m_mass*smprop->m_radius*smprop->m_radius,
163                                         smprop->m_mass*smprop->m_radius*smprop->m_radius,
164                                         smprop->m_mass*objprop->m_boundobject.c.m_height*objprop->m_boundobject.c.m_height);
165                                 break;
166                         case KX_BOUNDCONE:
167                                 shape = DT_NewCone(objprop->m_radius, objprop->m_boundobject.c.m_height);
168                                 smprop->m_inertia.scale(smprop->m_mass*smprop->m_radius*smprop->m_radius,
169                                         smprop->m_mass*smprop->m_radius*smprop->m_radius,
170                                         smprop->m_mass*objprop->m_boundobject.c.m_height*objprop->m_boundobject.c.m_height);
171                                 break;
172                         /* Dynamic mesh objects.  WARNING! slow. */
173                         case KX_BOUNDPOLYTOPE:
174                                 polytope = true;
175                                 // fall through
176                         case KX_BOUNDMESH:
177                                 if (meshobj && meshobj->NumPolygons() > 0)
178                                 {
179                                         if ((shape = CreateShapeFromMesh(meshobj, polytope)))
180                                         {
181                                                 // TODO: calculate proper inertia
182                                                 smprop->m_inertia *= smprop->m_mass*smprop->m_radius*smprop->m_radius;
183                                                 break;
184                                         }
185                                 }
186                                 /* If CreateShapeFromMesh fails, fall through and use sphere */
187                         default:
188                         case KX_BOUNDSPHERE:
189                                 shape = DT_NewSphere(objprop->m_radius);
190                                 smprop->m_inertia *= smprop->m_mass*smprop->m_radius*smprop->m_radius;
191                                 break;
192                                 
193                 }
194                 
195                 sumoObj = new SM_Object(shape, !objprop->m_ghost?smmaterial:NULL,smprop,NULL);
196                 
197                 sumoObj->setRigidBody(objprop->m_angular_rigidbody?true:false);
198                 
199                 BL_RegisterSumoObject(gameobj,sceneptr,sumoObj,"",true, true);
200                 
201         } 
202         else {
203                 // non physics object
204                 if (meshobj)
205                 {
206                         int numpolys = meshobj->NumPolygons();
207                         {
208
209                                 DT_ShapeHandle complexshape=0;
210                                 bool polytope = false;
211
212                                 switch (objprop->m_boundclass)
213                                 {
214                                         case KX_BOUNDBOX:
215                                                 complexshape = DT_NewBox(objprop->m_boundobject.box.m_extends[0], objprop->m_boundobject.box.m_extends[1], objprop->m_boundobject.box.m_extends[2]);
216                                                 break;
217                                         case KX_BOUNDSPHERE:
218                                                 complexshape = DT_NewSphere(objprop->m_boundobject.c.m_radius);
219                                                 break;
220                                         case KX_BOUNDCYLINDER:
221                                                 complexshape = DT_NewCylinder(objprop->m_boundobject.c.m_radius, objprop->m_boundobject.c.m_height);
222                                                 break;
223                                         case KX_BOUNDCONE:
224                                                 complexshape = DT_NewCone(objprop->m_boundobject.c.m_radius, objprop->m_boundobject.c.m_height);
225                                                 break;
226                                         case KX_BOUNDPOLYTOPE:
227                                                 polytope = true;
228                                                 // fall through
229                                         default:
230                                         case KX_BOUNDMESH:
231                                                 if (numpolys>0)
232                                                 {
233                                                         complexshape = CreateShapeFromMesh(meshobj, polytope);
234                                                         //std::cout << "Convert Physics Mesh: " << meshobj->GetName() << std::endl;
235 /*                                                      if (!complexshape) 
236                                                         {
237                                                                 // Something has to be done here - if the object has no polygons, it will not be able to have
238                                                                 //   sensors attached to it. 
239                                                                 DT_Vector3 pt = {0., 0., 0.};
240                                                                 complexshape = DT_NewSphere(1.0);
241                                                                 objprop->m_ghost = evilObject = true;
242                                                         } */
243                                                 }
244                                                 break;
245                                 }
246                                 
247                                 if (complexshape)
248                                 {
249                                         SM_Object *dynamicParent = NULL;
250
251                                         if (objprop->m_dynamic_parent)
252                                         {
253                                                 // problem is how to find the dynamic parent
254                                                 // in the scenegraph
255                                                 KX_SumoPhysicsController* sumoctrl = 
256                                                 (KX_SumoPhysicsController*)
257                                                         objprop->m_dynamic_parent->GetPhysicsController();
258
259                                                 if (sumoctrl)
260                                                 {
261                                                         dynamicParent = sumoctrl->GetSumoObject();
262                                                 }
263
264                                                 MT_assert(dynamicParent);
265                                         }
266                                 
267                                         
268                                         sumoObj = new SM_Object(complexshape,!objprop->m_ghost?smmaterial:NULL,NULL, dynamicParent);    
269                                         const STR_String& matname=meshobj->GetMaterialName(0);
270
271                                         
272                                         BL_RegisterSumoObject(gameobj,sceneptr,
273                                                 sumoObj,
274                                                 matname,
275                                                 objprop->m_dyna,
276                                                 objprop->m_isactor);
277                                 }
278                         }
279                 }
280         }
281
282         // physics object get updated here !
283
284         
285         // lazy evaluation because we might not support scaling !gameobj->UpdateTransform();
286
287         if (objprop->m_in_active_layer && sumoObj)
288         {
289                 sceneptr->add(*sumoObj);
290         }
291
292 }
293
294
295
296 static void     BL_RegisterSumoObject(
297         KX_GameObject* gameobj,
298         class SM_Scene* sumoScene,
299         class SM_Object* sumoObj,
300         const STR_String& matname,
301         bool isDynamic,
302         bool isActor) 
303 {
304                 PHY_IMotionState* motionstate = new KX_MotionState(gameobj->GetSGNode());
305
306                 // need easy access, not via 'node' etc.
307                 KX_SumoPhysicsController* physicscontroller = new KX_SumoPhysicsController(sumoScene,sumoObj,motionstate,isDynamic);
308                 gameobj->SetPhysicsController(physicscontroller,isDynamic);
309
310                 
311                 if (!gameobj->getClientInfo())
312                         std::cout << "BL_RegisterSumoObject: WARNING: Object " << gameobj->GetName() << " has no client info" << std::endl;
313                 physicscontroller->setNewClientInfo(gameobj->getClientInfo());
314                 
315
316                 gameobj->GetSGNode()->AddSGController(physicscontroller);
317
318                 gameobj->getClientInfo()->m_type = (isActor ? KX_ClientObjectInfo::ACTOR : KX_ClientObjectInfo::STATIC);
319
320                 // store materialname in auxinfo, needed for touchsensors
321                 gameobj->getClientInfo()->m_auxilary_info = (matname.Length() ? (void*)(matname.ReadPtr()+2) : NULL);
322
323                 physicscontroller->SetObject(gameobj->GetSGNode());
324 }
325
326 static DT_ShapeHandle InstancePhysicsComplex(RAS_MeshObject* meshobj, int vtxarray, RAS_IPolyMaterial *mat)
327 {
328         // instance a mesh from a single vertex array & material
329         const RAS_TexVert *vertex_array = &((*meshobj->GetVertexCache(mat)[vtxarray])[0]);
330         //const KX_IndexArray &index_array = *meshobj->GetIndexCache(mat)[vtxarray];
331         DT_VertexBaseHandle vertex_base = DT_NewVertexBase(vertex_array[0].getLocalXYZ(), sizeof(RAS_TexVert));
332         
333         DT_ShapeHandle shape = DT_NewComplexShape(vertex_base);
334         
335         std::vector<DT_Index> indices;
336         for (int p = 0; p < meshobj->NumPolygons(); p++)
337         {
338                 RAS_Polygon* poly = meshobj->GetPolygon(p);
339         
340                 // only add polygons that have the collisionflag set
341                 if (poly->IsCollider())
342                 {
343                         DT_VertexIndices(3, poly->GetVertexIndexBase().m_indexarray);
344                         
345                         // tesselate
346                         if (poly->VertexCount() == 4)
347                         {
348                                 DT_Begin();
349                                   DT_VertexIndex(poly->GetVertexIndexBase().m_indexarray[0]);
350                                   DT_VertexIndex(poly->GetVertexIndexBase().m_indexarray[2]);
351                                   DT_VertexIndex(poly->GetVertexIndexBase().m_indexarray[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, vtxarray, mat));
361         return shape;
362 }
363
364 static DT_ShapeHandle InstancePhysicsPolytope(RAS_MeshObject* meshobj, int vtxarray, RAS_IPolyMaterial *mat)
365 {
366         // instance a mesh from a single vertex array & material
367         const RAS_TexVert *vertex_array = &((*meshobj->GetVertexCache(mat)[vtxarray])[0]);
368         //const KX_IndexArray &index_array = *meshobj->GetIndexCache(mat)[vtxarray];
369         DT_VertexBaseHandle vertex_base = DT_NewVertexBase(vertex_array[0].getLocalXYZ(), sizeof(RAS_TexVert));
370         
371         std::vector<DT_Index> indices;
372         for (int p = 0; p < meshobj->NumPolygons(); p++)
373         {
374                 RAS_Polygon* poly = meshobj->GetPolygon(p);
375         
376                 // only add polygons that have the collisionflag set
377                 if (poly->IsCollider())
378                 {
379                         indices.push_back(poly->GetVertexIndexBase().m_indexarray[0]);
380                         indices.push_back(poly->GetVertexIndexBase().m_indexarray[1]);
381                         indices.push_back(poly->GetVertexIndexBase().m_indexarray[2]);
382                         
383                         if (poly->VertexCount() == 4)
384                                 indices.push_back(poly->GetVertexIndexBase().m_indexarray[3]);
385                 }
386         }
387
388         DT_ShapeHandle shape = DT_NewPolytope(vertex_base);
389         DT_VertexIndices(indices.size(), &indices[0]);
390         DT_EndPolytope();
391         
392         map_gamemesh_to_instance.insert(GEN_HashedPtr(meshobj), new KX_PhysicsInstance(vertex_base, vtxarray, mat));
393         return shape;
394 }
395
396 // This will have to be a method in a class somewhere...
397 // Update SOLID with a changed physics mesh.
398 // not used... yet.
399 bool KX_ReInstanceShapeFromMesh(RAS_MeshObject* meshobj)
400 {
401         KX_PhysicsInstance *instance = *map_gamemesh_to_instance[GEN_HashedPtr(meshobj)];
402         if (instance)
403         {
404                 const RAS_TexVert *vertex_array = &((*meshobj->GetVertexCache(instance->m_material)[instance->m_vtxarray])[0]);
405                 DT_ChangeVertexBase(instance->m_vertexbase, vertex_array[0].getLocalXYZ());
406                 return true;
407         }
408         return false;
409 }
410
411 static DT_ShapeHandle CreateShapeFromMesh(RAS_MeshObject* meshobj, bool polytope)
412 {
413
414         DT_ShapeHandle *shapeptr = map_gamemesh_to_sumoshape[GEN_HashedPtr(meshobj)];
415         // Mesh has already been converted: reuse
416         if (shapeptr)
417         {
418                 return *shapeptr;
419         }
420         
421         // Mesh has no polygons!
422         int numpolys = meshobj->NumPolygons();
423         if (!numpolys)
424         {
425                 return NULL;
426         }
427         
428         // Count the number of collision polygons and check they all come from the same 
429         // vertex array
430         int numvalidpolys = 0;
431         int vtxarray = -1;
432         RAS_IPolyMaterial *poly_material = NULL;
433         bool reinstance = true;
434
435         for (int p=0; p<numpolys; p++)
436         {
437                 RAS_Polygon* poly = meshobj->GetPolygon(p);
438         
439                 // only add polygons that have the collisionflag set
440                 if (poly->IsCollider())
441                 {
442                         // check polygon is from the same vertex array
443                         if (poly->GetVertexIndexBase().m_vtxarray != vtxarray)
444                         {
445                                 if (vtxarray < 0)
446                                         vtxarray = poly->GetVertexIndexBase().m_vtxarray;
447                                 else
448                                 {
449                                         reinstance = false;
450                                         vtxarray = -1;
451                                 }
452                         }
453                         
454                         // check poly is from the same material
455                         if (poly->GetMaterial()->GetPolyMaterial() != poly_material)
456                         {
457                                 if (poly_material)
458                                 {
459                                         reinstance = false;
460                                         poly_material = NULL;
461                                 }
462                                 else
463                                         poly_material = poly->GetMaterial()->GetPolyMaterial();
464                         }
465                         
466                         // count the number of collision polys
467                         numvalidpolys++;
468                         
469                         // We have one collision poly, and we can't reinstance, so we
470                         // might as well break here.
471                         if (!reinstance)
472                                 break;
473                 }
474         }
475         
476         // No collision polygons
477         if (numvalidpolys < 1)
478                 return NULL;
479         
480         DT_ShapeHandle shape;
481         if (reinstance)
482         {
483                 if (polytope)
484                         shape = InstancePhysicsPolytope(meshobj, vtxarray, poly_material);
485                 else
486                         shape = InstancePhysicsComplex(meshobj, vtxarray, poly_material);
487         }
488         else
489         {
490                 if (polytope)
491                 {
492                         std::cout << "CreateShapeFromMesh: " << meshobj->GetName() << " is not suitable for polytope." << std::endl;
493                         if (!poly_material)
494                                 std::cout << "                     Check mesh materials." << std::endl;
495                         if (vtxarray < 0)
496                                 std::cout << "                     Check number of vertices." << std::endl;
497                 }
498                 
499                 shape = DT_NewComplexShape(NULL);
500                         
501                 numvalidpolys = 0;
502         
503                 for (int p2=0; p2<numpolys; p2++)
504                 {
505                         RAS_Polygon* poly = meshobj->GetPolygon(p2);
506                 
507                         // only add polygons that have the collisionflag set
508                         if (poly->IsCollider())
509                         {   /* We have to tesselate here because SOLID can only raycast triangles */
510                            DT_Begin();
511                                 /* V1 */
512                                 DT_Vertex(meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray, 
513                                         poly->GetVertexIndexBase().m_indexarray[2],
514                                         poly->GetMaterial()->GetPolyMaterial())->getLocalXYZ());
515                                 /* V2 */
516                                 DT_Vertex(meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray, 
517                                         poly->GetVertexIndexBase().m_indexarray[1],
518                                         poly->GetMaterial()->GetPolyMaterial())->getLocalXYZ());
519                                 /* V3 */
520                                 DT_Vertex(meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray, 
521                                         poly->GetVertexIndexBase().m_indexarray[0],
522                                         poly->GetMaterial()->GetPolyMaterial())->getLocalXYZ());
523                                 
524                                 numvalidpolys++;
525                            DT_End();
526                                 
527                                 if (poly->VertexCount() == 4)
528                                 {
529                                    DT_Begin();
530                                         /* V1 */
531                                         DT_Vertex(meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray, 
532                                                 poly->GetVertexIndexBase().m_indexarray[3],
533                                                 poly->GetMaterial()->GetPolyMaterial())->getLocalXYZ());
534                                         /* V3 */
535                                         DT_Vertex(meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray, 
536                                                 poly->GetVertexIndexBase().m_indexarray[2],
537                                                 poly->GetMaterial()->GetPolyMaterial())->getLocalXYZ());
538                                         /* V4 */
539                                         DT_Vertex(meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray, 
540                                                 poly->GetVertexIndexBase().m_indexarray[0],
541                                                 poly->GetMaterial()->GetPolyMaterial())->getLocalXYZ());
542                                 
543                                         numvalidpolys++;
544                                    DT_End();
545                                 }
546                 
547                         }
548                 }
549                 
550                 DT_EndComplexShape();
551         }
552
553         if (numvalidpolys > 0)
554         {
555                 map_gamemesh_to_sumoshape.insert(GEN_HashedPtr(meshobj),shape);
556                 return shape;
557         }
558
559         delete shape;
560         return NULL;
561 }
562
563 void    KX_ClearSumoSharedShapes()
564 {
565         int numshapes = map_gamemesh_to_sumoshape.size();
566         int i;
567         for (i=0;i<numshapes ;i++)
568         {
569                 DT_ShapeHandle shape = *map_gamemesh_to_sumoshape.at(i);
570                 DT_DeleteShape(shape);
571         }
572         
573         map_gamemesh_to_sumoshape.clear();
574         
575         for (i=0; i < map_gamemesh_to_instance.size(); i++)
576                 delete *map_gamemesh_to_instance.at(i);
577         
578         map_gamemesh_to_instance.clear();
579 }
580
581
582
583
584
585 #endif //USE_SUMO_SOLID
586
587
588 #ifdef USE_ODE
589
590 void    KX_ConvertODEEngineObject(KX_GameObject* gameobj,
591                                                          RAS_MeshObject* meshobj,
592                                                          KX_Scene* kxscene,
593                                                         struct  PHY_ShapeProps* shapeprops,
594                                                         struct  PHY_MaterialProps*      smmaterial,
595                                                         struct  KX_ObjectProperties*    objprop)
596 {
597         
598         // not yet, future extension :)
599         bool dyna=objprop->m_dyna;
600         bool fullRigidBody= ( objprop->m_dyna && objprop->m_angular_rigidbody) != 0;
601         bool phantom = objprop->m_ghost;
602         class PHY_IMotionState* motionstate = new KX_MotionState(gameobj->GetSGNode());
603
604         class ODEPhysicsEnvironment* odeEnv =
605                 (ODEPhysicsEnvironment*)kxscene->GetPhysicsEnvironment();
606
607         dxSpace* space = odeEnv->GetOdeSpace();
608         dxWorld* world = odeEnv->GetOdeWorld();
609
610         bool isSphere = false;
611
612         switch (objprop->m_boundclass)
613         {
614         case KX_BOUNDBOX:
615                 {
616
617                                 KX_OdePhysicsController* physicscontroller = 
618                                         new KX_OdePhysicsController(
619                                         dyna,
620                                         fullRigidBody,
621                                         phantom,
622                                         motionstate,
623                                         space,
624                                         world,
625                                         shapeprops->m_mass,
626                                         smmaterial->m_friction,
627                                         smmaterial->m_restitution,
628                                         isSphere,
629                                         objprop->m_boundobject.box.m_center,
630                                         objprop->m_boundobject.box.m_extends,
631                                         objprop->m_boundobject.c.m_radius
632                                         );
633
634                                 gameobj->SetPhysicsController(physicscontroller);
635                                 physicscontroller->setNewClientInfo(gameobj->getClientInfo());                                          
636                                 gameobj->GetSGNode()->AddSGController(physicscontroller);
637
638                                 bool isActor = objprop->m_isactor;
639                                 STR_String materialname;
640                                 if (meshobj)
641                                         materialname = meshobj->GetMaterialName(0);
642
643                                 const char* matname = materialname.ReadPtr();
644
645
646                                 physicscontroller->SetObject(gameobj->GetSGNode());
647
648                                 break;
649                         }
650         default:
651                 {
652                 }
653         };
654
655 }
656
657
658 #endif // USE_ODE
659
660
661 #ifdef USE_BULLET
662
663 #include "CcdPhysicsEnvironment.h"
664 #include "CcdPhysicsController.h"
665 #include "BulletCollision/BroadphaseCollision/btBroadphaseInterface.h"
666
667 #include "KX_BulletPhysicsController.h"
668 #include "btBulletDynamicsCommon.h"
669
670                                                         #ifdef WIN32
671 #if _MSC_VER >= 1310
672 //only use SIMD Hull code under Win32
673 //#define TEST_HULL 1
674 #ifdef TEST_HULL
675 #define USE_HULL 1
676 //#define TEST_SIMD_HULL 1
677
678 #include "NarrowPhaseCollision/Hull.h"
679 #endif //#ifdef TEST_HULL
680
681 #endif //_MSC_VER 
682 #endif //WIN32
683
684
685 static GEN_Map<GEN_HashedPtr,btCollisionShape*> map_gamemesh_to_bulletshape;
686
687 // forward declarations
688 static btCollisionShape* CreateBulletShapeFromMesh(RAS_MeshObject* meshobj, bool polytope)
689 {
690         if (!meshobj)
691                 return 0;
692
693         btCollisionShape* collisionMeshShape = 0;
694         btConvexHullShape* convexHullShape = 0;
695         btTriangleMeshShape* concaveShape = 0;
696
697         btTriangleMesh* collisionMeshData = 0;
698
699         //see if there is any polygons, if not, bail out.
700
701         int numPoints = 0;
702         btVector3* points = 0;
703
704         btCollisionShape** shapeptr = map_gamemesh_to_bulletshape[GEN_HashedPtr(meshobj)];
705
706         // Mesh has already been converted: reuse
707         if (shapeptr)
708         {
709                 //return *shapeptr;
710         }
711
712         // Mesh has no polygons!
713         int numpolys = meshobj->NumPolygons();
714         if (!numpolys)
715         {
716                 return NULL;
717         }
718
719         // Count the number of collision polygons and check they all come from the same 
720         // vertex array
721         int numvalidpolys = 0;
722         int vtxarray = -1;
723         RAS_IPolyMaterial *poly_material = NULL;
724         bool reinstance = true;
725
726         for (int p=0; p<numpolys; p++)
727         {
728                 RAS_Polygon* poly = meshobj->GetPolygon(p);
729
730                 // only add polygons that have the collisionflag set
731                 if (poly->IsCollider())
732                 {
733                         // check polygon is from the same vertex array
734                         if (poly->GetVertexIndexBase().m_vtxarray != vtxarray)
735                         {
736                                 if (vtxarray < 0)
737                                         vtxarray = poly->GetVertexIndexBase().m_vtxarray;
738                                 else
739                                 {
740                                         reinstance = false;
741                                         vtxarray = -1;
742                                 }
743                         }
744
745                         // check poly is from the same material
746                         if (poly->GetMaterial()->GetPolyMaterial() != poly_material)
747                         {
748                                 if (poly_material)
749                                 {
750                                         reinstance = false;
751                                         poly_material = NULL;
752                                 }
753                                 else
754                                         poly_material = poly->GetMaterial()->GetPolyMaterial();
755                         }
756
757                         // count the number of collision polys
758                         numvalidpolys++;
759
760                         // We have one collision poly, and we can't reinstance, so we
761                         // might as well break here.
762                         if (!reinstance)
763                                 break;
764                 }
765         }
766
767         // No collision polygons
768         if (numvalidpolys < 1)
769                 return NULL;
770
771
772         if (polytope)
773         {
774                 convexHullShape = new btConvexHullShape(&points[0].getX(),numPoints);
775                 collisionMeshShape = convexHullShape;
776         } else
777         {
778                 collisionMeshData = new btTriangleMesh();
779 //              concaveShape = new btTriangleMeshShape(collisionMeshData);
780                 //collisionMeshShape = concaveShape;
781
782         }
783
784
785         numvalidpolys = 0;
786
787         for (int p2=0; p2<numpolys; p2++)
788         {
789                 RAS_Polygon* poly = meshobj->GetPolygon(p2);
790
791                 // only add polygons that have the collisionflag set
792                 if (poly->IsCollider())
793                 {   
794                         //Bullet can raycast any shape, so
795                         if (polytope)
796                         {
797                                 for (int i=0;i<poly->VertexCount();i++)
798                                 {
799                                         const float* vtx = meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray, 
800                                                 poly->GetVertexIndexBase().m_indexarray[i],
801                                                 poly->GetMaterial()->GetPolyMaterial())->getLocalXYZ();
802                                         btPoint3 point(vtx[0],vtx[1],vtx[2]);
803                                         convexHullShape->addPoint(point);
804                                 }
805                                 if (poly->VertexCount())
806                                         numvalidpolys++;
807
808                         } else
809                         {
810                                 {
811                                         const float* vtx = meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray, 
812                                                 poly->GetVertexIndexBase().m_indexarray[2],
813                                                 poly->GetMaterial()->GetPolyMaterial())->getLocalXYZ();
814                                         btPoint3 vertex0(vtx[0],vtx[1],vtx[2]);
815                                         vtx = meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray, 
816                                                 poly->GetVertexIndexBase().m_indexarray[1],
817                                                 poly->GetMaterial()->GetPolyMaterial())->getLocalXYZ();
818                                         btPoint3 vertex1(vtx[0],vtx[1],vtx[2]);
819                                         vtx = meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray, 
820                                                 poly->GetVertexIndexBase().m_indexarray[0],
821                                                 poly->GetMaterial()->GetPolyMaterial())->getLocalXYZ();
822                                         btPoint3 vertex2(vtx[0],vtx[1],vtx[2]);
823                                         collisionMeshData->addTriangle(vertex0,vertex1,vertex2);
824                                         numvalidpolys++;
825                                 }
826                                 if (poly->VertexCount() == 4)
827                                 {
828                                         const float* vtx = meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray, 
829                                                 poly->GetVertexIndexBase().m_indexarray[3],
830                                                 poly->GetMaterial()->GetPolyMaterial())->getLocalXYZ();
831                                         btPoint3 vertex0(vtx[0],vtx[1],vtx[2]);
832                                         vtx = meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray, 
833                                                 poly->GetVertexIndexBase().m_indexarray[2],
834                                                 poly->GetMaterial()->GetPolyMaterial())->getLocalXYZ();
835                                         btPoint3 vertex1(vtx[0],vtx[1],vtx[2]);
836                                         vtx = meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray, 
837                                                 poly->GetVertexIndexBase().m_indexarray[0],
838                                                 poly->GetMaterial()->GetPolyMaterial())->getLocalXYZ();
839                                         btPoint3 vertex2(vtx[0],vtx[1],vtx[2]);
840                                         collisionMeshData->addTriangle(vertex0,vertex1,vertex2);
841                                         numvalidpolys++;
842                                 }
843
844                         }               
845                 }
846         }
847
848
849
850         if (numvalidpolys > 0)
851         {
852                 
853                 //map_gamemesh_to_bulletshape.insert(GEN_HashedPtr(meshobj),collisionMeshShape);
854                 if (!polytope)
855                 {
856                         concaveShape = new btBvhTriangleMeshShape( collisionMeshData );
857                         //concaveShape = new btTriangleMeshShape( collisionMeshData );
858
859                         concaveShape->recalcLocalAabb();
860                         collisionMeshShape = concaveShape;
861
862                 } 
863                 
864                 
865
866                 return collisionMeshShape;
867         }
868
869         delete collisionMeshShape;
870         return NULL;
871
872 }
873
874
875
876 void    KX_ConvertBulletObject( class   KX_GameObject* gameobj,
877         class   RAS_MeshObject* meshobj,
878         class   KX_Scene* kxscene,
879         struct  PHY_ShapeProps* shapeprops,
880         struct  PHY_MaterialProps*      smmaterial,
881         struct  KX_ObjectProperties*    objprop)
882 {
883
884         CcdPhysicsEnvironment* env = (CcdPhysicsEnvironment*)kxscene->GetPhysicsEnvironment();
885         assert(env);
886         
887         bool isbulletdyna = objprop->m_dyna;
888         CcdConstructionInfo ci;
889         ci.m_localInertiaTensor =btVector3(0,0,0);
890         ci.m_mass = objprop->m_dyna ? shapeprops->m_mass : 0.f;
891
892         btCollisionShape* bm = 0;
893
894         switch (objprop->m_boundclass)
895         {
896         case KX_BOUNDSPHERE:
897                 {
898                         float radius = objprop->m_radius;
899                         btVector3 inertiaHalfExtents (
900                                 radius,
901                                 radius,
902                                 radius);
903                         
904                         //blender doesn't support multisphere, but for testing:
905
906                         //bm = new MultiSphereShape(inertiaHalfExtents,,&trans.getOrigin(),&radius,1);
907                         bm = new btSphereShape(objprop->m_radius);
908                         bm->calculateLocalInertia(ci.m_mass,ci.m_localInertiaTensor);
909                         break;
910                 };
911         case KX_BOUNDBOX:
912                 {
913                         MT_Vector3 halfExtents (
914                                 objprop->m_boundobject.box.m_extends[0],
915                         objprop->m_boundobject.box.m_extends[1],
916                         objprop->m_boundobject.box.m_extends[2]);
917
918                         halfExtents /= 2.f;
919
920                         //btVector3 he (halfExtents[0]-CONVEX_DISTANCE_MARGIN ,halfExtents[1]-CONVEX_DISTANCE_MARGIN ,halfExtents[2]-CONVEX_DISTANCE_MARGIN );
921                         //he = he.absolute();
922
923                         btVector3 he (halfExtents[0],halfExtents[1],halfExtents[2]);
924                         he = he.absolute();
925
926
927                         bm = new btBoxShape(he);
928                         bm->calculateLocalInertia(ci.m_mass,ci.m_localInertiaTensor);
929                         break;
930                 };
931         case KX_BOUNDCYLINDER:
932                 {
933                         btVector3 halfExtents (
934                                 objprop->m_boundobject.c.m_radius,
935                                 objprop->m_boundobject.c.m_radius,
936                                 objprop->m_boundobject.c.m_height * 0.5f
937                         );
938                         bm = new btCylinderShapeZ(halfExtents);
939                         bm->calculateLocalInertia(ci.m_mass,ci.m_localInertiaTensor);
940
941                         break;
942                 }
943
944                 case KX_BOUNDCONE:
945                 {
946                                 btVector3 halfExtents (objprop->m_boundobject.box.m_extends[0],
947                                 objprop->m_boundobject.box.m_extends[1],
948                                 objprop->m_boundobject.box.m_extends[2]);
949
950
951                                 halfExtents /= 2.f;
952
953                                 bm = new btConeShapeZ(objprop->m_boundobject.c.m_radius,objprop->m_boundobject.c.m_height);
954                                 bm->calculateLocalInertia(ci.m_mass,ci.m_localInertiaTensor);
955
956                         break;
957                 }
958                 case KX_BOUNDPOLYTOPE:
959                         {
960                                 bm = CreateBulletShapeFromMesh(meshobj,true);
961                                 if (bm)
962                                 {
963                                         bm->calculateLocalInertia(ci.m_mass,ci.m_localInertiaTensor);
964                                 }
965                                 break;
966                         }
967                 case KX_BOUNDMESH:
968                         {
969                                 if (!ci.m_mass)
970                                 {                               
971                                         bm = CreateBulletShapeFromMesh(meshobj,false);
972                                         ci.m_localInertiaTensor.setValue(0.f,0.f,0.f);
973                                         //no moving concave meshes, so don't bother calculating inertia
974                                         //bm->calculateLocalInertia(ci.m_mass,ci.m_localInertiaTensor);
975                                 }
976
977                                 break;
978                         }
979
980         default:
981                 //interpret the shape as a concave triangle-mesh
982                 {
983                         if (meshobj)
984                         {
985                         //      assert(0);
986
987                                         /*
988                                 meshobj->ScheduleCollisionPolygons();
989
990                                 KX_DeformableMesh* gfxmesh = new KX_DeformableMesh(meshobj);
991                                 gfxmesh->sendFixedMapping();
992                                 //trianglemesh
993                                 bm = new TriangleMeshInterface(gfxmesh,trans);
994                                 */
995                         }
996                 }
997         }
998
999
1000 //      ci.m_localInertiaTensor.setValue(0.1f,0.1f,0.1f);
1001
1002         if (!bm)
1003                 return;
1004
1005         bm->setMargin(0.06);
1006
1007         if (objprop->m_isCompoundChild)
1008         {
1009                 //find parent, compound shape and add to it
1010                 //take relative transform into account!
1011                 KX_BulletPhysicsController* parentCtrl = (KX_BulletPhysicsController*)objprop->m_dynamic_parent->GetPhysicsController();
1012                 assert(parentCtrl);
1013                 btRigidBody* rigidbody = parentCtrl->GetRigidBody();
1014                 btCollisionShape* colShape = rigidbody->getCollisionShape();
1015                 assert(colShape->isCompound());
1016                 btCompoundShape* compoundShape = (btCompoundShape*)colShape;
1017                 btTransform childTrans;
1018                 childTrans.setIdentity();
1019                 NodeList& children = objprop->m_dynamic_parent->GetSGNode()->GetSGChildren();
1020
1021                 MT_Point3 childPos = gameobj->GetSGNode()->GetLocalPosition();
1022                 MT_Matrix3x3 childRot = gameobj->GetSGNode()->GetLocalOrientation();
1023                 MT_Vector3 childScale = gameobj->GetSGNode()->GetLocalScale();
1024
1025                 bm->setLocalScaling(btVector3(childScale.x(),childScale.y(),childScale.z()));
1026                 childTrans.setOrigin(btVector3(childPos.x(),childPos.y(),childPos.z()));
1027                 float rotval[12];
1028                 childRot.getValue(rotval);
1029                 btMatrix3x3 newRot;
1030                 newRot.setValue(rotval[0],rotval[1],rotval[2],rotval[4],rotval[5],rotval[6],rotval[8],rotval[9],rotval[10]);
1031                 newRot = newRot.transpose();
1032
1033                 childTrans.setBasis(newRot);
1034                         
1035
1036                 compoundShape->addChildShape(childTrans,bm);
1037                 //do some recalc?
1038                 //recalc inertia for rigidbody
1039                 if (!rigidbody->isStaticOrKinematicObject())
1040                 {
1041                         btVector3 localInertia;
1042                         float mass = 1.f/rigidbody->getInvMass();
1043                         compoundShape->calculateLocalInertia(mass,localInertia);
1044                         rigidbody->setMassProps(mass,localInertia);
1045                 }
1046                 return;
1047         }
1048
1049         if (objprop->m_hasCompoundChildren)
1050         {
1051                 //replace shape by compoundShape
1052                 btCompoundShape* compoundShape = new btCompoundShape();
1053                 btTransform identTrans;
1054                 identTrans.setIdentity();
1055                 compoundShape->addChildShape(identTrans,bm);
1056                 bm = compoundShape;
1057         }
1058
1059
1060 #ifdef TEST_SIMD_HULL
1061         if (bm->IsPolyhedral())
1062         {
1063                 PolyhedralConvexShape* polyhedron = static_cast<PolyhedralConvexShape*>(bm);
1064                 if (!polyhedron->m_optionalHull)
1065                 {
1066                         //first convert vertices in 'Point3' format
1067                         int numPoints = polyhedron->GetNumVertices();
1068                         Point3* points = new Point3[numPoints+1];
1069                         //first 4 points should not be co-planar, so add central point to satisfy MakeHull
1070                         points[0] = Point3(0.f,0.f,0.f);
1071                         
1072                         btVector3 vertex;
1073                         for (int p=0;p<numPoints;p++)
1074                         {
1075                                 polyhedron->GetVertex(p,vertex);
1076                                 points[p+1] = Point3(vertex.getX(),vertex.getY(),vertex.getZ());
1077                         }
1078
1079                         Hull* hull = Hull::MakeHull(numPoints+1,points);
1080                         polyhedron->m_optionalHull = hull;
1081                 }
1082
1083         }
1084 #endif //TEST_SIMD_HULL
1085
1086
1087         ci.m_collisionShape = bm;
1088         
1089
1090         class PHY_IMotionState* motionstate = new KX_MotionState(gameobj->GetSGNode());
1091
1092         if (!objprop->m_dyna)
1093         {
1094                 ci.m_collisionFlags |= btCollisionObject::CF_STATIC_OBJECT;
1095         }
1096
1097         
1098         ci.m_MotionState = motionstate;
1099         ci.m_gravity = btVector3(0,0,0);
1100         
1101         ci.m_localInertiaTensor = btVector3(ci.m_mass/3.f,ci.m_mass/3.f,ci.m_mass/3.f);
1102         
1103         btTransform trans;
1104         trans.setIdentity();
1105         
1106
1107         
1108         ci.m_friction = smmaterial->m_friction;//tweak the friction a bit, so the default 0.5 works nice
1109         ci.m_restitution = smmaterial->m_restitution;
1110         ci.m_physicsEnv = env;
1111         // drag / damping is inverted
1112         ci.m_linearDamping = 1.f - shapeprops->m_lin_drag;
1113         ci.m_angularDamping = 1.f - shapeprops->m_ang_drag;
1114         //need a bit of damping, else system doesn't behave well
1115         ci.m_inertiaFactor = shapeprops->m_inertia/0.4f;//defaults to 0.4, don't want to change behaviour
1116         
1117         KX_BulletPhysicsController* physicscontroller = new KX_BulletPhysicsController(ci,isbulletdyna);
1118
1119         if (objprop->m_in_active_layer)
1120         {
1121                 env->addCcdPhysicsController( physicscontroller);
1122         }
1123
1124         
1125
1126         gameobj->SetPhysicsController(physicscontroller,isbulletdyna);
1127         physicscontroller->setNewClientInfo(gameobj->getClientInfo());          
1128         btRigidBody* rbody = physicscontroller->GetRigidBody();
1129
1130         if (objprop->m_disableSleeping)
1131                 rbody->setActivationState(DISABLE_DEACTIVATION);
1132         
1133         if (objprop->m_ghost)
1134         {
1135                 rbody->setCollisionFlags(rbody->getCollisionFlags() | btCollisionObject::CF_NO_CONTACT_RESPONSE);
1136         }
1137         if (objprop->m_dyna && !objprop->m_angular_rigidbody)
1138         {
1139                 /*
1140                 //setting the inertia could achieve similar results to constraint the up
1141                 //but it is prone to instability, so use special 'Angular' constraint
1142                 btVector3 inertia = physicscontroller->GetRigidBody()->getInvInertiaDiagLocal();
1143                 inertia.setX(0.f);
1144                 inertia.setZ(0.f);
1145
1146                 physicscontroller->GetRigidBody()->setInvInertiaDiagLocal(inertia);
1147                 physicscontroller->GetRigidBody()->updateInertiaTensor();
1148                 */
1149
1150                 env->createConstraint(physicscontroller,0,PHY_ANGULAR_CONSTRAINT,0,0,0,0,0,1);
1151                 
1152
1153
1154         }
1155
1156         bool isActor = objprop->m_isactor;
1157         gameobj->getClientInfo()->m_type = (isActor ? KX_ClientObjectInfo::ACTOR : KX_ClientObjectInfo::STATIC);
1158         // store materialname in auxinfo, needed for touchsensors
1159         if (meshobj)
1160         {
1161                 const STR_String& matname=meshobj->GetMaterialName(0);
1162                 gameobj->getClientInfo()->m_auxilary_info = (matname.Length() ? (void*)(matname.ReadPtr()+2) : NULL);
1163         } else
1164         {
1165                 gameobj->getClientInfo()->m_auxilary_info = 0;
1166         }
1167
1168
1169         gameobj->GetSGNode()->AddSGController(physicscontroller);
1170
1171         STR_String materialname;
1172         if (meshobj)
1173                 materialname = meshobj->GetMaterialName(0);
1174
1175         physicscontroller->SetObject(gameobj->GetSGNode());
1176
1177 }
1178         
1179 void    KX_ClearBulletSharedShapes()
1180 {
1181         int numshapes = map_gamemesh_to_bulletshape.size();
1182         int i;
1183         btCollisionShape*shape=0;
1184         for (i=0;i<numshapes ;i++)
1185         {
1186                 shape = *map_gamemesh_to_bulletshape.at(i);
1187                 //delete shape;
1188         }
1189         
1190         map_gamemesh_to_bulletshape.clear();
1191         
1192 }
1193
1194 #endif
1195