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