synched with trunk at revision 31065
[blender.git] / source / gameengine / Ketsji / KX_KetsjiEngine.cpp
1 /*
2  * $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19  *
20  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
21  * All rights reserved.
22  *
23  * The Original Code is: all of this file.
24  *
25  * Contributor(s): none yet.
26  *
27  * ***** END GPL LICENSE BLOCK *****
28  * The engine ties all game modules together. 
29  */
30
31 #ifdef WIN32
32 #pragma warning (disable : 4786)
33 #endif //WIN32
34
35 #include <iostream>
36
37 #include "KX_KetsjiEngine.h"
38
39 #include "ListValue.h"
40 #include "IntValue.h"
41 #include "VectorValue.h"
42 #include "BoolValue.h"
43 #include "FloatValue.h"
44
45 #define KX_NUM_ITERATIONS 4
46 #include "RAS_BucketManager.h"
47 #include "RAS_Rect.h"
48 #include "RAS_IRasterizer.h"
49 #include "RAS_IRenderTools.h"
50 #include "RAS_ICanvas.h"
51 #include "STR_String.h"
52 #include "MT_Vector3.h"
53 #include "MT_Transform.h"
54 #include "SCA_IInputDevice.h"
55 #include "KX_Scene.h"
56 #include "MT_CmMatrix4x4.h"
57 #include "KX_Camera.h"
58 #include "KX_Dome.h"
59 #include "KX_Light.h"
60 #include "KX_PythonInit.h"
61 #include "KX_PyConstraintBinding.h"
62 #include "PHY_IPhysicsEnvironment.h"
63
64 #include "AUD_C-API.h"
65
66 #include "NG_NetworkScene.h"
67 #include "NG_NetworkDeviceInterface.h"
68
69 #include "KX_WorldInfo.h"
70 #include "KX_ISceneConverter.h"
71 #include "KX_TimeCategoryLogger.h"
72
73 #include "RAS_FramingManager.h"
74 #include "stdio.h"
75 #include "DNA_world_types.h"
76 #include "DNA_scene_types.h"
77
78 #include "KX_NavMeshObject.h"
79
80 // If define: little test for Nzc: guarded drawing. If the canvas is
81 // not valid, skip rendering this frame.
82 //#define NZC_GUARDED_OUTPUT
83 #define DEFAULT_LOGIC_TIC_RATE 60.0
84 #define DEFAULT_PHYSICS_TIC_RATE 60.0
85
86 const char KX_KetsjiEngine::m_profileLabels[tc_numCategories][15] = {
87         "Physics:",             // tc_physics
88         "Logic",                // tc_logic
89         "Network:",             // tc_network
90         "Scenegraph:",  // tc_scenegraph
91         "Sound:",               // tc_sound
92         "Rasterizer:",  // tc_rasterizer
93         "Services:",    // tc_services
94         "Overhead:",    // tc_overhead
95         "Outside:"              // tc_outside
96 };
97
98 double KX_KetsjiEngine::m_ticrate = DEFAULT_LOGIC_TIC_RATE;
99 int        KX_KetsjiEngine::m_maxLogicFrame = 5;
100 int        KX_KetsjiEngine::m_maxPhysicsFrame = 5;
101 double KX_KetsjiEngine::m_anim_framerate = 25.0;
102 double KX_KetsjiEngine::m_suspendedtime = 0.0;
103 double KX_KetsjiEngine::m_suspendeddelta = 0.0;
104 double KX_KetsjiEngine::m_average_framerate = 0.0;
105
106
107 /**
108  *      Constructor of the Ketsji Engine
109  */
110 KX_KetsjiEngine::KX_KetsjiEngine(KX_ISystem* system)
111      :  m_canvas(NULL),
112         m_rasterizer(NULL),
113         m_kxsystem(system),
114         m_rendertools(NULL),
115         m_sceneconverter(NULL),
116         m_networkdevice(NULL),
117 #ifndef DISABLE_PYTHON
118         m_pythondictionary(NULL),
119 #endif
120         m_keyboarddevice(NULL),
121         m_mousedevice(NULL),
122
123         m_propertiesPresent(false),
124
125         m_bInitialized(false),
126         m_activecam(0),
127         m_bFixedTime(false),
128         
129         m_firstframe(true),
130         
131         m_frameTime(0.f),
132         m_clockTime(0.f),
133         m_previousClockTime(0.f),
134
135
136         m_exitcode(KX_EXIT_REQUEST_NO_REQUEST),
137         m_exitstring(""),
138         
139         m_drawingmode(5),
140         m_cameraZoom(1.0),
141         
142         m_overrideCam(false),
143         m_overrideCamUseOrtho(false),
144         m_overrideCamNear(0.0),
145         m_overrideCamFar(0.0),
146
147         m_stereo(false),
148         m_curreye(0),
149
150         m_logger(NULL),
151         
152         // Set up timing info display variables
153         m_show_framerate(false),
154         m_show_profile(false),
155         m_showProperties(false),
156         m_showBackground(false),
157         m_show_debug_properties(false),
158
159         m_animation_record(false),
160
161         // Default behavior is to hide the cursor every frame.
162         m_hideCursor(false),
163
164         m_overrideFrameColor(false),
165         m_overrideFrameColorR(0.0),
166         m_overrideFrameColorG(0.0),
167         m_overrideFrameColorB(0.0),
168
169         m_usedome(false)
170 {
171         // Initialize the time logger
172         m_logger = new KX_TimeCategoryLogger (25);
173
174         for (int i = tc_first; i < tc_numCategories; i++)
175                 m_logger->AddCategory((KX_TimeCategory)i);
176                 
177 }
178
179
180
181 /**
182  *      Destructor of the Ketsji Engine, release all memory
183  */
184 KX_KetsjiEngine::~KX_KetsjiEngine()
185 {
186         delete m_logger;
187         if(m_usedome)
188                 delete m_dome;
189 }
190
191
192
193 void KX_KetsjiEngine::SetKeyboardDevice(SCA_IInputDevice* keyboarddevice)
194 {
195         MT_assert(keyboarddevice);
196         m_keyboarddevice = keyboarddevice;
197 }
198
199
200
201 void KX_KetsjiEngine::SetMouseDevice(SCA_IInputDevice* mousedevice)
202 {
203         MT_assert(mousedevice);
204         m_mousedevice = mousedevice;
205 }
206
207
208
209 void KX_KetsjiEngine::SetNetworkDevice(NG_NetworkDeviceInterface* networkdevice)
210 {
211         MT_assert(networkdevice);
212         m_networkdevice = networkdevice;
213 }
214
215
216 void KX_KetsjiEngine::SetCanvas(RAS_ICanvas* canvas)
217 {
218         MT_assert(canvas);
219         m_canvas = canvas;
220 }
221
222
223
224 void KX_KetsjiEngine::SetRenderTools(RAS_IRenderTools* rendertools)
225 {
226         MT_assert(rendertools);
227         m_rendertools = rendertools;
228 }
229
230
231
232 void KX_KetsjiEngine::SetRasterizer(RAS_IRasterizer* rasterizer)
233 {
234         MT_assert(rasterizer);
235         m_rasterizer = rasterizer;
236 }
237
238 #ifndef DISABLE_PYTHON
239 /*
240  * At the moment the GameLogic module is imported into 'pythondictionary' after this function is called.
241  * if this function ever changes to assign a copy, make sure the game logic module is imported into this dictionary before hand.
242  */
243 void KX_KetsjiEngine::SetPyNamespace(PyObject* pythondictionary)
244 {
245         MT_assert(pythondictionary);
246         m_pythondictionary = pythondictionary;
247 }
248 #endif
249
250
251 void KX_KetsjiEngine::SetSceneConverter(KX_ISceneConverter* sceneconverter)
252 {
253         MT_assert(sceneconverter);
254         m_sceneconverter = sceneconverter;
255 }
256
257 void KX_KetsjiEngine::InitDome(short res, short mode, short angle, float resbuf, short tilt, struct Text* text)
258 {
259         m_dome = new KX_Dome(m_canvas, m_rasterizer, m_rendertools,this, res, mode, angle, resbuf, tilt, text);
260         m_usedome = true;
261 }
262
263 void KX_KetsjiEngine::RenderDome()
264 {
265         GLuint  viewport[4]={0};
266         glGetIntegerv(GL_VIEWPORT,(GLint *)viewport);
267         
268         m_dome->SetViewPort(viewport);
269
270         KX_Scene* firstscene = *m_scenes.begin();
271         const RAS_FrameSettings &framesettings = firstscene->GetFramingType();
272
273         m_logger->StartLog(tc_rasterizer, m_kxsystem->GetTimeInSeconds(), true);
274
275         // hiding mouse cursor each frame
276         // (came back when going out of focus and then back in again)
277         if (m_hideCursor)
278                 m_canvas->SetMouseState(RAS_ICanvas::MOUSE_INVISIBLE);
279
280         // clear the entire game screen with the border color
281         // only once per frame
282
283         m_canvas->BeginDraw();
284
285         // BeginFrame() sets the actual drawing area. You can use a part of the window
286         if (!BeginFrame())
287                 return;
288
289         KX_SceneList::iterator sceneit;
290         KX_Scene* scene;
291
292         int n_renders=m_dome->GetNumberRenders();// usually 4 or 6
293         for (int i=0;i<n_renders;i++){
294                 m_canvas->ClearBuffer(RAS_ICanvas::COLOR_BUFFER|RAS_ICanvas::DEPTH_BUFFER);
295                 for (sceneit = m_scenes.begin();sceneit != m_scenes.end(); sceneit++)
296                 // for each scene, call the proceed functions
297                 {
298                         scene = *sceneit;
299                         KX_Camera* cam = scene->GetActiveCamera();
300
301                         m_rendertools->BeginFrame(m_rasterizer);
302                         // pass the scene's worldsettings to the rasterizer
303                         SetWorldSettings(scene->GetWorldInfo());
304
305                         // shadow buffers
306                         if (i == 0){
307                                 RenderShadowBuffers(scene);
308                         }
309                         // Avoid drawing the scene with the active camera twice when it's viewport is enabled
310                         if(cam && !cam->GetViewport())
311                         {
312                                 if (scene->IsClearingZBuffer())
313                                         m_rasterizer->ClearDepthBuffer();
314                 
315                                 m_rendertools->SetAuxilaryClientInfo(scene);
316                 
317                                 // do the rendering
318                                 m_dome->RenderDomeFrame(scene,cam, i);
319                         }
320                         
321                         list<class KX_Camera*>* cameras = scene->GetCameras();
322                         
323                         // Draw the scene once for each camera with an enabled viewport
324                         list<KX_Camera*>::iterator it = cameras->begin();
325                         while(it != cameras->end())
326                         {
327                                 if((*it)->GetViewport())
328                                 {
329                                         if (scene->IsClearingZBuffer())
330                                                 m_rasterizer->ClearDepthBuffer();
331                         
332                                         m_rendertools->SetAuxilaryClientInfo(scene);
333                         
334                                         // do the rendering
335                                         m_dome->RenderDomeFrame(scene, (*it),i);
336                                 }
337                                 
338                                 it++;
339                         }
340                         // Part of PostRenderScene()
341                         m_rendertools->MotionBlur(m_rasterizer);
342                         scene->Render2DFilters(m_canvas);
343                         // no RunDrawingCallBacks
344                         // no FlushDebugShapes
345                 }
346                 m_dome->BindImages(i);
347         }       
348
349         m_canvas->EndFrame();//XXX do we really need that?
350
351         m_canvas->SetViewPort(0, 0, m_canvas->GetWidth(), m_canvas->GetHeight());
352
353         if (m_overrideFrameColor) //XXX why do we want
354         {
355                 // Do not use the framing bar color set in the Blender scenes
356                 m_canvas->ClearColor(
357                         m_overrideFrameColorR,
358                         m_overrideFrameColorG,
359                         m_overrideFrameColorB,
360                         1.0
361                         );
362         }
363         else
364         {
365                 // Use the framing bar color set in the Blender scenes
366                 m_canvas->ClearColor(
367                         framesettings.BarRed(),
368                         framesettings.BarGreen(),
369                         framesettings.BarBlue(),
370                         1.0
371                         );
372         }
373         m_dome->Draw();
374         // Draw Callback for the last scene
375 #ifndef DISABLE_PYTHON
376         scene->RunDrawingCallbacks(scene->GetPostDrawCB());
377 #endif  
378         EndFrame();
379 }
380
381 /**
382  * Ketsji Init(), Initializes datastructures and converts data from
383  * Blender into Ketsji native (realtime) format also sets up the
384  * graphics context
385  */
386 void KX_KetsjiEngine::StartEngine(bool clearIpo)
387 {
388         m_clockTime = m_kxsystem->GetTimeInSeconds();
389         m_frameTime = m_kxsystem->GetTimeInSeconds();
390         m_previousClockTime = m_kxsystem->GetTimeInSeconds();
391
392         m_firstframe = true;
393         m_bInitialized = true;
394         // there is always one scene enabled at startup
395         Scene* scene = m_scenes[0]->GetBlenderScene();
396         if (scene)
397         {
398                 m_ticrate = scene->gm.ticrate ? scene->gm.ticrate : DEFAULT_LOGIC_TIC_RATE;
399                 m_maxLogicFrame = scene->gm.maxlogicstep ? scene->gm.maxlogicstep : 5;
400                 m_maxPhysicsFrame = scene->gm.maxphystep ? scene->gm.maxlogicstep : 5;
401         }
402         else
403         {
404                 m_ticrate = DEFAULT_LOGIC_TIC_RATE;
405                 m_maxLogicFrame = 5;
406                 m_maxPhysicsFrame = 5;
407         }
408         
409         if (m_animation_record)
410         {
411                 m_sceneconverter->ResetPhysicsObjectsAnimationIpo(clearIpo);
412                 m_sceneconverter->WritePhysicsObjectToAnimationIpo(m_currentFrame);
413         }
414
415 }
416
417 void KX_KetsjiEngine::ClearFrame()
418 {
419         // clear unless we're drawing overlapping stereo
420         if(m_rasterizer->InterlacedStereo() &&
421                 m_rasterizer->GetEye() == RAS_IRasterizer::RAS_STEREO_RIGHTEYE)
422                 return;
423
424         // clear the viewports with the background color of the first scene
425         bool doclear = false;
426         KX_SceneList::iterator sceneit;
427         RAS_Rect clearvp, area, viewport;
428
429         for (sceneit = m_scenes.begin(); sceneit != m_scenes.end(); sceneit++)
430         {
431                 KX_Scene* scene = *sceneit;
432                 //const RAS_FrameSettings &framesettings = scene->GetFramingType();
433                 list<class KX_Camera*>* cameras = scene->GetCameras();
434
435                 list<KX_Camera*>::iterator it;
436                 for(it = cameras->begin(); it != cameras->end(); it++)
437                 {
438                         GetSceneViewport(scene, (*it), area, viewport);
439
440                         if(!doclear) {
441                                 clearvp = viewport;
442                                 doclear = true;
443                         }
444                         else {
445                                 if(viewport.GetLeft() < clearvp.GetLeft())
446                                         clearvp.SetLeft(viewport.GetLeft());
447                                 if(viewport.GetBottom() < clearvp.GetBottom())
448                                         clearvp.SetBottom(viewport.GetBottom());
449                                 if(viewport.GetRight() > clearvp.GetRight())
450                                         clearvp.SetRight(viewport.GetRight());
451                                 if(viewport.GetTop() > clearvp.GetTop())
452                                         clearvp.SetTop(viewport.GetTop());
453
454                         }
455                 }
456         }
457
458         if(doclear) {
459                 KX_Scene* firstscene = *m_scenes.begin();
460                 SetBackGround(firstscene->GetWorldInfo());
461
462                 m_canvas->SetViewPort(clearvp.GetLeft(), clearvp.GetBottom(),
463                         clearvp.GetRight(), clearvp.GetTop());  
464                 m_rasterizer->ClearColorBuffer();
465         }
466 }
467
468 bool KX_KetsjiEngine::BeginFrame()
469 {
470         // set the area used for rendering (stereo can assign only a subset)
471         m_rasterizer->SetRenderArea();
472
473         if (m_canvas->BeginDraw())
474         {
475                 ClearFrame();
476
477                 m_rasterizer->BeginFrame(m_drawingmode , m_kxsystem->GetTimeInSeconds());
478                 m_rendertools->BeginFrame(m_rasterizer);
479
480                 return true;
481         }
482         
483         return false;
484 }               
485
486
487 void KX_KetsjiEngine::EndFrame()
488 {
489         // Show profiling info
490         m_logger->StartLog(tc_overhead, m_kxsystem->GetTimeInSeconds(), true);
491         if (m_show_framerate || m_show_profile || (m_show_debug_properties && m_propertiesPresent))
492         {
493                 RenderDebugProperties();
494         }
495
496         m_average_framerate = m_logger->GetAverage();
497         if (m_average_framerate < 1e-6)
498                 m_average_framerate = 1e-6;
499         m_average_framerate = 1.0/m_average_framerate;
500
501         // Go to next profiling measurement, time spend after this call is shown in the next frame.
502         m_logger->NextMeasurement(m_kxsystem->GetTimeInSeconds());
503
504         m_logger->StartLog(tc_rasterizer, m_kxsystem->GetTimeInSeconds(), true);
505         m_rasterizer->EndFrame();
506         // swap backbuffer (drawing into this buffer) <-> front/visible buffer
507         m_rasterizer->SwapBuffers();
508         m_rendertools->EndFrame(m_rasterizer);
509
510         
511         m_canvas->EndDraw();
512 }
513
514 //#include "PIL_time.h"
515 //#include "LinearMath/btQuickprof.h"
516
517
518 bool KX_KetsjiEngine::NextFrame()
519 {
520         double timestep = 1.0/m_ticrate;
521         double framestep = timestep;
522 //      static hidden::Clock sClock;
523
524 m_logger->StartLog(tc_services, m_kxsystem->GetTimeInSeconds(),true);
525
526 //float dt = sClock.getTimeMicroseconds() * 0.000001f;
527 //sClock.reset();
528
529 if (m_bFixedTime)
530         m_clockTime += timestep;
531 else
532 {
533
534 //      m_clockTime += dt;
535         m_clockTime = m_kxsystem->GetTimeInSeconds();
536 }
537         
538         double deltatime = m_clockTime - m_frameTime;
539         if (deltatime<0.f)
540         {
541                 printf("problem with clock\n");
542                 deltatime = 0.f;
543                 m_clockTime = 0.f;
544                 m_frameTime = 0.f;
545         }
546
547
548         // Compute the number of logic frames to do each update (fixed tic bricks)
549         int frames =int(deltatime*m_ticrate+1e-6);
550 //      if (frames>1)
551 //              printf("****************************************");
552 //      printf("dt = %f, deltatime = %f, frames = %d\n",dt, deltatime,frames);
553         
554 //      if (!frames)
555 //              PIL_sleep_ms(1);
556         
557         KX_SceneList::iterator sceneit;
558         
559         if (frames>m_maxPhysicsFrame)
560         {
561         
562         //      printf("framedOut: %d\n",frames);
563                 m_frameTime+=(frames-m_maxPhysicsFrame)*timestep;
564                 frames = m_maxPhysicsFrame;
565         }
566         
567
568         bool doRender = frames>0;
569
570         if (frames > m_maxLogicFrame)
571         {
572                 framestep = (frames*timestep)/m_maxLogicFrame;
573                 frames = m_maxLogicFrame;
574         }
575                 
576         while (frames)
577         {
578         
579
580                 m_frameTime += framestep;
581                 
582                 for (sceneit = m_scenes.begin();sceneit != m_scenes.end(); ++sceneit)
583                 // for each scene, call the proceed functions
584                 {
585                         KX_Scene* scene = *sceneit;
586         
587                         /* Suspension holds the physics and logic processing for an
588                         * entire scene. Objects can be suspended individually, and
589                         * the settings for that preceed the logic and physics
590                         * update. */
591                         m_logger->StartLog(tc_logic, m_kxsystem->GetTimeInSeconds(), true);
592
593                         m_sceneconverter->resetNoneDynamicObjectToIpo();//this is for none dynamic objects with ipo
594
595                         scene->UpdateObjectActivity();
596         
597                         if (!scene->IsSuspended())
598                         {
599                                 // if the scene was suspended recalcutlate the delta tu "curtime"
600                                 m_suspendedtime = scene->getSuspendedTime();
601                                 if (scene->getSuspendedTime()!=0.0)
602                                         scene->setSuspendedDelta(scene->getSuspendedDelta()+m_clockTime-scene->getSuspendedTime());
603                                 m_suspendeddelta = scene->getSuspendedDelta();
604
605                                 
606                                 m_logger->StartLog(tc_network, m_kxsystem->GetTimeInSeconds(), true);
607                                 SG_SetActiveStage(SG_STAGE_NETWORK);
608                                 scene->GetNetworkScene()->proceed(m_frameTime);
609         
610                                 //m_logger->StartLog(tc_scenegraph, m_kxsystem->GetTimeInSeconds(), true);
611                                 //SG_SetActiveStage(SG_STAGE_NETWORK_UPDATE);
612                                 //scene->UpdateParents(m_frameTime);
613                                 
614                                 m_logger->StartLog(tc_physics, m_kxsystem->GetTimeInSeconds(), true);
615                                 SG_SetActiveStage(SG_STAGE_PHYSICS1);
616                                 // set Python hooks for each scene
617 #ifndef DISABLE_PYTHON
618                                 PHY_SetActiveEnvironment(scene->GetPhysicsEnvironment());
619 #endif
620                                 KX_SetActiveScene(scene);
621         
622                                 scene->GetPhysicsEnvironment()->endFrame();
623                                 
624                                 // Update scenegraph after physics step. This maps physics calculations
625                                 // into node positions.         
626                                 //m_logger->StartLog(tc_scenegraph, m_kxsystem->GetTimeInSeconds(), true);
627                                 //SG_SetActiveStage(SG_STAGE_PHYSICS1_UPDATE);
628                                 //scene->UpdateParents(m_frameTime);
629                                 
630                                 // Process sensors, and controllers
631                                 m_logger->StartLog(tc_logic, m_kxsystem->GetTimeInSeconds(), true);
632                                 SG_SetActiveStage(SG_STAGE_CONTROLLER);
633                                 scene->LogicBeginFrame(m_frameTime);
634         
635                                 // Scenegraph needs to be updated again, because Logic Controllers 
636                                 // can affect the local matrices.
637                                 m_logger->StartLog(tc_scenegraph, m_kxsystem->GetTimeInSeconds(), true);
638                                 SG_SetActiveStage(SG_STAGE_CONTROLLER_UPDATE);
639                                 scene->UpdateParents(m_frameTime);
640         
641                                 // Process actuators
642         
643                                 // Do some cleanup work for this logic frame
644                                 m_logger->StartLog(tc_logic, m_kxsystem->GetTimeInSeconds(), true);
645                                 SG_SetActiveStage(SG_STAGE_ACTUATOR);
646                                 scene->LogicUpdateFrame(m_frameTime, true);
647                                 
648                                 scene->LogicEndFrame();
649         
650                                 // Actuators can affect the scenegraph
651                                 m_logger->StartLog(tc_scenegraph, m_kxsystem->GetTimeInSeconds(), true);
652                                 SG_SetActiveStage(SG_STAGE_ACTUATOR_UPDATE);
653                                 scene->UpdateParents(m_frameTime);
654                                 
655                                 m_logger->StartLog(tc_physics, m_kxsystem->GetTimeInSeconds(), true);
656                                 SG_SetActiveStage(SG_STAGE_PHYSICS2);
657                                 scene->GetPhysicsEnvironment()->beginFrame();
658                 
659                                 // Perform physics calculations on the scene. This can involve 
660                                 // many iterations of the physics solver.
661                                 scene->GetPhysicsEnvironment()->proceedDeltaTime(m_frameTime,timestep,framestep);//m_deltatimerealDeltaTime);
662
663                                 m_logger->StartLog(tc_scenegraph, m_kxsystem->GetTimeInSeconds(), true);
664                                 SG_SetActiveStage(SG_STAGE_PHYSICS2_UPDATE);
665                                 scene->UpdateParents(m_frameTime);
666                         
667                         
668                                 if (m_animation_record)
669                                 {                                       
670                                         m_sceneconverter->WritePhysicsObjectToAnimationIpo(++m_currentFrame);
671                                 }
672
673                                 scene->setSuspendedTime(0.0);
674                         } // suspended
675                         else
676                                 if(scene->getSuspendedTime()==0.0)
677                                         scene->setSuspendedTime(m_clockTime);
678         
679                         DoSound(scene);
680                         
681                         m_logger->StartLog(tc_services, m_kxsystem->GetTimeInSeconds(), true);
682                 }
683
684                 // update system devices
685                 m_logger->StartLog(tc_logic, m_kxsystem->GetTimeInSeconds(), true);
686                 if (m_keyboarddevice)
687                         m_keyboarddevice->NextFrame();
688         
689                 if (m_mousedevice)
690                         m_mousedevice->NextFrame();
691                 
692                 if (m_networkdevice)
693                         m_networkdevice->NextFrame();
694
695                 // scene management
696                 ProcessScheduledScenes();
697                 
698                 frames--;
699         }
700
701         bool bUseAsyncLogicBricks= false;//true;
702
703         if (bUseAsyncLogicBricks)
704         {       
705                 // Logic update sub frame: this will let some logic bricks run at the
706                 // full frame rate.
707                 for (sceneit = m_scenes.begin();sceneit != m_scenes.end(); ++sceneit)
708                 // for each scene, call the proceed functions
709                 {
710                         KX_Scene* scene = *sceneit;
711
712                         if (!scene->IsSuspended())
713                         {
714                                 // if the scene was suspended recalcutlate the delta tu "curtime"
715                                 m_suspendedtime = scene->getSuspendedTime();
716                                 if (scene->getSuspendedTime()!=0.0)
717                                         scene->setSuspendedDelta(scene->getSuspendedDelta()+m_clockTime-scene->getSuspendedTime());
718                                 m_suspendeddelta = scene->getSuspendedDelta();
719                                 
720                                 // set Python hooks for each scene
721 #ifndef DISABLE_PYTHON
722                                 PHY_SetActiveEnvironment(scene->GetPhysicsEnvironment());
723 #endif
724                                 KX_SetActiveScene(scene);
725                                 
726                                 m_logger->StartLog(tc_scenegraph, m_kxsystem->GetTimeInSeconds(), true);
727                                 SG_SetActiveStage(SG_STAGE_PHYSICS1);
728                                 scene->UpdateParents(m_clockTime);
729
730                                 // Perform physics calculations on the scene. This can involve 
731                                 // many iterations of the physics solver.
732                                 m_logger->StartLog(tc_physics, m_kxsystem->GetTimeInSeconds(), true);
733                                 scene->GetPhysicsEnvironment()->proceedDeltaTime(m_clockTime,timestep,timestep);
734                                 // Update scenegraph after physics step. This maps physics calculations
735                                 // into node positions.         
736                                 m_logger->StartLog(tc_scenegraph, m_kxsystem->GetTimeInSeconds(), true);
737                                 SG_SetActiveStage(SG_STAGE_PHYSICS2);
738                                 scene->UpdateParents(m_clockTime);
739                                 
740                                 // Do some cleanup work for this logic frame
741                                 m_logger->StartLog(tc_logic, m_kxsystem->GetTimeInSeconds(), true);
742                                 scene->LogicUpdateFrame(m_clockTime, false);
743
744                                 // Actuators can affect the scenegraph
745                                 m_logger->StartLog(tc_scenegraph, m_kxsystem->GetTimeInSeconds(), true);
746                                 SG_SetActiveStage(SG_STAGE_ACTUATOR);
747                                 scene->UpdateParents(m_clockTime);
748                                  
749                                 scene->setSuspendedTime(0.0);
750                         } // suspended
751                         else
752                                 if(scene->getSuspendedTime()==0.0)
753                                         scene->setSuspendedTime(m_clockTime);
754
755                         DoSound(scene);
756
757                         m_logger->StartLog(tc_services, m_kxsystem->GetTimeInSeconds(), true);
758                 }
759         }
760
761
762         m_previousClockTime = m_clockTime;
763         
764         // Start logging time spend outside main loop
765         m_logger->StartLog(tc_outside, m_kxsystem->GetTimeInSeconds(), true);
766         
767         return doRender;
768 }
769
770
771
772 void KX_KetsjiEngine::Render()
773 {
774         if(m_usedome){
775                 RenderDome();
776                 return;
777         }
778         KX_Scene* firstscene = *m_scenes.begin();
779         const RAS_FrameSettings &framesettings = firstscene->GetFramingType();
780
781         m_logger->StartLog(tc_rasterizer, m_kxsystem->GetTimeInSeconds(), true);
782         SG_SetActiveStage(SG_STAGE_RENDER);
783
784         // hiding mouse cursor each frame
785         // (came back when going out of focus and then back in again)
786         if (m_hideCursor)
787                 m_canvas->SetMouseState(RAS_ICanvas::MOUSE_INVISIBLE);
788
789         // clear the entire game screen with the border color
790         // only once per frame
791         m_canvas->BeginDraw();
792         if (m_drawingmode == RAS_IRasterizer::KX_TEXTURED) {
793                 m_canvas->SetViewPort(0, 0, m_canvas->GetWidth(), m_canvas->GetHeight());
794                 if (m_overrideFrameColor)
795                 {
796                         // Do not use the framing bar color set in the Blender scenes
797                         m_canvas->ClearColor(
798                                 m_overrideFrameColorR,
799                                 m_overrideFrameColorG,
800                                 m_overrideFrameColorB,
801                                 1.0
802                                 );
803                 }
804                 else
805                 {
806                         // Use the framing bar color set in the Blender scenes
807                         m_canvas->ClearColor(
808                                 framesettings.BarRed(),
809                                 framesettings.BarGreen(),
810                                 framesettings.BarBlue(),
811                                 1.0
812                                 );
813                 }
814                 // clear the -whole- viewport
815                 m_canvas->ClearBuffer(RAS_ICanvas::COLOR_BUFFER|RAS_ICanvas::DEPTH_BUFFER);
816         }
817
818         m_rasterizer->SetEye(RAS_IRasterizer::RAS_STEREO_LEFTEYE);
819
820         // BeginFrame() sets the actual drawing area. You can use a part of the window
821         if (!BeginFrame())
822                 return;
823
824         KX_SceneList::iterator sceneit;
825         for (sceneit = m_scenes.begin();sceneit != m_scenes.end(); sceneit++)
826         // for each scene, call the proceed functions
827         {
828                 KX_Scene* scene = *sceneit;
829                 KX_Camera* cam = scene->GetActiveCamera();
830                 // pass the scene's worldsettings to the rasterizer
831                 SetWorldSettings(scene->GetWorldInfo());
832
833                 // this is now done incrementatlly in KX_Scene::CalculateVisibleMeshes
834                 //scene->UpdateMeshTransformations();
835
836                 // shadow buffers
837                 RenderShadowBuffers(scene);
838
839                 // Avoid drawing the scene with the active camera twice when it's viewport is enabled
840                 if(cam && !cam->GetViewport())
841                 {
842                         if (scene->IsClearingZBuffer())
843                                 m_rasterizer->ClearDepthBuffer();
844         
845                         m_rendertools->SetAuxilaryClientInfo(scene);
846         
847                         // do the rendering
848                         RenderFrame(scene, cam);
849                 }
850                 
851                 list<class KX_Camera*>* cameras = scene->GetCameras();
852                 
853                 // Draw the scene once for each camera with an enabled viewport
854                 list<KX_Camera*>::iterator it = cameras->begin();
855                 while(it != cameras->end())
856                 {
857                         if((*it)->GetViewport())
858                         {
859                                 if (scene->IsClearingZBuffer())
860                                         m_rasterizer->ClearDepthBuffer();
861                 
862                                 m_rendertools->SetAuxilaryClientInfo(scene);
863                 
864                                 // do the rendering
865                                 RenderFrame(scene, (*it));
866                         }
867                         
868                         it++;
869                 }
870                 PostRenderScene(scene);
871         }
872
873         // only one place that checks for stereo
874         if(m_rasterizer->Stereo())
875         {
876                 m_rasterizer->SetEye(RAS_IRasterizer::RAS_STEREO_RIGHTEYE);
877
878                 if (!BeginFrame())
879                         return;
880
881
882                 for (sceneit = m_scenes.begin();sceneit != m_scenes.end(); sceneit++)
883                 // for each scene, call the proceed functions
884                 {
885                         KX_Scene* scene = *sceneit;
886                         KX_Camera* cam = scene->GetActiveCamera();
887
888                         // pass the scene's worldsettings to the rasterizer
889                         SetWorldSettings(scene->GetWorldInfo());
890                 
891                         if (scene->IsClearingZBuffer())
892                                 m_rasterizer->ClearDepthBuffer();
893
894                         //pass the scene, for picking and raycasting (shadows)
895                         m_rendertools->SetAuxilaryClientInfo(scene);
896
897                         // do the rendering
898                         //RenderFrame(scene);
899                         RenderFrame(scene, cam);
900
901                         list<class KX_Camera*>* cameras = scene->GetCameras();                  
902         
903                         // Draw the scene once for each camera with an enabled viewport
904                         list<KX_Camera*>::iterator it = cameras->begin();
905                         while(it != cameras->end())
906                         {
907                                 if((*it)->GetViewport())
908                                 {
909                                         if (scene->IsClearingZBuffer())
910                                                 m_rasterizer->ClearDepthBuffer();
911                         
912                                         m_rendertools->SetAuxilaryClientInfo(scene);
913                         
914                                         // do the rendering
915                                         RenderFrame(scene, (*it));
916                                 }
917                                 
918                                 it++;
919                         }
920                         PostRenderScene(scene);
921                 }
922         } // if(m_rasterizer->Stereo())
923
924         EndFrame();
925 }
926
927
928
929 void KX_KetsjiEngine::RequestExit(int exitrequestmode)
930 {
931         m_exitcode = exitrequestmode;
932 }
933
934
935
936 void KX_KetsjiEngine::SetNameNextGame(const STR_String& nextgame)
937 {
938         m_exitstring = nextgame;
939 }
940
941
942
943 int KX_KetsjiEngine::GetExitCode()
944 {
945         // if a gameactuator has set an exitcode or if there are no scenes left
946         if (!m_exitcode)
947         {
948                 if (m_scenes.begin()==m_scenes.end())
949                         m_exitcode = KX_EXIT_REQUEST_NO_SCENES_LEFT;
950         }
951
952         return m_exitcode;
953 }
954
955
956
957 const STR_String& KX_KetsjiEngine::GetExitString()
958 {
959         return m_exitstring;
960 }
961
962
963
964 void KX_KetsjiEngine::DoSound(KX_Scene* scene)
965 {
966         m_logger->StartLog(tc_sound, m_kxsystem->GetTimeInSeconds(), true);
967
968         KX_Camera* cam = scene->GetActiveCamera();
969         if (!cam)
970                 return;
971         MT_Point3 listenerposition = cam->NodeGetWorldPosition();
972         MT_Vector3 listenervelocity = cam->GetLinearVelocity();
973         MT_Matrix3x3 listenerorientation = cam->NodeGetWorldOrientation();
974
975         {
976                 AUD_3DData data;
977                 float f;
978
979                 listenerorientation.getValue3x3(data.orientation);
980                 listenerposition.getValue(data.position);
981                 listenervelocity.getValue(data.velocity);
982
983                 f = data.position[1];
984                 data.position[1] = data.position[2];
985                 data.position[2] = -f;
986
987                 f = data.velocity[1];
988                 data.velocity[1] = data.velocity[2];
989                 data.velocity[2] = -f;
990
991                 f = data.orientation[1];
992                 data.orientation[1] = data.orientation[2];
993                 data.orientation[2] = -f;
994
995                 f = data.orientation[3];
996                 data.orientation[3] = -data.orientation[6];
997                 data.orientation[6] = f;
998
999                 f = data.orientation[4];
1000                 data.orientation[4] = -data.orientation[8];
1001                 data.orientation[8] = -f;
1002
1003                 f = data.orientation[5];
1004                 data.orientation[5] = data.orientation[7];
1005                 data.orientation[7] = f;
1006
1007                 AUD_updateListener(&data);
1008         }
1009 }
1010
1011
1012
1013 void KX_KetsjiEngine::SetBackGround(KX_WorldInfo* wi)
1014 {
1015         if (wi->hasWorld())
1016         {
1017                 if (m_drawingmode == RAS_IRasterizer::KX_TEXTURED)
1018                 {       
1019                         m_rasterizer->SetBackColor(
1020                                 wi->getBackColorRed(),
1021                                 wi->getBackColorGreen(),
1022                                 wi->getBackColorBlue(),
1023                                 0.0
1024                         );
1025                 }
1026         }
1027 }
1028
1029
1030
1031 void KX_KetsjiEngine::SetWorldSettings(KX_WorldInfo* wi)
1032 {
1033         if (wi->hasWorld())
1034         {
1035                 // ...
1036                 m_rasterizer->SetAmbientColor(
1037                         wi->getAmbientColorRed(),
1038                         wi->getAmbientColorGreen(),
1039                         wi->getAmbientColorBlue()
1040                 );
1041
1042                 if (m_drawingmode >= RAS_IRasterizer::KX_SOLID)
1043                 {       
1044                         if (wi->hasMist())
1045                         {
1046                                 m_rasterizer->SetFog(
1047                                         wi->getMistStart(),
1048                                         wi->getMistDistance(),
1049                                         wi->getMistColorRed(),
1050                                         wi->getMistColorGreen(),
1051                                         wi->getMistColorBlue()
1052                                 );
1053                         }
1054                 }
1055         }
1056 }
1057
1058
1059
1060 void KX_KetsjiEngine::SetDrawType(int drawingmode)
1061 {
1062         m_drawingmode = drawingmode;
1063 }
1064
1065
1066         
1067 void KX_KetsjiEngine::EnableCameraOverride(const STR_String& forscene)
1068 {
1069         m_overrideCam = true;
1070         m_overrideSceneName = forscene;
1071 }
1072
1073
1074
1075 void KX_KetsjiEngine::SetCameraZoom(float camzoom)
1076 {
1077         m_cameraZoom = camzoom;
1078 }
1079
1080
1081
1082 void KX_KetsjiEngine::SetCameraOverrideUseOrtho(bool useOrtho)
1083 {
1084         m_overrideCamUseOrtho = useOrtho;
1085 }
1086
1087
1088
1089 void KX_KetsjiEngine::SetCameraOverrideProjectionMatrix(const MT_CmMatrix4x4& mat)
1090 {
1091         m_overrideCamProjMat = mat;
1092 }
1093
1094
1095 void KX_KetsjiEngine::SetCameraOverrideViewMatrix(const MT_CmMatrix4x4& mat)
1096 {
1097         m_overrideCamViewMat = mat;
1098 }
1099
1100 void KX_KetsjiEngine::SetCameraOverrideClipping(float near, float far)
1101 {
1102         m_overrideCamNear = near;
1103         m_overrideCamFar = far;
1104 }
1105
1106 void KX_KetsjiEngine::SetCameraOverrideLens(float lens)
1107 {
1108         m_overrideCamLens = lens;
1109 }
1110
1111 void KX_KetsjiEngine::GetSceneViewport(KX_Scene *scene, KX_Camera* cam, RAS_Rect& area, RAS_Rect& viewport)
1112 {
1113         // In this function we make sure the rasterizer settings are upto
1114         // date. We compute the viewport so that logic
1115         // using this information is upto date.
1116
1117         // Note we postpone computation of the projection matrix
1118         // so that we are using the latest camera position.
1119         if (cam->GetViewport()) {
1120                 RAS_Rect userviewport;
1121
1122                 userviewport.SetLeft(cam->GetViewportLeft()); 
1123                 userviewport.SetBottom(cam->GetViewportBottom());
1124                 userviewport.SetRight(cam->GetViewportRight());
1125                 userviewport.SetTop(cam->GetViewportTop());
1126
1127                 // Don't do bars on user specified viewport
1128                 RAS_FrameSettings settings = scene->GetFramingType();
1129                 if(settings.FrameType() == RAS_FrameSettings::e_frame_bars)
1130                         settings.SetFrameType(RAS_FrameSettings::e_frame_extend);
1131
1132                 RAS_FramingManager::ComputeViewport(
1133                         scene->GetFramingType(),
1134                         userviewport,
1135                         viewport
1136                 );
1137
1138                 area = userviewport;
1139         }
1140         else if ( !m_overrideCam || (scene->GetName() != m_overrideSceneName) ||  m_overrideCamUseOrtho ) {
1141                 RAS_FramingManager::ComputeViewport(
1142                         scene->GetFramingType(),
1143                         m_canvas->GetDisplayArea(),
1144                         viewport
1145                 );
1146
1147                 area = m_canvas->GetDisplayArea();
1148         } else {
1149                 viewport.SetLeft(0); 
1150                 viewport.SetBottom(0);
1151                 viewport.SetRight(int(m_canvas->GetWidth()));
1152                 viewport.SetTop(int(m_canvas->GetHeight()));
1153
1154                 area = m_canvas->GetDisplayArea();
1155         }
1156 }
1157
1158 void KX_KetsjiEngine::RenderShadowBuffers(KX_Scene *scene)
1159 {
1160         CListValue *lightlist = scene->GetLightList();
1161         int i, drawmode;
1162
1163         m_rendertools->SetAuxilaryClientInfo(scene);
1164
1165         for(i=0; i<lightlist->GetCount(); i++) {
1166                 KX_GameObject *gameobj = (KX_GameObject*)lightlist->GetValue(i);
1167
1168                 KX_LightObject *light = (KX_LightObject*)gameobj;
1169
1170                 light->Update();
1171
1172                 if(m_drawingmode == RAS_IRasterizer::KX_TEXTURED && light->HasShadowBuffer()) {
1173                         /* make temporary camera */
1174                         RAS_CameraData camdata = RAS_CameraData();
1175                         KX_Camera *cam = new KX_Camera(scene, scene->m_callbacks, camdata, true, true);
1176                         cam->SetName("__shadow__cam__");
1177
1178                         MT_Transform camtrans;
1179
1180                         /* switch drawmode for speed */
1181                         drawmode = m_rasterizer->GetDrawingMode();
1182                         m_rasterizer->SetDrawingMode(RAS_IRasterizer::KX_SHADOW);
1183
1184                         /* binds framebuffer object, sets up camera .. */
1185                         light->BindShadowBuffer(m_rasterizer, cam, camtrans);
1186
1187                         /* update scene */
1188                         scene->CalculateVisibleMeshes(m_rasterizer, cam, light->GetShadowLayer());
1189
1190                         /* render */
1191                         m_rasterizer->ClearDepthBuffer();
1192                         scene->RenderBuckets(camtrans, m_rasterizer, m_rendertools);
1193
1194                         /* unbind framebuffer object, restore drawmode, free camera */
1195                         light->UnbindShadowBuffer(m_rasterizer);
1196                         m_rasterizer->SetDrawingMode(drawmode);
1197                         cam->Release();
1198                 }
1199         }
1200 }
1201         
1202 // update graphics
1203 void KX_KetsjiEngine::RenderFrame(KX_Scene* scene, KX_Camera* cam)
1204 {
1205         bool override_camera;
1206         RAS_Rect viewport, area;
1207         float nearfrust, farfrust, focallength;
1208 //      KX_Camera* cam = scene->GetActiveCamera();
1209         
1210         if (!cam)
1211                 return;
1212         GetSceneViewport(scene, cam, area, viewport);
1213
1214         // store the computed viewport in the scene
1215         scene->SetSceneViewport(viewport);      
1216
1217         // set the viewport for this frame and scene
1218         m_canvas->SetViewPort(viewport.GetLeft(), viewport.GetBottom(),
1219                 viewport.GetRight(), viewport.GetTop());        
1220         
1221         // see KX_BlenderMaterial::Activate
1222         //m_rasterizer->SetAmbient();
1223         m_rasterizer->DisplayFog();
1224
1225         override_camera = m_overrideCam && (scene->GetName() == m_overrideSceneName);
1226         override_camera = override_camera && (cam->GetName() == "__default__cam__");
1227
1228         if (override_camera && m_overrideCamUseOrtho) {
1229                 m_rasterizer->SetProjectionMatrix(m_overrideCamProjMat);
1230                 if (!cam->hasValidProjectionMatrix()) {
1231                         // needed to get frustrum planes for culling
1232                         MT_Matrix4x4 projmat;
1233                         projmat.setValue(m_overrideCamProjMat.getPointer());
1234                         cam->SetProjectionMatrix(projmat);
1235                 }
1236         } else if (cam->hasValidProjectionMatrix() && !cam->GetViewport() )
1237         {
1238                 m_rasterizer->SetProjectionMatrix(cam->GetProjectionMatrix());
1239         } else
1240         {
1241                 RAS_FrameFrustum frustum;
1242                 bool orthographic = !cam->GetCameraData()->m_perspective;
1243                 nearfrust = cam->GetCameraNear();
1244                 farfrust = cam->GetCameraFar();
1245                 focallength = cam->GetFocalLength();
1246                 MT_Matrix4x4 projmat;
1247
1248                 if(override_camera) {
1249                         nearfrust = m_overrideCamNear;
1250                         farfrust = m_overrideCamFar;
1251                 }
1252
1253                 if (orthographic) {
1254
1255                         RAS_FramingManager::ComputeOrtho(
1256                                 scene->GetFramingType(),
1257                                 area,
1258                                 viewport,
1259                                 cam->GetScale(),
1260                                 nearfrust,
1261                                 farfrust,
1262                                 frustum
1263                         );
1264                         if (!cam->GetViewport()) {
1265                                 frustum.x1 *= m_cameraZoom;
1266                                 frustum.x2 *= m_cameraZoom;
1267                                 frustum.y1 *= m_cameraZoom;
1268                                 frustum.y2 *= m_cameraZoom;
1269                         }
1270                         projmat = m_rasterizer->GetOrthoMatrix(
1271                                 frustum.x1, frustum.x2, frustum.y1, frustum.y2, frustum.camnear, frustum.camfar);
1272
1273                 } else {
1274                         RAS_FramingManager::ComputeFrustum(
1275                                 scene->GetFramingType(),
1276                                 area,
1277                                 viewport,
1278                                 cam->GetLens(),
1279                                 nearfrust,
1280                                 farfrust,
1281                                 frustum
1282                         );
1283
1284                         if (!cam->GetViewport()) {
1285                                 frustum.x1 *= m_cameraZoom;
1286                                 frustum.x2 *= m_cameraZoom;
1287                                 frustum.y1 *= m_cameraZoom;
1288                                 frustum.y2 *= m_cameraZoom;
1289                         }
1290                         projmat = m_rasterizer->GetFrustumMatrix(
1291                                 frustum.x1, frustum.x2, frustum.y1, frustum.y2, frustum.camnear, frustum.camfar, focallength);
1292                 }
1293                 cam->SetProjectionMatrix(projmat);
1294                 
1295                 // Otherwise the projection matrix for each eye will be the same...
1296                 if (!orthographic && m_rasterizer->Stereo())
1297                         cam->InvalidateProjectionMatrix();
1298         }
1299
1300         MT_Transform camtrans(cam->GetWorldToCamera());
1301         MT_Matrix4x4 viewmat(camtrans);
1302         
1303         m_rasterizer->SetViewMatrix(viewmat, cam->NodeGetWorldOrientation(), cam->NodeGetWorldPosition(), cam->GetCameraData()->m_perspective);
1304         cam->SetModelviewMatrix(viewmat);
1305
1306         // The following actually reschedules all vertices to be
1307         // redrawn. There is a cache between the actual rescheduling
1308         // and this call though. Visibility is imparted when this call
1309         // runs through the individual objects.
1310
1311         m_logger->StartLog(tc_scenegraph, m_kxsystem->GetTimeInSeconds(), true);
1312         SG_SetActiveStage(SG_STAGE_CULLING);
1313
1314         scene->CalculateVisibleMeshes(m_rasterizer,cam);
1315
1316         m_logger->StartLog(tc_rasterizer, m_kxsystem->GetTimeInSeconds(), true);
1317         SG_SetActiveStage(SG_STAGE_RENDER);
1318
1319 #ifndef DISABLE_PYTHON
1320         // Run any pre-drawing python callbacks
1321         scene->RunDrawingCallbacks(scene->GetPreDrawCB());
1322 #endif
1323
1324         scene->RenderBuckets(camtrans, m_rasterizer, m_rendertools);
1325         
1326         if (scene->GetPhysicsEnvironment())
1327                 scene->GetPhysicsEnvironment()->debugDrawWorld();
1328 }
1329 /*
1330 To run once per scene
1331 */
1332 void KX_KetsjiEngine::PostRenderScene(KX_Scene* scene)
1333 {
1334         m_rendertools->MotionBlur(m_rasterizer);
1335         scene->Render2DFilters(m_canvas);
1336 #ifndef DISABLE_PYTHON
1337         scene->RunDrawingCallbacks(scene->GetPostDrawCB());     
1338 #endif
1339         m_rasterizer->FlushDebugShapes();
1340 }
1341
1342 void KX_KetsjiEngine::StopEngine()
1343 {
1344         if (m_bInitialized)
1345         {
1346
1347                 if (m_animation_record)
1348                 {
1349 //                      printf("TestHandlesPhysicsObjectToAnimationIpo\n");
1350                         m_sceneconverter->TestHandlesPhysicsObjectToAnimationIpo();
1351                 }
1352
1353                 KX_SceneList::iterator sceneit;
1354                 for (sceneit = m_scenes.begin();sceneit != m_scenes.end() ; sceneit++)
1355                 {
1356                         KX_Scene* scene = *sceneit;
1357                         m_sceneconverter->RemoveScene(scene);
1358                 }       
1359                 m_scenes.clear();
1360
1361                 // cleanup all the stuff                
1362                 m_rasterizer->Exit();
1363         }
1364 }
1365
1366 // Scene Management is able to switch between scenes
1367 // and have several scene's running in parallel
1368 void KX_KetsjiEngine::AddScene(KX_Scene* scene)
1369
1370         m_scenes.push_back(scene);
1371         PostProcessScene(scene);
1372         SceneListsChanged();
1373 }
1374
1375
1376
1377 void KX_KetsjiEngine::PostProcessScene(KX_Scene* scene)
1378 {
1379         bool override_camera = (m_overrideCam && (scene->GetName() == m_overrideSceneName));
1380
1381         SG_SetActiveStage(SG_STAGE_SCENE);
1382
1383         // if there is no activecamera, or the camera is being
1384         // overridden we need to construct a temporarily camera
1385         if (!scene->GetActiveCamera() || override_camera)
1386         {
1387                 KX_Camera* activecam = NULL;
1388
1389                 RAS_CameraData camdata = RAS_CameraData();
1390                 if (override_camera) camdata.m_lens = m_overrideCamLens;
1391
1392                 activecam = new KX_Camera(scene,KX_Scene::m_callbacks,camdata);
1393                 activecam->SetName("__default__cam__");
1394         
1395                         // set transformation
1396                 if (override_camera) {
1397                         const MT_CmMatrix4x4& cammatdata = m_overrideCamViewMat;
1398                         MT_Transform trans = MT_Transform(cammatdata.getPointer());
1399                         MT_Transform camtrans;
1400                         camtrans.invert(trans);
1401                         
1402                         activecam->NodeSetLocalPosition(camtrans.getOrigin());
1403                         activecam->NodeSetLocalOrientation(camtrans.getBasis());
1404                         activecam->NodeUpdateGS(0);
1405                 } else {
1406                         activecam->NodeSetLocalPosition(MT_Point3(0.0, 0.0, 0.0));
1407                         activecam->NodeSetLocalOrientation(MT_Vector3(0.0, 0.0, 0.0));
1408                         activecam->NodeUpdateGS(0);
1409                 }
1410
1411                 scene->AddCamera(activecam);
1412                 scene->SetActiveCamera(activecam);
1413                 scene->GetObjectList()->Add(activecam->AddRef());
1414                 scene->GetRootParentList()->Add(activecam->AddRef());
1415                 //done with activecam
1416                 activecam->Release();
1417         }
1418         
1419         scene->UpdateParents(0.0);
1420 }
1421
1422
1423
1424 void KX_KetsjiEngine::RenderDebugProperties()
1425 {
1426         STR_String debugtxt;
1427         int xcoord = 10;        // mmmm, these constants were taken from blender source
1428         int ycoord = 14;        // to 'mimic' behaviour
1429
1430         float tottime = m_logger->GetAverage();
1431         if (tottime < 1e-6f) {
1432                 tottime = 1e-6f;
1433         }
1434
1435         // Set viewport to entire canvas
1436         RAS_Rect viewport;
1437         m_canvas->SetViewPort(0, 0, int(m_canvas->GetWidth()), int(m_canvas->GetHeight()));
1438         
1439         /* Framerate display */
1440         if (m_show_framerate) {
1441                 debugtxt.Format("swap : %.3f (%.3f frames per second)", tottime, 1.0/tottime);
1442                 m_rendertools->RenderText2D(RAS_IRenderTools::RAS_TEXT_PADDED, 
1443                                                                         debugtxt.Ptr(),
1444                                                                         xcoord,
1445                                                                         ycoord, 
1446                                                                         m_canvas->GetWidth() /* RdV, TODO ?? */, 
1447                                                                         m_canvas->GetHeight() /* RdV, TODO ?? */);
1448                 ycoord += 14;
1449         }
1450
1451         /* Profile and framerate display */
1452         if (m_show_profile)
1453         {               
1454                 for (int j = tc_first; j < tc_numCategories; j++)
1455                 {
1456                         debugtxt.Format(m_profileLabels[j]);
1457                         m_rendertools->RenderText2D(RAS_IRenderTools::RAS_TEXT_PADDED, 
1458                                                                                 debugtxt.Ptr(),
1459                                                                                 xcoord,ycoord,
1460                                                                                 m_canvas->GetWidth(), 
1461                                                                                 m_canvas->GetHeight());
1462                         double time = m_logger->GetAverage((KX_TimeCategory)j);
1463                         debugtxt.Format("%.3fms (%2.2f %%)", time*1000.f, time/tottime * 100.f);
1464                         m_rendertools->RenderText2D(RAS_IRenderTools::RAS_TEXT_PADDED, 
1465                                                                                 debugtxt.Ptr(),
1466                                                                                 xcoord + 60 ,ycoord,
1467                                                                                 m_canvas->GetWidth(), 
1468                                                                                 m_canvas->GetHeight());
1469                         ycoord += 14;
1470                 }
1471         }
1472
1473         /* Property display*/
1474         if (m_show_debug_properties && m_propertiesPresent)
1475         {
1476                 KX_SceneList::iterator sceneit;
1477                 for (sceneit = m_scenes.begin();sceneit != m_scenes.end() ; sceneit++)
1478                 {
1479                         KX_Scene* scene = *sceneit;
1480                         /* the 'normal' debug props */
1481                         vector<SCA_DebugProp*>& debugproplist = scene->GetDebugProperties();
1482                         
1483                         for (vector<SCA_DebugProp*>::iterator it = debugproplist.begin();
1484                                  !(it==debugproplist.end());it++)
1485                         {
1486                                 CValue* propobj = (*it)->m_obj;
1487                                 STR_String objname = propobj->GetName();
1488                                 STR_String propname = (*it)->m_name;
1489                                 if (propname == "__state__")
1490                                 {
1491                                         // reserve name for object state
1492                                         KX_GameObject* gameobj = static_cast<KX_GameObject*>(propobj);
1493                                         unsigned int state = gameobj->GetState();
1494                                         debugtxt = objname + "." + propname + " = ";
1495                                         bool first = true;
1496                                         for (int statenum=1;state;state >>= 1, statenum++)
1497                                         {
1498                                                 if (state & 1)
1499                                                 {
1500                                                         if (!first)
1501                                                         {
1502                                                                 debugtxt += ",";
1503                                                         }
1504                                                         debugtxt += STR_String(statenum);
1505                                                         first = false;
1506                                                 }
1507                                         }
1508                                         m_rendertools->RenderText2D(RAS_IRenderTools::RAS_TEXT_PADDED, 
1509                                                                                                         debugtxt.Ptr(),
1510                                                                                                         xcoord,
1511                                                                                                         ycoord,
1512                                                                                                         m_canvas->GetWidth(),
1513                                                                                                         m_canvas->GetHeight());
1514                                         ycoord += 14;
1515                                 }
1516                                 else
1517                                 {
1518                                         CValue* propval = propobj->GetProperty(propname);
1519                                         if (propval)
1520                                         {
1521                                                 STR_String text = propval->GetText();
1522                                                 debugtxt = objname + "." + propname + " = " + text;
1523                                                 m_rendertools->RenderText2D(RAS_IRenderTools::RAS_TEXT_PADDED, 
1524                                                                                                         debugtxt.Ptr(),
1525                                                                                                         xcoord,
1526                                                                                                         ycoord,
1527                                                                                                         m_canvas->GetWidth(),
1528                                                                                                         m_canvas->GetHeight());
1529                                                 ycoord += 14;
1530                                         }
1531                                 }
1532                         }
1533                 }
1534         }
1535 }
1536
1537
1538 KX_SceneList* KX_KetsjiEngine::CurrentScenes()
1539 {
1540         return &m_scenes;       
1541 }
1542
1543
1544
1545 KX_Scene* KX_KetsjiEngine::FindScene(const STR_String& scenename)
1546 {
1547         KX_SceneList::iterator sceneit = m_scenes.begin();
1548
1549         // bit risky :) better to split the second clause 
1550         while ( (sceneit != m_scenes.end()) 
1551                         && ((*sceneit)->GetName() != scenename))
1552         {
1553                 sceneit++;
1554         }
1555
1556         return ((sceneit == m_scenes.end()) ? NULL : *sceneit); 
1557 }
1558
1559
1560
1561 void KX_KetsjiEngine::ConvertAndAddScene(const STR_String& scenename,bool overlay)
1562 {
1563         // only add scene when it doesn't exist!
1564         if (FindScene(scenename))
1565         {
1566                 STR_String tmpname = scenename;
1567                 printf("warning: scene %s already exists, not added!\n",tmpname.Ptr());
1568         }
1569         else
1570         {
1571                 if (overlay)
1572                 {
1573                         m_addingOverlayScenes.insert(scenename);
1574                 }
1575                 else
1576                 {
1577                         m_addingBackgroundScenes.insert(scenename);
1578                 }
1579         }
1580 }
1581
1582
1583
1584
1585 void KX_KetsjiEngine::RemoveScene(const STR_String& scenename)
1586 {
1587         if (FindScene(scenename))
1588         {
1589                 m_removingScenes.insert(scenename);
1590         }
1591         else
1592         {
1593 //              STR_String tmpname = scenename;
1594                 std::cout << "warning: scene " << scenename << " does not exist, not removed!" << std::endl;
1595         }
1596 }
1597
1598
1599
1600 void KX_KetsjiEngine::RemoveScheduledScenes()
1601 {
1602         if (m_removingScenes.size())
1603         {
1604                 set<STR_String>::iterator scenenameit;
1605                 for (scenenameit=m_removingScenes.begin();scenenameit != m_removingScenes.end();scenenameit++)
1606                 {
1607                         STR_String scenename = *scenenameit;
1608
1609                         KX_SceneList::iterator sceneit;
1610                         for (sceneit = m_scenes.begin();sceneit != m_scenes.end() ; sceneit++)
1611                         {
1612                                 KX_Scene* scene = *sceneit;
1613                                 if (scene->GetName()==scenename)
1614                                 {
1615                                         m_sceneconverter->RemoveScene(scene);
1616                                         m_scenes.erase(sceneit);
1617                                         break;
1618                                 }
1619                         }       
1620                 }
1621                 m_removingScenes.clear();
1622         }
1623 }
1624
1625 KX_Scene* KX_KetsjiEngine::CreateScene(Scene *scene)
1626 {
1627         KX_Scene* tmpscene = new KX_Scene(m_keyboarddevice,
1628                                                                           m_mousedevice,
1629                                                                           m_networkdevice,
1630                                                                           scene->id.name+2,
1631                                                                           scene,
1632                                                                           m_canvas);
1633
1634         m_sceneconverter->ConvertScene(tmpscene,
1635                                                           m_rendertools,
1636                                                           m_canvas);
1637
1638         return tmpscene;
1639 }
1640
1641 KX_Scene* KX_KetsjiEngine::CreateScene(const STR_String& scenename)
1642 {
1643         Scene *scene = m_sceneconverter->GetBlenderSceneForName(scenename);
1644         return CreateScene(scene);
1645 }
1646
1647 void KX_KetsjiEngine::AddScheduledScenes()
1648 {
1649         set<STR_String>::iterator scenenameit;
1650
1651         if (m_addingOverlayScenes.size())
1652         {
1653                 for (scenenameit = m_addingOverlayScenes.begin();
1654                         scenenameit != m_addingOverlayScenes.end();
1655                         scenenameit++)
1656                 {
1657                         STR_String scenename = *scenenameit;
1658                         KX_Scene* tmpscene = CreateScene(scenename);
1659                         m_scenes.push_back(tmpscene);
1660                         PostProcessScene(tmpscene);
1661                 }
1662                 m_addingOverlayScenes.clear();
1663         }
1664         
1665         if (m_addingBackgroundScenes.size())
1666         {
1667                 for (scenenameit = m_addingBackgroundScenes.begin();
1668                         scenenameit != m_addingBackgroundScenes.end();
1669                         scenenameit++)
1670                 {
1671                         STR_String scenename = *scenenameit;
1672                         KX_Scene* tmpscene = CreateScene(scenename);
1673                         m_scenes.insert(m_scenes.begin(),tmpscene);
1674                         PostProcessScene(tmpscene);
1675
1676                 }
1677                 m_addingBackgroundScenes.clear();
1678         }
1679 }
1680
1681
1682
1683 void KX_KetsjiEngine::ReplaceScene(const STR_String& oldscene,const STR_String& newscene)
1684 {
1685         m_replace_scenes.insert(std::make_pair(oldscene,newscene));
1686 }
1687
1688 // replace scene is not the same as removing and adding because the
1689 // scene must be in exact the same place (to maintain drawingorder)
1690 // (nzc) - should that not be done with a scene-display list? It seems
1691 // stupid to rely on the mem allocation order...
1692 void KX_KetsjiEngine::ReplaceScheduledScenes()
1693 {
1694         if (m_replace_scenes.size())
1695         {
1696                 set<pair<STR_String,STR_String> >::iterator scenenameit;
1697                 
1698                 for (scenenameit = m_replace_scenes.begin();
1699                         scenenameit != m_replace_scenes.end();
1700                         scenenameit++)
1701                 {
1702                         STR_String oldscenename = (*scenenameit).first;
1703                         STR_String newscenename = (*scenenameit).second;
1704                         int i=0;
1705                         /* Scenes are not supposed to be included twice... I think */
1706                         KX_SceneList::iterator sceneit;
1707                         for (sceneit = m_scenes.begin();sceneit != m_scenes.end() ; sceneit++)
1708                         {
1709                                 KX_Scene* scene = *sceneit;
1710                                 if (scene->GetName() == oldscenename)
1711                                 {
1712                                         m_sceneconverter->RemoveScene(scene);
1713                                         KX_Scene* tmpscene = CreateScene(newscenename);
1714                                         m_scenes[i]=tmpscene;
1715                                         PostProcessScene(tmpscene);
1716                                 }
1717                                 i++;
1718                         }
1719                 }
1720                 m_replace_scenes.clear();
1721         }       
1722 }
1723
1724
1725
1726 void KX_KetsjiEngine::SuspendScene(const STR_String& scenename)
1727 {
1728         KX_Scene*  scene = FindScene(scenename);
1729         if (scene) scene->Suspend();
1730 }
1731
1732
1733
1734 void KX_KetsjiEngine::ResumeScene(const STR_String& scenename)
1735 {
1736         KX_Scene*  scene = FindScene(scenename);
1737         if (scene) scene->Resume();
1738 }
1739
1740
1741
1742 void KX_KetsjiEngine::SetUseFixedTime(bool bUseFixedTime)
1743 {
1744         m_bFixedTime = bUseFixedTime;
1745 }
1746
1747
1748 void    KX_KetsjiEngine::SetAnimRecordMode(bool animation_record, int startFrame)
1749 {
1750         m_animation_record = animation_record;
1751         if (animation_record)
1752         {
1753                 //when recording physics keyframes, always run at a fixed framerate
1754                 m_bFixedTime = true;
1755         }
1756         m_currentFrame = startFrame;
1757 }
1758
1759 bool KX_KetsjiEngine::GetUseFixedTime(void) const
1760 {
1761         return m_bFixedTime;
1762 }
1763
1764 double KX_KetsjiEngine::GetSuspendedDelta()
1765 {
1766         return m_suspendeddelta;
1767 }
1768
1769 double KX_KetsjiEngine::GetTicRate()
1770 {
1771         return m_ticrate;
1772 }
1773
1774 void KX_KetsjiEngine::SetTicRate(double ticrate)
1775 {
1776         m_ticrate = ticrate;
1777 }
1778
1779 int KX_KetsjiEngine::GetMaxLogicFrame()
1780 {
1781         return m_maxLogicFrame;
1782 }
1783
1784 void KX_KetsjiEngine::SetMaxLogicFrame(int frame)
1785 {
1786         m_maxLogicFrame = frame;
1787 }
1788
1789 int KX_KetsjiEngine::GetMaxPhysicsFrame()
1790 {
1791         return m_maxPhysicsFrame;
1792 }
1793
1794 void KX_KetsjiEngine::SetMaxPhysicsFrame(int frame)
1795 {
1796         m_maxPhysicsFrame = frame;
1797 }
1798
1799 double KX_KetsjiEngine::GetAnimFrameRate()
1800 {
1801         return m_anim_framerate;
1802 }
1803
1804 double KX_KetsjiEngine::GetClockTime(void) const
1805 {
1806         return m_clockTime;
1807 }
1808
1809 double KX_KetsjiEngine::GetFrameTime(void) const
1810 {
1811         return m_frameTime;
1812 }
1813
1814 double KX_KetsjiEngine::GetRealTime(void) const
1815 {
1816         return m_kxsystem->GetTimeInSeconds();
1817 }
1818
1819 void KX_KetsjiEngine::SetAnimFrameRate(double framerate)
1820 {
1821         m_anim_framerate = framerate;
1822 }
1823
1824 double KX_KetsjiEngine::GetAverageFrameRate()
1825 {
1826         return m_average_framerate;
1827 }
1828
1829 void KX_KetsjiEngine::SetTimingDisplay(bool frameRate, bool profile, bool properties)
1830 {
1831         m_show_framerate = frameRate;
1832         m_show_profile = profile;
1833         m_show_debug_properties = properties;
1834 }
1835
1836
1837
1838 void KX_KetsjiEngine::GetTimingDisplay(bool& frameRate, bool& profile, bool& properties) const
1839 {
1840         frameRate = m_show_framerate;
1841         profile = m_show_profile;
1842         properties = m_show_debug_properties;
1843 }
1844
1845
1846
1847 void KX_KetsjiEngine::ProcessScheduledScenes(void)
1848 {
1849         // Check whether there will be changes to the list of scenes
1850         if (m_addingOverlayScenes.size() ||
1851                 m_addingBackgroundScenes.size() ||
1852                 m_replace_scenes.size() ||
1853                 m_removingScenes.size()) {
1854
1855                 // Change the scene list
1856                 ReplaceScheduledScenes();
1857                 RemoveScheduledScenes();
1858                 AddScheduledScenes();
1859
1860                 // Notify
1861                 SceneListsChanged();
1862         }
1863 }
1864
1865
1866
1867 void KX_KetsjiEngine::SceneListsChanged(void)
1868 {
1869         m_propertiesPresent = false;
1870         KX_SceneList::iterator sceneit = m_scenes.begin();
1871         while ((sceneit != m_scenes.end()) && (!m_propertiesPresent))
1872         {
1873                 KX_Scene* scene = *sceneit;
1874                 vector<SCA_DebugProp*>& debugproplist = scene->GetDebugProperties();    
1875                 m_propertiesPresent = !debugproplist.empty();
1876                 sceneit++;
1877         }
1878 }
1879
1880
1881 void KX_KetsjiEngine::SetHideCursor(bool hideCursor)
1882 {
1883         m_hideCursor = hideCursor;
1884 }
1885
1886
1887 bool KX_KetsjiEngine::GetHideCursor(void) const
1888 {
1889         return m_hideCursor;
1890 }
1891
1892
1893 void KX_KetsjiEngine::SetUseOverrideFrameColor(bool overrideFrameColor)
1894 {
1895         m_overrideFrameColor = overrideFrameColor;
1896 }
1897
1898
1899 bool KX_KetsjiEngine::GetUseOverrideFrameColor(void) const
1900 {
1901         return m_overrideFrameColor;
1902 }
1903
1904
1905 void KX_KetsjiEngine::SetOverrideFrameColor(float r, float g, float b)
1906 {
1907         m_overrideFrameColorR = r;
1908         m_overrideFrameColorG = g;
1909         m_overrideFrameColorB = b;
1910 }
1911
1912
1913 void KX_KetsjiEngine::GetOverrideFrameColor(float& r, float& g, float& b) const
1914 {
1915         r = m_overrideFrameColorR;
1916         g = m_overrideFrameColorG;
1917         b = m_overrideFrameColorB;
1918 }
1919
1920