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