c877b699860efdbbbd6e29ef55aa7e7433a0378d
[blender.git] / source / gameengine / Ketsji / KX_ConvertPhysicsObjects.cpp
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version. The Blender
10  * Foundation also sells licenses for use in proprietary software under
11  * the Blender License.  See http://www.blender.org/BL/ for information
12  * about this.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software Foundation,
21  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22  *
23  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
24  * All rights reserved.
25  *
26  * The Original Code is: all of this file.
27  *
28  * Contributor(s): none yet.
29  *
30  * ***** END GPL/BL DUAL LICENSE BLOCK *****
31  */
32 #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 #include "SumoPhysicsEnvironment.h"
67 #include "KX_SumoPhysicsController.h"
68
69
70 // sumo physics specific
71 #include "SM_Object.h"
72 #include "SM_FhObject.h"
73 #include "SM_Scene.h"
74 #include "SM_ClientObjectInfo.h"
75
76 #include "KX_SumoPhysicsController.h"
77
78 struct KX_PhysicsInstance
79 {
80         DT_VertexBaseHandle     m_vertexbase;
81         int                     m_vtxarray;
82         RAS_IPolyMaterial*      m_material;
83         
84         KX_PhysicsInstance(DT_VertexBaseHandle vertex_base, int vtxarray, RAS_IPolyMaterial* mat)
85                 : m_vertexbase(vertex_base),
86                   m_vtxarray(vtxarray),
87                   m_material(mat)
88         {
89         }
90         
91         ~KX_PhysicsInstance()
92         {
93                 DT_DeleteVertexBase(m_vertexbase);
94         }
95 };
96
97 static GEN_Map<GEN_HashedPtr,DT_ShapeHandle> map_gamemesh_to_sumoshape;
98 static GEN_Map<GEN_HashedPtr, KX_PhysicsInstance*> map_gamemesh_to_instance;
99
100 // forward declarations
101 static void     BL_RegisterSumoObject(KX_GameObject* gameobj,class SM_Scene* sumoScene,class SM_Object* sumoObj,const STR_String& matname,bool isDynamic,bool isActor);
102 static DT_ShapeHandle CreateShapeFromMesh(RAS_MeshObject* meshobj, bool polytope);
103
104 void    KX_ConvertSumoObject(   KX_GameObject* gameobj,
105                                 RAS_MeshObject* meshobj,
106                                 KX_Scene* kxscene,
107                                 PHY_ShapeProps* kxshapeprops,
108                                 PHY_MaterialProps*      kxmaterial,
109                                 struct  KX_ObjectProperties*    objprop)
110
111
112 {
113         SM_ShapeProps* smprop = new SM_ShapeProps;
114
115         smprop->m_ang_drag = kxshapeprops->m_ang_drag;
116         smprop->m_do_anisotropic = kxshapeprops->m_do_anisotropic;
117         smprop->m_do_fh = kxshapeprops->m_do_fh;
118         smprop->m_do_rot_fh = kxshapeprops->m_do_rot_fh ;
119         smprop->m_friction_scaling[0]  = kxshapeprops->m_friction_scaling[0];
120         smprop->m_friction_scaling[1]  = kxshapeprops->m_friction_scaling[1];
121         smprop->m_friction_scaling[2]  = kxshapeprops->m_friction_scaling[2];
122         smprop->m_inertia = MT_Vector3(1., 1., 1.) * kxshapeprops->m_inertia;
123         smprop->m_lin_drag = kxshapeprops->m_lin_drag;
124         smprop->m_mass = kxshapeprops->m_mass;
125         smprop->m_radius = objprop->m_radius;
126
127
128         SM_MaterialProps* smmaterial = new SM_MaterialProps;
129
130         smmaterial->m_fh_damping = kxmaterial->m_fh_damping;
131         smmaterial->m_fh_distance = kxmaterial->m_fh_distance;
132         smmaterial->m_fh_normal = kxmaterial->m_fh_normal;
133         smmaterial->m_fh_spring = kxmaterial->m_fh_spring;
134         smmaterial->m_friction = kxmaterial->m_friction;
135         smmaterial->m_restitution = kxmaterial->m_restitution;
136
137         SumoPhysicsEnvironment* sumoEnv =
138                 (SumoPhysicsEnvironment*)kxscene->GetPhysicsEnvironment();
139
140         SM_Scene*       sceneptr = sumoEnv->GetSumoScene();
141
142         SM_Object*      sumoObj=NULL;
143
144         if (objprop->m_dyna && objprop->m_isactor)
145         {
146                 DT_ShapeHandle shape = NULL;
147                 bool polytope = false;
148                 switch (objprop->m_boundclass)
149                 {
150                         case KX_BOUNDBOX:
151                                 shape = DT_NewBox(objprop->m_boundobject.box.m_extends[0], 
152                                                 objprop->m_boundobject.box.m_extends[1], 
153                                                 objprop->m_boundobject.box.m_extends[2]);
154                                 smprop->m_inertia.scale(objprop->m_boundobject.box.m_extends[0]*objprop->m_boundobject.box.m_extends[0],
155                                         objprop->m_boundobject.box.m_extends[1]*objprop->m_boundobject.box.m_extends[1],
156                                         objprop->m_boundobject.box.m_extends[2]*objprop->m_boundobject.box.m_extends[2]);
157                                 smprop->m_inertia *= smprop->m_mass/MT_Vector3(objprop->m_boundobject.box.m_extends).length();
158                                 break;
159                         case KX_BOUNDCYLINDER:
160                                 shape = DT_NewCylinder(smprop->m_radius, objprop->m_boundobject.c.m_height);
161                                 smprop->m_inertia.scale(smprop->m_mass*smprop->m_radius*smprop->m_radius,
162                                         smprop->m_mass*smprop->m_radius*smprop->m_radius,
163                                         smprop->m_mass*objprop->m_boundobject.c.m_height*objprop->m_boundobject.c.m_height);
164                                 break;
165                         case KX_BOUNDCONE:
166                                 shape = DT_NewCone(objprop->m_radius, objprop->m_boundobject.c.m_height);
167                                 smprop->m_inertia.scale(smprop->m_mass*smprop->m_radius*smprop->m_radius,
168                                         smprop->m_mass*smprop->m_radius*smprop->m_radius,
169                                         smprop->m_mass*objprop->m_boundobject.c.m_height*objprop->m_boundobject.c.m_height);
170                                 break;
171                         /* Dynamic mesh objects.  WARNING! slow. */
172                         case KX_BOUNDPOLYTOPE:
173                                 polytope = true;
174                                 // fall through
175                         case KX_BOUNDMESH:
176                                 if (meshobj && meshobj->NumPolygons() > 0)
177                                 {
178                                         if ((shape = CreateShapeFromMesh(meshobj, polytope)))
179                                         {
180                                                 // TODO: calculate proper inertia
181                                                 smprop->m_inertia *= smprop->m_mass*smprop->m_radius*smprop->m_radius;
182                                                 break;
183                                         }
184                                 }
185                                 /* If CreateShapeFromMesh fails, fall through and use sphere */
186                         default:
187                         case KX_BOUNDSPHERE:
188                                 shape = DT_NewSphere(objprop->m_radius);
189                                 smprop->m_inertia *= smprop->m_mass*smprop->m_radius*smprop->m_radius;
190                                 break;
191                                 
192                 }
193                 
194                 sumoObj = new SM_Object(shape, !objprop->m_ghost?smmaterial:NULL,smprop,NULL);
195                 
196                 sumoObj->setRigidBody(objprop->m_angular_rigidbody?true:false);
197                 
198                 BL_RegisterSumoObject(gameobj,sceneptr,sumoObj,"",true, true);
199                 
200         } 
201         else {
202                 // non physics object
203                 if (meshobj)
204                 {
205                         int numpolys = meshobj->NumPolygons();
206                         {
207
208                                 DT_ShapeHandle complexshape=0;
209                                 bool polytope = false;
210
211                                 switch (objprop->m_boundclass)
212                                 {
213                                         case KX_BOUNDBOX:
214                                                 complexshape = DT_NewBox(objprop->m_boundobject.box.m_extends[0], objprop->m_boundobject.box.m_extends[1], objprop->m_boundobject.box.m_extends[2]);
215                                                 break;
216                                         case KX_BOUNDSPHERE:
217                                                 complexshape = DT_NewSphere(objprop->m_boundobject.c.m_radius);
218                                                 break;
219                                         case KX_BOUNDCYLINDER:
220                                                 complexshape = DT_NewCylinder(objprop->m_boundobject.c.m_radius, objprop->m_boundobject.c.m_height);
221                                                 break;
222                                         case KX_BOUNDCONE:
223                                                 complexshape = DT_NewCone(objprop->m_boundobject.c.m_radius, objprop->m_boundobject.c.m_height);
224                                                 break;
225                                         case KX_BOUNDPOLYTOPE:
226                                                 polytope = true;
227                                                 // fall through
228                                         default:
229                                         case KX_BOUNDMESH:
230                                                 if (numpolys>0)
231                                                 {
232                                                         complexshape = CreateShapeFromMesh(meshobj, polytope);
233                                                         //std::cout << "Convert Physics Mesh: " << meshobj->GetName() << std::endl;
234 /*                                                      if (!complexshape) 
235                                                         {
236                                                                 // Something has to be done here - if the object has no polygons, it will not be able to have
237                                                                 //   sensors attached to it. 
238                                                                 DT_Vector3 pt = {0., 0., 0.};
239                                                                 complexshape = DT_NewSphere(1.0);
240                                                                 objprop->m_ghost = evilObject = true;
241                                                         } */
242                                                 }
243                                                 break;
244                                 }
245                                 
246                                 if (complexshape)
247                                 {
248                                         SM_Object *dynamicParent = NULL;
249
250                                         if (objprop->m_dynamic_parent)
251                                         {
252                                                 // problem is how to find the dynamic parent
253                                                 // in the scenegraph
254                                                 KX_SumoPhysicsController* sumoctrl = 
255                                                 (KX_SumoPhysicsController*)
256                                                         objprop->m_dynamic_parent->GetPhysicsController();
257
258                                                 if (sumoctrl)
259                                                 {
260                                                         dynamicParent = sumoctrl->GetSumoObject();
261                                                 }
262
263                                                 MT_assert(dynamicParent);
264                                         }
265                                 
266                                         
267                                         sumoObj = new SM_Object(complexshape,!objprop->m_ghost?smmaterial:NULL,NULL, dynamicParent);    
268                                         const STR_String& matname=meshobj->GetMaterialName(0);
269
270                                         
271                                         BL_RegisterSumoObject(gameobj,sceneptr,
272                                                 sumoObj,
273                                                 matname,
274                                                 objprop->m_dyna,
275                                                 objprop->m_isactor);
276                                 }
277                         }
278                 }
279         }
280
281         // physics object get updated here !
282
283         
284         // lazy evaluation because we might not support scaling !gameobj->UpdateTransform();
285
286         if (objprop->m_in_active_layer && sumoObj)
287         {
288                 sceneptr->add(*sumoObj);
289         }
290
291 }
292
293
294
295 static void     BL_RegisterSumoObject(
296         KX_GameObject* gameobj,
297         class SM_Scene* sumoScene,
298         class SM_Object* sumoObj,
299         const STR_String& matname,
300         bool isDynamic,
301         bool isActor) 
302 {
303                 PHY_IMotionState* motionstate = new KX_MotionState(gameobj->GetSGNode());
304
305                 // need easy access, not via 'node' etc.
306                 KX_SumoPhysicsController* physicscontroller = new KX_SumoPhysicsController(sumoScene,sumoObj,motionstate,isDynamic);
307                 gameobj->SetPhysicsController(physicscontroller);
308
309                 
310                 if (!gameobj->getClientInfo())
311                         std::cout << "BL_RegisterSumoObject: WARNING: Object " << gameobj->GetName() << " has no client info" << std::endl;
312                 physicscontroller->setNewClientInfo(gameobj->getClientInfo());
313                 
314
315                 gameobj->GetSGNode()->AddSGController(physicscontroller);
316
317                 gameobj->getClientInfo()->m_type = (isActor ? KX_ClientObjectInfo::ACTOR : KX_ClientObjectInfo::STATIC);
318
319                 // store materialname in auxinfo, needed for touchsensors
320                 gameobj->getClientInfo()->m_auxilary_info = (matname.Length() ? (void*)(matname.ReadPtr()+2) : NULL);
321
322                 physicscontroller->SetObject(gameobj->GetSGNode());
323 }
324
325 static DT_ShapeHandle InstancePhysicsComplex(RAS_MeshObject* meshobj, int vtxarray, RAS_IPolyMaterial *mat)
326 {
327         // instance a mesh from a single vertex array & material
328         const RAS_TexVert *vertex_array = &((*meshobj->GetVertexCache(mat)[vtxarray])[0]);
329         //const KX_IndexArray &index_array = *meshobj->GetIndexCache(mat)[vtxarray];
330         DT_VertexBaseHandle vertex_base = DT_NewVertexBase(vertex_array[0].getLocalXYZ(), sizeof(RAS_TexVert));
331         
332         DT_ShapeHandle shape = DT_NewComplexShape(vertex_base);
333         
334         std::vector<DT_Index> indices;
335         for (int p = 0; p < meshobj->NumPolygons(); p++)
336         {
337                 RAS_Polygon* poly = meshobj->GetPolygon(p);
338         
339                 // only add polygons that have the collisionflag set
340                 if (poly->IsCollider())
341                 {
342                         DT_VertexIndices(3, poly->GetVertexIndexBase().m_indexarray);
343                         
344                         // tesselate
345                         if (poly->VertexCount() == 4)
346                         {
347                                 DT_Begin();
348                                   DT_VertexIndex(poly->GetVertexIndexBase().m_indexarray[0]);
349                                   DT_VertexIndex(poly->GetVertexIndexBase().m_indexarray[2]);
350                                   DT_VertexIndex(poly->GetVertexIndexBase().m_indexarray[3]);
351                                 DT_End();
352                         }
353                 }
354         }
355
356         //DT_VertexIndices(indices.size(), &indices[0]);
357         DT_EndComplexShape();
358         
359         map_gamemesh_to_instance.insert(GEN_HashedPtr(meshobj), new KX_PhysicsInstance(vertex_base, vtxarray, mat));
360         return shape;
361 }
362
363 static DT_ShapeHandle InstancePhysicsPolytope(RAS_MeshObject* meshobj, int vtxarray, RAS_IPolyMaterial *mat)
364 {
365         // instance a mesh from a single vertex array & material
366         const RAS_TexVert *vertex_array = &((*meshobj->GetVertexCache(mat)[vtxarray])[0]);
367         //const KX_IndexArray &index_array = *meshobj->GetIndexCache(mat)[vtxarray];
368         DT_VertexBaseHandle vertex_base = DT_NewVertexBase(vertex_array[0].getLocalXYZ(), 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->GetVertexIndexBase().m_indexarray[0]);
379                         indices.push_back(poly->GetVertexIndexBase().m_indexarray[1]);
380                         indices.push_back(poly->GetVertexIndexBase().m_indexarray[2]);
381                         
382                         if (poly->VertexCount() == 4)
383                                 indices.push_back(poly->GetVertexIndexBase().m_indexarray[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, vtxarray, 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 = &((*meshobj->GetVertexCache(instance->m_material)[instance->m_vtxarray])[0]);
404                 DT_ChangeVertexBase(instance->m_vertexbase, vertex_array[0].getLocalXYZ());
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         int vtxarray = -1;
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->GetVertexIndexBase().m_vtxarray != vtxarray)
443                         {
444                                 if (vtxarray < 0)
445                                         vtxarray = poly->GetVertexIndexBase().m_vtxarray;
446                                 else
447                                 {
448                                         reinstance = false;
449                                         vtxarray = -1;
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, vtxarray, poly_material);
484                 else
485                         shape = InstancePhysicsComplex(meshobj, vtxarray, 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 (vtxarray < 0)
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 */
511                                 DT_Vertex(meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray, 
512                                         poly->GetVertexIndexBase().m_indexarray[2],
513                                         poly->GetMaterial()->GetPolyMaterial())->getLocalXYZ());
514                                 /* V2 */
515                                 DT_Vertex(meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray, 
516                                         poly->GetVertexIndexBase().m_indexarray[1],
517                                         poly->GetMaterial()->GetPolyMaterial())->getLocalXYZ());
518                                 /* V3 */
519                                 DT_Vertex(meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray, 
520                                         poly->GetVertexIndexBase().m_indexarray[0],
521                                         poly->GetMaterial()->GetPolyMaterial())->getLocalXYZ());
522                                 
523                                 numvalidpolys++;
524                            DT_End();
525                                 
526                                 if (poly->VertexCount() == 4)
527                                 {
528                                    DT_Begin();
529                                         /* V1 */
530                                         DT_Vertex(meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray, 
531                                                 poly->GetVertexIndexBase().m_indexarray[3],
532                                                 poly->GetMaterial()->GetPolyMaterial())->getLocalXYZ());
533                                         /* V3 */
534                                         DT_Vertex(meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray, 
535                                                 poly->GetVertexIndexBase().m_indexarray[2],
536                                                 poly->GetMaterial()->GetPolyMaterial())->getLocalXYZ());
537                                         /* V4 */
538                                         DT_Vertex(meshobj->GetVertex(poly->GetVertexIndexBase().m_vtxarray, 
539                                                 poly->GetVertexIndexBase().m_indexarray[0],
540                                                 poly->GetMaterial()->GetPolyMaterial())->getLocalXYZ());
541                                 
542                                         numvalidpolys++;
543                                    DT_End();
544                                 }
545                 
546                         }
547                 }
548                 
549                 DT_EndComplexShape();
550         }
551
552         if (numvalidpolys > 0)
553         {
554                 map_gamemesh_to_sumoshape.insert(GEN_HashedPtr(meshobj),shape);
555                 return shape;
556         }
557
558         delete shape;
559         return NULL;
560 }
561
562 void    KX_ClearSumoSharedShapes()
563 {
564         int numshapes = map_gamemesh_to_sumoshape.size();
565         int i;
566         for (i=0;i<numshapes ;i++)
567         {
568                 DT_ShapeHandle shape = *map_gamemesh_to_sumoshape.at(i);
569                 DT_DeleteShape(shape);
570         }
571         
572         map_gamemesh_to_sumoshape.clear();
573         
574         for (i=0; i < map_gamemesh_to_instance.size(); i++)
575                 delete *map_gamemesh_to_instance.at(i);
576         
577         map_gamemesh_to_instance.clear();
578 }
579
580 #endif //USE_SUMO_SOLID
581
582
583 #ifdef USE_ODE
584
585 void    KX_ConvertODEEngineObject(KX_GameObject* gameobj,
586                                                          RAS_MeshObject* meshobj,
587                                                          KX_Scene* kxscene,
588                                                         struct  PHY_ShapeProps* shapeprops,
589                                                         struct  PHY_MaterialProps*      smmaterial,
590                                                         struct  KX_ObjectProperties*    objprop)
591 {
592         
593         // not yet, future extension :)
594         bool dyna=objprop->m_dyna;
595         bool fullRigidBody= ( objprop->m_dyna && objprop->m_angular_rigidbody) != 0;
596         bool phantom = objprop->m_ghost;
597         class PHY_IMotionState* motionstate = new KX_MotionState(gameobj->GetSGNode());
598
599         class ODEPhysicsEnvironment* odeEnv =
600                 (ODEPhysicsEnvironment*)kxscene->GetPhysicsEnvironment();
601
602         dxSpace* space = odeEnv->GetOdeSpace();
603         dxWorld* world = odeEnv->GetOdeWorld();
604
605         bool isSphere = false;
606
607         switch (objprop->m_boundclass)
608         {
609         case KX_BOUNDBOX:
610                 {
611
612                                 KX_OdePhysicsController* physicscontroller = 
613                                         new KX_OdePhysicsController(
614                                         dyna,
615                                         fullRigidBody,
616                                         phantom,
617                                         motionstate,
618                                         space,
619                                         world,
620                                         shapeprops->m_mass,
621                                         smmaterial->m_friction,
622                                         smmaterial->m_restitution,
623                                         isSphere,
624                                         objprop->m_boundobject.box.m_center,
625                                         objprop->m_boundobject.box.m_extends,
626                                         objprop->m_boundobject.c.m_radius
627                                         );
628
629                                 gameobj->SetPhysicsController(physicscontroller);
630                                 physicscontroller->setNewClientInfo(gameobj->getClientInfo());                                          
631                                 gameobj->GetSGNode()->AddSGController(physicscontroller);
632
633                                 bool isActor = objprop->m_isactor;
634                                 STR_String materialname;
635                                 if (meshobj)
636                                         materialname = meshobj->GetMaterialName(0);
637
638                                 const char* matname = materialname.ReadPtr();
639
640
641                                 physicscontroller->SetObject(gameobj->GetSGNode());
642
643                                 break;
644                         }
645         default:
646                 {
647                 }
648         };
649
650 }
651
652
653 #endif // USE_ODE