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