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