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