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