contribution from RCRuiz:
[blender.git] / source / gameengine / Converter / KX_BlenderSceneConverter.cpp
1 /**
2  * $Id$
3  * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version. The Blender
9  * Foundation also sells licenses for use in proprietary software under
10  * the Blender License.  See http://www.blender.org/BL/ for information
11  * about this.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software Foundation,
20  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
21  *
22  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
23  * All rights reserved.
24  *
25  * The Original Code is: all of this file.
26  *
27  * Contributor(s): none yet.
28  *
29  * ***** END GPL/BL DUAL LICENSE BLOCK *****
30  */
31
32 #ifdef WIN32
33         #pragma warning (disable:4786) // suppress stl-MSVC debug info warning
34 #endif
35
36 #include "KX_Scene.h"
37 #include "KX_GameObject.h"
38 #include "KX_BlenderSceneConverter.h"
39 #include "KX_IpoConvert.h"
40 #include "RAS_MeshObject.h"
41 #include "KX_PhysicsEngineEnums.h"
42 #include "PHY_IPhysicsEnvironment.h"
43 #include "KX_KetsjiEngine.h"
44 #include "KX_IPhysicsController.h"
45 #include "BL_Material.h"
46
47 #include "DummyPhysicsEnvironment.h"
48
49 //to decide to use sumo/ode or dummy physics - defines USE_ODE
50 #include "KX_ConvertPhysicsObject.h"
51
52 #ifdef USE_BULLET
53 #include "CcdPhysicsEnvironment.h"
54 #endif
55
56 #ifdef USE_ODE
57 #include "OdePhysicsEnvironment.h"
58 #endif //USE_ODE
59
60 #ifdef USE_SUMO_SOLID
61 #include "SumoPhysicsEnvironment.h"
62 #endif
63
64 #include "KX_BlenderSceneConverter.h"
65 #include "KX_BlenderScalarInterpolator.h"
66 #include "BL_BlenderDataConversion.h"
67 #include "BlenderWorldInfo.h"
68 #include "KX_Scene.h"
69
70 /* This little block needed for linking to Blender... */
71 #ifdef WIN32
72 #include "BLI_winstuff.h"
73 #endif
74
75 /* This list includes only data type definitions */
76 #include "DNA_scene_types.h"
77 #include "DNA_world_types.h"
78 #include "BKE_main.h"
79
80 #include "BLI_arithb.h"
81
82 extern "C"
83 {
84 #include "DNA_object_types.h"
85 #include "DNA_curve_types.h"
86 #include "BLI_blenlib.h"
87 #include "MEM_guardedalloc.h"
88 #include "BSE_editipo.h"
89 #include "BSE_editipo_types.h"
90 #include "DNA_ipo_types.h"
91 #include "BKE_global.h"
92 #include "DNA_space_types.h"
93 }
94
95
96 KX_BlenderSceneConverter::KX_BlenderSceneConverter(
97                                                         struct Main* maggie,
98                                                         struct SpaceIpo*        sipo,
99                                                         class KX_KetsjiEngine* engine
100                                                         )
101                                                         : m_maggie(maggie),
102                                                         m_sipo(sipo),
103                                                         m_ketsjiEngine(engine),
104                                                         m_alwaysUseExpandFraming(false),
105                                                         m_usemat(false)
106 {
107         m_newfilename = "";
108 }
109
110
111 KX_BlenderSceneConverter::~KX_BlenderSceneConverter()
112 {
113         // clears meshes, and hashmaps from blender to gameengine data
114         int i;
115         // delete sumoshapes
116         
117
118         int numipolists = m_map_blender_to_gameipolist.size();
119         for (i=0; i<numipolists; i++) {
120                 BL_InterpolatorList *ipoList= *m_map_blender_to_gameipolist.at(i);
121
122                 delete (ipoList);
123         }
124
125         vector<KX_WorldInfo*>::iterator itw = m_worldinfos.begin();
126         while (itw != m_worldinfos.end()) {
127                 delete (*itw);
128                 itw++;
129         }
130
131         vector<RAS_IPolyMaterial*>::iterator itp = m_polymaterials.begin();
132         while (itp != m_polymaterials.end()) {
133                 delete (*itp);
134                 itp++;
135         }
136
137         // delete after RAS_IPolyMaterial
138         vector<BL_Material *>::iterator itmat = m_materials.begin();
139         while (itmat != m_materials.end()) {
140                 delete (*itmat);
141                 itmat++;
142         }       
143
144
145         vector<RAS_MeshObject*>::iterator itm = m_meshobjects.begin();
146         while (itm != m_meshobjects.end()) {
147                 delete (*itm);
148                 itm++;
149         }
150         
151 #ifdef USE_SUMO_SOLID
152         KX_ClearSumoSharedShapes();
153 #endif
154
155 #ifdef USE_BULLET
156         KX_ClearBulletSharedShapes();
157 #endif
158
159 }
160
161
162
163 void KX_BlenderSceneConverter::SetNewFileName(const STR_String& filename)
164 {
165         m_newfilename = filename;
166 }
167
168
169
170 bool KX_BlenderSceneConverter::TryAndLoadNewFile()
171 {
172         bool result = false;
173
174         // find the file
175 /*      if ()
176         {
177                 result = true;
178         }
179         // if not, clear the newfilename
180         else
181         {
182                 m_newfilename = "";     
183         }
184 */
185         return result;
186 }
187
188
189
190         /**
191          * Find the specified scene by name, or the first
192          * scene if nothing matches (shouldn't happen).
193          */
194 static struct Scene *GetSceneForName2(struct Main *maggie, const STR_String& scenename) {
195         Scene *sce;
196
197         for (sce= (Scene*) maggie->scene.first; sce; sce= (Scene*) sce->id.next)
198                 if (scenename == (sce->id.name+2))
199                         return sce;
200
201         return (Scene*) maggie->scene.first;
202 }
203 #include "KX_PythonInit.h"
204
205 #ifdef USE_BULLET
206
207 #include "LinearMath/btIDebugDraw.h"
208
209
210 struct  BlenderDebugDraw : public btIDebugDraw
211 {
212         BlenderDebugDraw () :
213                 m_debugMode(0) 
214         {
215         }
216         
217         int m_debugMode;
218
219         virtual void    drawLine(const btVector3& from,const btVector3& to,const btVector3& color)
220         {
221                 if (m_debugMode >0)
222                 {
223                         MT_Vector3 kxfrom(from[0],from[1],from[2]);
224                         MT_Vector3 kxto(to[0],to[1],to[2]);
225                         MT_Vector3 kxcolor(color[0],color[1],color[2]);
226
227                         KX_RasterizerDrawDebugLine(kxfrom,kxto,kxcolor);
228                 }
229         }
230         
231         virtual void    drawContactPoint(const btVector3& PointOnB,const btVector3& normalOnB,float distance,int lifeTime,const btVector3& color)
232         {
233                 //not yet
234         }
235
236         virtual void    setDebugMode(int debugMode)
237         {
238                 m_debugMode = debugMode;
239         }
240         virtual int             getDebugMode() const
241         {
242                 return m_debugMode;
243         }
244                 
245 };
246
247 #endif
248
249 void KX_BlenderSceneConverter::ConvertScene(const STR_String& scenename,
250                                                                                         class KX_Scene* destinationscene,
251                                                                                         PyObject* dictobj,
252                                                                                         class SCA_IInputDevice* keyinputdev,
253                                                                                         class RAS_IRenderTools* rendertools,
254                                                                                         class RAS_ICanvas* canvas)
255 {
256         //find out which physics engine
257         Scene *blenderscene = GetSceneForName2(m_maggie, scenename);
258
259         e_PhysicsEngine physics_engine = UseBullet;
260
261         if (blenderscene)
262         {
263         
264                 if (blenderscene->world)
265                 {
266                         switch (blenderscene->world->physicsEngine)
267                         {
268                         case WOPHY_BULLET:
269                                 {
270                                         physics_engine = UseBullet;
271                                         break;
272                                 }
273                                 
274                                 case WOPHY_ODE:
275                                 {
276                                         physics_engine = UseODE;
277                                         break;
278                                 }
279                                 case WOPHY_DYNAMO:
280                                 {
281                                         physics_engine = UseDynamo;
282                                         break;
283                                 }
284                                 case WOPHY_SUMO:
285                                 {
286                                         physics_engine = UseSumo; 
287                                         break;
288                                 }
289                                 case WOPHY_NONE:
290                                 {
291                                         physics_engine = UseNone;
292                                 }
293                         }
294                   
295                 }
296         }
297
298         switch (physics_engine)
299         {
300 #ifdef USE_BULLET
301                 case UseBullet:
302                         {
303                                 CcdPhysicsEnvironment* ccdPhysEnv = new CcdPhysicsEnvironment();
304                                 ccdPhysEnv->setDebugDrawer(new BlenderDebugDraw());
305                                 ccdPhysEnv->setDeactivationLinearTreshold(0.8f); // default, can be overridden by Python
306                                 ccdPhysEnv->setDeactivationAngularTreshold(1.0f); // default, can be overridden by Python
307
308                                 //todo: get a button in blender ?
309                                 //disable / enable debug drawing (contact points, aabb's etc)   
310                                 //ccdPhysEnv->setDebugMode(1);
311                                 destinationscene->SetPhysicsEnvironment(ccdPhysEnv);
312                                 break;
313                         }
314 #endif
315
316 #ifdef USE_SUMO_SOLID
317                 case UseSumo:
318                         destinationscene ->SetPhysicsEnvironment(new SumoPhysicsEnvironment());
319                         break;
320 #endif
321 #ifdef USE_ODE
322
323                 case UseODE:
324                         destinationscene ->SetPhysicsEnvironment(new ODEPhysicsEnvironment());
325                         break;
326 #endif //USE_ODE
327         
328                 case UseDynamo:
329                 {
330                 }
331                 
332                 default:
333                 case UseNone:
334                         physics_engine = UseNone;
335                         destinationscene ->SetPhysicsEnvironment(new DummyPhysicsEnvironment());
336                         break;
337         }
338
339         BL_ConvertBlenderObjects(m_maggie,
340                 scenename,
341                 destinationscene,
342                 m_ketsjiEngine,
343                 physics_engine,
344                 dictobj,
345                 keyinputdev,
346                 rendertools,
347                 canvas,
348                 this,
349                 m_alwaysUseExpandFraming
350                 );
351
352         m_map_blender_to_gameactuator.clear();
353         m_map_blender_to_gamecontroller.clear();
354         
355         m_map_blender_to_gameobject.clear();
356         m_map_mesh_to_gamemesh.clear();
357
358         //don't clear it yet, it is needed for the baking physics into ipo animation
359         //m_map_gameobject_to_blender.clear();
360 }
361
362
363 // use blender materials
364 void KX_BlenderSceneConverter::SetMaterials(bool val)
365 {
366         m_usemat = val;
367 }
368
369 bool KX_BlenderSceneConverter::GetMaterials()
370 {
371         return m_usemat;
372 }
373
374
375 void KX_BlenderSceneConverter::RegisterBlenderMaterial(BL_Material *mat)
376 {
377         m_materials.push_back(mat);
378 }
379
380
381
382 void KX_BlenderSceneConverter::SetAlwaysUseExpandFraming(
383         bool to_what)
384 {
385         m_alwaysUseExpandFraming= to_what;
386 }
387
388         
389
390 void KX_BlenderSceneConverter::RegisterGameObject(
391                                                                         KX_GameObject *gameobject, 
392                                                                         struct Object *for_blenderobject) 
393 {
394         m_map_gameobject_to_blender.insert(CHashedPtr(gameobject),for_blenderobject);
395         m_map_blender_to_gameobject.insert(CHashedPtr(for_blenderobject),gameobject);
396 }
397
398
399
400 KX_GameObject *KX_BlenderSceneConverter::FindGameObject(
401                                                                         struct Object *for_blenderobject) 
402 {
403         KX_GameObject **obp= m_map_blender_to_gameobject[CHashedPtr(for_blenderobject)];
404         
405         return obp?*obp:NULL;
406 }
407
408
409
410 struct Object *KX_BlenderSceneConverter::FindBlenderObject(
411                                                                         KX_GameObject *for_gameobject) 
412 {
413         struct Object **obp= m_map_gameobject_to_blender[CHashedPtr(for_gameobject)];
414         
415         return obp?*obp:NULL;
416 }
417
418         
419
420 void KX_BlenderSceneConverter::RegisterGameMesh(
421                                                                         RAS_MeshObject *gamemesh,
422                                                                         struct Mesh *for_blendermesh)
423 {
424         m_map_mesh_to_gamemesh.insert(CHashedPtr(for_blendermesh),gamemesh);
425         m_meshobjects.push_back(gamemesh);
426 }
427
428
429
430 RAS_MeshObject *KX_BlenderSceneConverter::FindGameMesh(
431                                                                         struct Mesh *for_blendermesh,
432                                                                         unsigned int onlayer)
433 {
434         RAS_MeshObject** meshp = m_map_mesh_to_gamemesh[CHashedPtr(for_blendermesh)];
435         
436         if (meshp && onlayer==(*meshp)->GetLightLayer()) {
437                 return *meshp;
438         } else {
439                 return NULL;
440         }
441 }
442
443         
444
445
446         
447
448 void KX_BlenderSceneConverter::RegisterPolyMaterial(RAS_IPolyMaterial *polymat)
449 {
450         m_polymaterials.push_back(polymat);
451 }
452
453
454
455 void KX_BlenderSceneConverter::RegisterInterpolatorList(
456                                                                         BL_InterpolatorList *ipoList,
457                                                                         struct Ipo *for_ipo)
458 {
459         m_map_blender_to_gameipolist.insert(CHashedPtr(for_ipo), ipoList);
460 }
461
462
463
464 BL_InterpolatorList *KX_BlenderSceneConverter::FindInterpolatorList(
465                                                                         struct Ipo *for_ipo)
466 {
467         BL_InterpolatorList **listp = m_map_blender_to_gameipolist[CHashedPtr(for_ipo)];
468                 
469         return listp?*listp:NULL;
470 }
471
472
473
474 void KX_BlenderSceneConverter::RegisterGameActuator(
475                                                                         SCA_IActuator *act,
476                                                                         struct bActuator *for_actuator)
477 {
478         m_map_blender_to_gameactuator.insert(CHashedPtr(for_actuator), act);
479 }
480
481
482
483 SCA_IActuator *KX_BlenderSceneConverter::FindGameActuator(
484                                                                         struct bActuator *for_actuator)
485 {
486         SCA_IActuator **actp = m_map_blender_to_gameactuator[CHashedPtr(for_actuator)];
487         
488         return actp?*actp:NULL;
489 }
490
491
492
493 void KX_BlenderSceneConverter::RegisterGameController(
494                                                                         SCA_IController *cont,
495                                                                         struct bController *for_controller)
496 {
497         m_map_blender_to_gamecontroller.insert(CHashedPtr(for_controller), cont);
498 }
499
500
501
502 SCA_IController *KX_BlenderSceneConverter::FindGameController(
503                                                                         struct bController *for_controller)
504 {
505         SCA_IController **contp = m_map_blender_to_gamecontroller[CHashedPtr(for_controller)];
506         
507         return contp?*contp:NULL;
508 }
509
510
511
512 void KX_BlenderSceneConverter::RegisterWorldInfo(
513                                                                         KX_WorldInfo *worldinfo)
514 {
515         m_worldinfos.push_back(worldinfo);
516 }
517
518 /*
519  * When deleting an IPO curve from Python, check if the IPO is being
520  * edited and if so clear the pointer to the old curve.
521  */
522 void KX_BlenderSceneConverter::localDel_ipoCurve ( IpoCurve * icu ,struct SpaceIpo*     sipo)
523 {
524         if (!sipo)
525                 return;
526
527         int i;
528         EditIpo *ei= (EditIpo *)sipo->editipo;
529         if (!ei) return;
530
531         for(i=0; i<G.sipo->totipo; i++, ei++) {
532                 if ( ei->icu == icu ) {
533                         ei->flag &= ~(IPO_SELECT | IPO_EDIT);
534                         ei->icu= 0;
535                         return;
536                 }
537         }
538 }
539
540 //quick hack
541 extern "C"
542 {
543         Ipo *add_ipo( char *name, int idcode );
544         char *getIpoCurveName( IpoCurve * icu );
545         struct IpoCurve *verify_ipocurve(struct ID *, short, char *, char *, int);
546         void testhandles_ipocurve(struct IpoCurve *icu);
547         void Mat3ToEul(float tmat[][3], float *eul);
548
549 }
550
551 IpoCurve* findIpoCurve(IpoCurve* first,char* searchName)
552 {
553         IpoCurve* icu1;
554         for( icu1 = first; icu1; icu1 = icu1->next ) 
555         {
556                 char* curveName = getIpoCurveName( icu1 );
557                 if( !strcmp( curveName, searchName) )
558                 {
559                         return icu1;
560                 }
561         }
562         return 0;
563 }
564
565 // this is not longer necesary //rcruiz
566 /*Ipo* KX_BlenderSceneConverter::findIpoForName(char* objName)
567 {
568         Ipo* ipo_iter = (Ipo*)m_maggie->ipo.first;
569
570         while( ipo_iter )
571         {
572                 if( strcmp( objName, ipo_iter->id.name + 2 ) == 0 ) 
573                 {
574                         return ipo_iter;
575                 }
576                 ipo_iter = (Ipo*)ipo_iter->id.next;
577         }
578         return 0;
579 }
580 */
581
582 void    KX_BlenderSceneConverter::ResetPhysicsObjectsAnimationIpo(bool clearIpo)
583 {
584
585         KX_SceneList* scenes = m_ketsjiEngine->CurrentScenes();
586         int numScenes = scenes->size();
587         int i;
588         for (i=0;i<numScenes;i++)
589         {
590                 KX_Scene* scene = scenes->at(i);
591                 //PHY_IPhysicsEnvironment* physEnv = scene->GetPhysicsEnvironment();
592                 CListValue* parentList = scene->GetRootParentList();
593                 int numObjects = parentList->GetCount();
594                 int g;
595                 for (g=0;g<numObjects;g++)
596                 {
597                         KX_GameObject* gameObj = (KX_GameObject*)parentList->GetValue(g);
598                         if (gameObj->IsDynamic())
599                         {
600                                 //KX_IPhysicsController* physCtrl = gameObj->GetPhysicsController();
601                                 
602                                 Object* blenderObject = FindBlenderObject(gameObj);
603                                 if (blenderObject)
604                                 {
605                                         //erase existing ipo's
606                                         Ipo* ipo = blenderObject->ipo;//findIpoForName(blenderObject->id.name+2);
607                                         if (ipo)
608                                         {       //clear the curve data
609                                                 if (clearIpo){//rcruiz
610                                                         IpoCurve *icu1;
611                                                                                                                 
612                                                         int numCurves = 0;
613                                                         for( icu1 = (IpoCurve*)ipo->curve.first; icu1;  ) {
614                                                         
615                                                                 IpoCurve* tmpicu = icu1;
616                                                                 
617                                                                 /*int i;
618                                                                 BezTriple *bezt;
619                                                                 for( bezt = tmpicu->bezt, i = 0;        i < tmpicu->totvert; i++, bezt++){
620                                                                         printf("(%f,%f,%f),(%f,%f,%f),(%f,%f,%f)\n",bezt->vec[0][0],bezt->vec[0][1],bezt->vec[0][2],bezt->vec[1][0],bezt->vec[1][1],bezt->vec[1][2],bezt->vec[2][0],bezt->vec[2][1],bezt->vec[2][2]);
621                                                                 }*/
622                                                                 
623                                                                 icu1 = icu1->next;
624                                                                 numCurves++;
625                         
626                                                                 BLI_remlink( &( blenderObject->ipo->curve ), tmpicu );
627                                                                 if( tmpicu->bezt )
628                                                                         MEM_freeN( tmpicu->bezt );
629                                                                 MEM_freeN( tmpicu );
630                                                                 localDel_ipoCurve( tmpicu ,m_sipo);
631                                                         }
632                                                 }
633                                         } else
634                                         {       ipo = add_ipo(blenderObject->id.name+2, ID_OB);
635                                                 blenderObject->ipo = ipo;
636
637                                         }
638                                 
639                                         
640
641                                         
642
643                                 }
644                         }
645
646                 }
647                 
648         
649         }
650
651
652
653 }
654
655 void    KX_BlenderSceneConverter::resetNoneDynamicObjectToIpo(){
656         
657         if (addInitFromFrame){          
658                 KX_SceneList* scenes = m_ketsjiEngine->CurrentScenes();
659                 int numScenes = scenes->size();
660                 if (numScenes>=0){
661                         KX_Scene* scene = scenes->at(0);
662                         CListValue* parentList = scene->GetRootParentList();
663                         for (int ix=0;ix<parentList->GetCount();ix++){
664                                 KX_GameObject* gameobj = (KX_GameObject*)parentList->GetValue(ix);
665                                 if (!gameobj->IsDynamic()){
666                                         Object* blenderobject = FindBlenderObject(gameobj);
667                                         if (!blenderobject)
668                                                 continue;
669                                         if (blenderobject->type==OB_ARMATURE)
670                                                 continue;
671                                         float eu[3];
672                                         Mat4ToEul(blenderobject->obmat,eu);                                     
673                                         MT_Point3 pos = MT_Point3(
674                                                 blenderobject->obmat[3][0],
675                                                 blenderobject->obmat[3][1],
676                                                 blenderobject->obmat[3][2]
677                                         );
678                                         MT_Vector3 eulxyz = MT_Vector3(
679                                                 eu[0],
680                                                 eu[1],
681                                                 eu[2]
682                                         );
683                                         MT_Vector3 scale = MT_Vector3(
684                                                 blenderobject->size[0],
685                                                 blenderobject->size[1],
686                                                 blenderobject->size[2]
687                                         );
688                                         gameobj->NodeSetLocalPosition(pos);
689                                         gameobj->NodeSetLocalOrientation(MT_Matrix3x3(eulxyz));
690                                         gameobj->NodeSetLocalScale(scale);
691                                         gameobj->NodeUpdateGS(0,true);
692                                 }
693                         }
694                 }
695         }
696 }
697
698 #define TEST_HANDLES_GAME2IPO 0
699
700         ///this generates ipo curves for position, rotation, allowing to use game physics in animation
701 void    KX_BlenderSceneConverter::WritePhysicsObjectToAnimationIpo(int frameNumber)
702 {
703
704         KX_SceneList* scenes = m_ketsjiEngine->CurrentScenes();
705         int numScenes = scenes->size();
706         int i;
707         for (i=0;i<numScenes;i++)
708         {
709                 KX_Scene* scene = scenes->at(i);
710                 //PHY_IPhysicsEnvironment* physEnv = scene->GetPhysicsEnvironment();
711                 CListValue* parentList = scene->GetRootParentList();
712                 int numObjects = parentList->GetCount();
713                 int g;
714                 for (g=0;g<numObjects;g++)
715                 {
716                         KX_GameObject* gameObj = (KX_GameObject*)parentList->GetValue(g);
717                         if (gameObj->IsDynamic())
718                         {
719                                 KX_IPhysicsController* physCtrl = gameObj->GetPhysicsController();
720                                 
721                                 Object* blenderObject = FindBlenderObject(gameObj);
722                                 if (blenderObject)
723                                 {
724
725                                         const MT_Matrix3x3& orn = gameObj->NodeGetWorldOrientation();
726                                         float eulerAngles[3];   
727                                         float tmat[3][3];
728                                         for (int r=0;r<3;r++)
729                                         {
730                                                 for (int c=0;c<3;c++)
731                                                 {
732                                                         tmat[r][c] = orn[c][r];
733                                                 }
734                                         }
735                                         Mat3ToEul(tmat, eulerAngles);
736                                         
737                                         for(int x = 0; x < 3; x++) {
738                                                 eulerAngles[x] *= (float) (180 / 3.14159265f);
739                                         }
740
741                                         eulerAngles[0]/=10.f;
742                                         eulerAngles[1]/=10.f;
743                                         eulerAngles[2]/=10.f;
744
745
746
747                                         const MT_Vector3& scale = gameObj->NodeGetWorldScaling();
748                                         const MT_Point3& position = gameObj->NodeGetWorldPosition();
749                                         
750                                         Ipo* ipo = blenderObject->ipo;
751                                         if (ipo)
752                                         {
753
754                                                 //create the curves, if not existing
755
756                                         IpoCurve *icu1 = findIpoCurve((IpoCurve *)ipo->curve.first,"LocX");
757                                         if (!icu1)
758                                                 icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, OB_LOC_X);
759                                         
760                                         icu1 = findIpoCurve((IpoCurve *)ipo->curve.first,"LocY");
761                                         if (!icu1)
762                                                 icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, OB_LOC_Y);
763                                         
764                                         icu1 = findIpoCurve((IpoCurve *)ipo->curve.first,"LocZ");
765                                         if (!icu1)
766                                                 icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, OB_LOC_Z);
767
768                                         icu1 = findIpoCurve((IpoCurve *)ipo->curve.first,"RotX");
769                                         if (!icu1)
770                                                 icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, OB_ROT_X);
771
772                                         icu1 = findIpoCurve((IpoCurve *)ipo->curve.first,"RotY");
773                                         if (!icu1)
774                                                 icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, OB_ROT_Y);
775
776                                         icu1 = findIpoCurve((IpoCurve *)ipo->curve.first,"RotZ");
777                                         if (!icu1)
778                                                 icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, OB_ROT_Z);
779
780
781
782                                         //fill the curves with data
783
784                                                 icu1 = findIpoCurve((IpoCurve *)ipo->curve.first,"LocX");
785                                                 if (icu1)
786                                                 {
787                                                         float curVal = position.x();
788                                                         insert_vert_ipo(icu1, frameNumber, curVal);
789 #ifdef TEST_HANDLES_GAME2IPO
790                                                         testhandles_ipocurve(icu1);
791 #endif
792                                                 }
793                                                 icu1 = findIpoCurve((IpoCurve *)ipo->curve.first,"LocY");
794                                                 if (icu1)
795                                                 {
796                                                         float curVal = position.y();
797                                                         insert_vert_ipo(icu1, frameNumber, curVal);
798 #ifdef TEST_HANDLES_GAME2IPO
799
800                                                         testhandles_ipocurve(icu1);
801 #endif
802                                                 }
803                                                 icu1 = findIpoCurve((IpoCurve *)ipo->curve.first,"LocZ");
804                                                 if (icu1)
805                                                 {
806                                                         float curVal = position.z();
807                                                         insert_vert_ipo(icu1, frameNumber, curVal);
808 #ifdef TEST_HANDLES_GAME2IPO
809                                                         testhandles_ipocurve(icu1);
810 #endif
811                                                 }
812                                                 icu1 = findIpoCurve((IpoCurve *)ipo->curve.first,"RotX");
813                                                 if (icu1)
814                                                 {
815                                                         float curVal = eulerAngles[0];
816                                                         insert_vert_ipo(icu1, frameNumber, curVal);
817 #ifdef TEST_HANDLES_GAME2IPO
818
819                                                         testhandles_ipocurve(icu1);
820 #endif
821                                                 }
822                                                 icu1 = findIpoCurve((IpoCurve *)ipo->curve.first,"RotY");
823                                                 if (icu1)
824                                                 {
825                                                         float curVal = eulerAngles[1];
826                                                         insert_vert_ipo(icu1, frameNumber, curVal);
827 #ifdef TEST_HANDLES_GAME2IPO
828
829                                                         testhandles_ipocurve(icu1);
830 #endif
831                                                 }
832                                                 icu1 = findIpoCurve((IpoCurve *)ipo->curve.first,"RotZ");
833                                                 if (icu1)
834                                                 {
835                                                         float curVal = eulerAngles[2];
836                                                         insert_vert_ipo(icu1, frameNumber, curVal);
837 #ifdef TEST_HANDLES_GAME2IPO
838                                                         
839                                                         testhandles_ipocurve(icu1);
840 #endif
841
842                                                 }
843
844                                         }
845                                 }
846                         }
847
848                 }
849                 
850         
851         }       
852         
853
854 }
855
856
857 void    KX_BlenderSceneConverter::TestHandlesPhysicsObjectToAnimationIpo()
858 {
859
860         KX_SceneList* scenes = m_ketsjiEngine->CurrentScenes();
861         int numScenes = scenes->size();
862         int i;
863         for (i=0;i<numScenes;i++)
864         {
865                 KX_Scene* scene = scenes->at(i);
866                 //PHY_IPhysicsEnvironment* physEnv = scene->GetPhysicsEnvironment();
867                 CListValue* parentList = scene->GetRootParentList();
868                 int numObjects = parentList->GetCount();
869                 int g;
870                 for (g=0;g<numObjects;g++)
871                 {
872                         KX_GameObject* gameObj = (KX_GameObject*)parentList->GetValue(g);
873                         if (gameObj->IsDynamic())
874                         {
875                                 KX_IPhysicsController* physCtrl = gameObj->GetPhysicsController();
876                                 
877                                 Object* blenderObject = FindBlenderObject(gameObj);
878                                 if (blenderObject)
879                                 {
880
881                                         const MT_Matrix3x3& orn = gameObj->NodeGetWorldOrientation();
882                                         float eulerAngles[3];   
883                                         float tmat[3][3];
884                                         for (int r=0;r<3;r++)
885                                         {
886                                                 for (int c=0;c<3;c++)
887                                                 {
888                                                         tmat[r][c] = orn[c][r];
889                                                 }
890                                         }
891                                         Mat3ToEul(tmat, eulerAngles);
892                                         
893                                         for(int x = 0; x < 3; x++) {
894                                                 eulerAngles[x] *= (float) (180 / 3.14159265f);
895                                         }
896
897                                         eulerAngles[0]/=10.f;
898                                         eulerAngles[1]/=10.f;
899                                         eulerAngles[2]/=10.f;
900
901
902
903                                         const MT_Vector3& scale = gameObj->NodeGetWorldScaling();
904                                         const MT_Point3& position = gameObj->NodeGetWorldPosition();
905                                         
906                                         Ipo* ipo = blenderObject->ipo;
907                                         if (ipo)
908                                         {
909
910                                                 //create the curves, if not existing
911
912                                         IpoCurve *icu1 = findIpoCurve((IpoCurve *)ipo->curve.first,"LocX");
913                                         if (!icu1)
914                                                 icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, OB_LOC_X);
915                                         
916                                         icu1 = findIpoCurve((IpoCurve *)ipo->curve.first,"LocY");
917                                         if (!icu1)
918                                                 icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, OB_LOC_Y);
919                                         
920                                         icu1 = findIpoCurve((IpoCurve *)ipo->curve.first,"LocZ");
921                                         if (!icu1)
922                                                 icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, OB_LOC_Z);
923
924                                         icu1 = findIpoCurve((IpoCurve *)ipo->curve.first,"RotX");
925                                         if (!icu1)
926                                                 icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, OB_ROT_X);
927
928                                         icu1 = findIpoCurve((IpoCurve *)ipo->curve.first,"RotY");
929                                         if (!icu1)
930                                                 icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, OB_ROT_Y);
931
932                                         icu1 = findIpoCurve((IpoCurve *)ipo->curve.first,"RotZ");
933                                         if (!icu1)
934                                                 icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, OB_ROT_Z);
935
936
937
938                                         //fill the curves with data
939
940                                                 icu1 = findIpoCurve((IpoCurve *)ipo->curve.first,"LocX");
941                                                 if (icu1)
942                                                 {
943                                                         testhandles_ipocurve(icu1);
944                                                 }
945                                                 icu1 = findIpoCurve((IpoCurve *)ipo->curve.first,"LocY");
946                                                 if (icu1)
947                                                 {
948                                                         testhandles_ipocurve(icu1);
949                                                 }
950                                                 icu1 = findIpoCurve((IpoCurve *)ipo->curve.first,"LocZ");
951                                                 if (icu1)
952                                                 {
953                                                         testhandles_ipocurve(icu1);
954                                                 }
955                                                 icu1 = findIpoCurve((IpoCurve *)ipo->curve.first,"RotX");
956                                                 if (icu1)
957                                                 {
958                                                         testhandles_ipocurve(icu1);
959                                                 }
960                                                 icu1 = findIpoCurve((IpoCurve *)ipo->curve.first,"RotY");
961                                                 if (icu1)
962                                                 {
963                                                         testhandles_ipocurve(icu1);
964                                                 }
965                                                 icu1 = findIpoCurve((IpoCurve *)ipo->curve.first,"RotZ");
966                                                 if (icu1)
967                                                 {
968                                                         testhandles_ipocurve(icu1);
969                                                 }
970
971                                         }
972                                 }
973                         }
974
975                 }
976                 
977         
978         }
979
980
981
982 }