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