Blender V2.61 - r43446

KX_KetsjiEngine.cpp

Go to the documentation of this file.
00001 /*
00002  * ***** BEGIN GPL LICENSE BLOCK *****
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License
00006  * as published by the Free Software Foundation; either version 2
00007  * of the License, or (at your option) any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software Foundation,
00016  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017  *
00018  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
00019  * All rights reserved.
00020  *
00021  * The Original Code is: all of this file.
00022  *
00023  * Contributor(s): none yet.
00024  *
00025  * ***** END GPL LICENSE BLOCK *****
00026  * The engine ties all game modules together. 
00027  */
00028 
00034 #if defined(WIN32) && !defined(FREE_WINDOWS)
00035 #pragma warning (disable : 4786)
00036 #endif //WIN32
00037 
00038 #include <iostream>
00039 #include <stdio.h>
00040 
00041 #include "KX_KetsjiEngine.h"
00042 
00043 #include "ListValue.h"
00044 #include "IntValue.h"
00045 #include "VectorValue.h"
00046 #include "BoolValue.h"
00047 #include "FloatValue.h"
00048 
00049 #define KX_NUM_ITERATIONS 4
00050 #include "RAS_BucketManager.h"
00051 #include "RAS_Rect.h"
00052 #include "RAS_IRasterizer.h"
00053 #include "RAS_IRenderTools.h"
00054 #include "RAS_ICanvas.h"
00055 #include "STR_String.h"
00056 #include "MT_Vector3.h"
00057 #include "MT_Transform.h"
00058 #include "SCA_IInputDevice.h"
00059 #include "KX_Scene.h"
00060 #include "MT_CmMatrix4x4.h"
00061 #include "KX_Camera.h"
00062 #include "KX_FontObject.h"
00063 #include "KX_Dome.h"
00064 #include "KX_Light.h"
00065 #include "KX_PythonInit.h"
00066 #include "KX_PyConstraintBinding.h"
00067 #include "PHY_IPhysicsEnvironment.h"
00068 
00069 #ifdef WITH_AUDASPACE
00070 #  include "AUD_C-API.h"
00071 #  include "AUD_I3DDevice.h"
00072 #endif
00073 
00074 #include "NG_NetworkScene.h"
00075 #include "NG_NetworkDeviceInterface.h"
00076 
00077 #include "KX_WorldInfo.h"
00078 #include "KX_ISceneConverter.h"
00079 #include "KX_TimeCategoryLogger.h"
00080 
00081 #include "RAS_FramingManager.h"
00082 #include "DNA_world_types.h"
00083 #include "DNA_scene_types.h"
00084 
00085 #include "KX_NavMeshObject.h"
00086 
00087 // If define: little test for Nzc: guarded drawing. If the canvas is
00088 // not valid, skip rendering this frame.
00089 //#define NZC_GUARDED_OUTPUT
00090 #define DEFAULT_LOGIC_TIC_RATE 60.0
00091 #define DEFAULT_PHYSICS_TIC_RATE 60.0
00092 
00093 const char KX_KetsjiEngine::m_profileLabels[tc_numCategories][15] = {
00094     "Physics:",     // tc_physics
00095     "Logic:",       // tc_logic
00096     "Animations:",  // tc_animations
00097     "Network:",     // tc_network
00098     "Scenegraph:",  // tc_scenegraph
00099     "Rasterizer:",  // tc_rasterizer
00100     "Services:",    // tc_services
00101     "Overhead:",    // tc_overhead
00102     "Outside:"      // tc_outside
00103 };
00104 
00105 double KX_KetsjiEngine::m_ticrate = DEFAULT_LOGIC_TIC_RATE;
00106 int    KX_KetsjiEngine::m_maxLogicFrame = 5;
00107 int    KX_KetsjiEngine::m_maxPhysicsFrame = 5;
00108 double KX_KetsjiEngine::m_anim_framerate = 25.0;
00109 double KX_KetsjiEngine::m_suspendedtime = 0.0;
00110 double KX_KetsjiEngine::m_suspendeddelta = 0.0;
00111 double KX_KetsjiEngine::m_average_framerate = 0.0;
00112 bool   KX_KetsjiEngine::m_restrict_anim_fps = false;
00113 short  KX_KetsjiEngine::m_exitkey = 130; //ESC Key
00114 
00115 
00119 KX_KetsjiEngine::KX_KetsjiEngine(KX_ISystem* system)
00120     :   m_canvas(NULL),
00121     m_rasterizer(NULL),
00122     m_kxsystem(system),
00123     m_rendertools(NULL),
00124     m_sceneconverter(NULL),
00125     m_networkdevice(NULL),
00126 #ifdef WITH_PYTHON
00127     m_pythondictionary(NULL),
00128 #endif
00129     m_keyboarddevice(NULL),
00130     m_mousedevice(NULL),
00131 
00132     m_propertiesPresent(false),
00133 
00134     m_bInitialized(false),
00135     m_activecam(0),
00136     m_bFixedTime(false),
00137     
00138     m_firstframe(true),
00139     
00140     m_frameTime(0.f),
00141     m_clockTime(0.f),
00142     m_previousClockTime(0.f),
00143     m_previousAnimTime(0.f),
00144 
00145 
00146     m_exitcode(KX_EXIT_REQUEST_NO_REQUEST),
00147     m_exitstring(""),
00148     
00149     m_drawingmode(5),
00150     m_cameraZoom(1.0),
00151     
00152     m_overrideCam(false),
00153     m_overrideCamUseOrtho(false),
00154     m_overrideCamNear(0.0),
00155     m_overrideCamFar(0.0),
00156 
00157     m_stereo(false),
00158     m_curreye(0),
00159 
00160     m_logger(NULL),
00161     
00162     // Set up timing info display variables
00163     m_show_framerate(false),
00164     m_show_profile(false),
00165     m_showProperties(false),
00166     m_showBackground(false),
00167     m_show_debug_properties(false),
00168 
00169     m_animation_record(false),
00170 
00171     // Default behavior is to hide the cursor every frame.
00172     m_hideCursor(false),
00173 
00174     m_overrideFrameColor(false),
00175     m_overrideFrameColorR(0.0),
00176     m_overrideFrameColorG(0.0),
00177     m_overrideFrameColorB(0.0),
00178 
00179     m_usedome(false)
00180 {
00181     // Initialize the time logger
00182     m_logger = new KX_TimeCategoryLogger (25);
00183 
00184     for (int i = tc_first; i < tc_numCategories; i++)
00185         m_logger->AddCategory((KX_TimeCategory)i);
00186         
00187 }
00188 
00189 
00190 
00194 KX_KetsjiEngine::~KX_KetsjiEngine()
00195 {
00196     delete m_logger;
00197     if(m_usedome)
00198         delete m_dome;
00199 }
00200 
00201 
00202 
00203 void KX_KetsjiEngine::SetKeyboardDevice(SCA_IInputDevice* keyboarddevice)
00204 {
00205     MT_assert(keyboarddevice);
00206     m_keyboarddevice = keyboarddevice;
00207 }
00208 
00209 
00210 
00211 void KX_KetsjiEngine::SetMouseDevice(SCA_IInputDevice* mousedevice)
00212 {
00213     MT_assert(mousedevice);
00214     m_mousedevice = mousedevice;
00215 }
00216 
00217 
00218 
00219 void KX_KetsjiEngine::SetNetworkDevice(NG_NetworkDeviceInterface* networkdevice)
00220 {
00221     MT_assert(networkdevice);
00222     m_networkdevice = networkdevice;
00223 }
00224 
00225 
00226 void KX_KetsjiEngine::SetCanvas(RAS_ICanvas* canvas)
00227 {
00228     MT_assert(canvas);
00229     m_canvas = canvas;
00230 }
00231 
00232 
00233 
00234 void KX_KetsjiEngine::SetRenderTools(RAS_IRenderTools* rendertools)
00235 {
00236     MT_assert(rendertools);
00237     m_rendertools = rendertools;
00238 }
00239 
00240 
00241 
00242 void KX_KetsjiEngine::SetRasterizer(RAS_IRasterizer* rasterizer)
00243 {
00244     MT_assert(rasterizer);
00245     m_rasterizer = rasterizer;
00246 }
00247 
00248 #ifdef WITH_PYTHON
00249 /*
00250  * At the moment the bge.logic module is imported into 'pythondictionary' after this function is called.
00251  * if this function ever changes to assign a copy, make sure the game logic module is imported into this dictionary before hand.
00252  */
00253 void KX_KetsjiEngine::SetPyNamespace(PyObject* pythondictionary)
00254 {
00255     MT_assert(pythondictionary);
00256     m_pythondictionary = pythondictionary;
00257 }
00258 #endif
00259 
00260 
00261 void KX_KetsjiEngine::SetSceneConverter(KX_ISceneConverter* sceneconverter)
00262 {
00263     MT_assert(sceneconverter);
00264     m_sceneconverter = sceneconverter;
00265 }
00266 
00267 void KX_KetsjiEngine::InitDome(short res, short mode, short angle, float resbuf, short tilt, struct Text* text)
00268 {
00269     m_dome = new KX_Dome(m_canvas, m_rasterizer, m_rendertools,this, res, mode, angle, resbuf, tilt, text);
00270     m_usedome = true;
00271 }
00272 
00273 void KX_KetsjiEngine::RenderDome()
00274 {
00275     GLuint  viewport[4]={0};
00276     glGetIntegerv(GL_VIEWPORT,(GLint *)viewport);
00277     
00278     m_dome->SetViewPort(viewport);
00279 
00280     KX_Scene* firstscene = *m_scenes.begin();
00281     const RAS_FrameSettings &framesettings = firstscene->GetFramingType();
00282 
00283     m_logger->StartLog(tc_rasterizer, m_kxsystem->GetTimeInSeconds(), true);
00284 
00285     // hiding mouse cursor each frame
00286     // (came back when going out of focus and then back in again)
00287     if (m_hideCursor)
00288         m_canvas->SetMouseState(RAS_ICanvas::MOUSE_INVISIBLE);
00289 
00290     // clear the entire game screen with the border color
00291     // only once per frame
00292 
00293     m_canvas->BeginDraw();
00294 
00295     // BeginFrame() sets the actual drawing area. You can use a part of the window
00296     if (!BeginFrame())
00297         return;
00298 
00299     KX_SceneList::iterator sceneit;
00300     KX_Scene* scene;
00301 
00302     int n_renders=m_dome->GetNumberRenders();// usually 4 or 6
00303     for (int i=0;i<n_renders;i++){
00304         m_canvas->ClearBuffer(RAS_ICanvas::COLOR_BUFFER|RAS_ICanvas::DEPTH_BUFFER);
00305         for (sceneit = m_scenes.begin();sceneit != m_scenes.end(); sceneit++)
00306         // for each scene, call the proceed functions
00307         {
00308             scene = *sceneit;
00309             KX_Camera* cam = scene->GetActiveCamera();
00310 
00311             m_rendertools->BeginFrame(m_rasterizer);
00312             // pass the scene's worldsettings to the rasterizer
00313             SetWorldSettings(scene->GetWorldInfo());
00314 
00315             // shadow buffers
00316             if (i == 0){
00317                 RenderShadowBuffers(scene);
00318             }
00319             // Avoid drawing the scene with the active camera twice when it's viewport is enabled
00320             if(cam && !cam->GetViewport())
00321             {
00322                 if (scene->IsClearingZBuffer())
00323                     m_rasterizer->ClearDepthBuffer();
00324         
00325                 m_rendertools->SetAuxilaryClientInfo(scene);
00326         
00327                 // do the rendering
00328                 m_dome->RenderDomeFrame(scene,cam, i);
00329                 //render all the font objects for this scene
00330                 RenderFonts(scene);
00331             }
00332             
00333             list<class KX_Camera*>* cameras = scene->GetCameras();
00334             
00335             // Draw the scene once for each camera with an enabled viewport
00336             list<KX_Camera*>::iterator it = cameras->begin();
00337             while(it != cameras->end())
00338             {
00339                 if((*it)->GetViewport())
00340                 {
00341                     if (scene->IsClearingZBuffer())
00342                         m_rasterizer->ClearDepthBuffer();
00343             
00344                     m_rendertools->SetAuxilaryClientInfo(scene);
00345             
00346                     // do the rendering
00347                     m_dome->RenderDomeFrame(scene, (*it),i);
00348                     //render all the font objects for this scene
00349                     RenderFonts(scene);
00350                 }
00351                 
00352                 it++;
00353             }
00354             // Part of PostRenderScene()
00355             m_rendertools->MotionBlur(m_rasterizer);
00356             scene->Render2DFilters(m_canvas);
00357             // no RunDrawingCallBacks
00358             // no FlushDebugLines
00359         }
00360         m_dome->BindImages(i);
00361     }   
00362 
00363     m_canvas->EndFrame();//XXX do we really need that?
00364 
00365     m_canvas->SetViewPort(0, 0, m_canvas->GetWidth(), m_canvas->GetHeight());
00366 
00367     if (m_overrideFrameColor) //XXX why do we want
00368     {
00369         // Do not use the framing bar color set in the Blender scenes
00370         m_canvas->ClearColor(
00371             m_overrideFrameColorR,
00372             m_overrideFrameColorG,
00373             m_overrideFrameColorB,
00374             1.0
00375             );
00376     }
00377     else
00378     {
00379         // Use the framing bar color set in the Blender scenes
00380         m_canvas->ClearColor(
00381             framesettings.BarRed(),
00382             framesettings.BarGreen(),
00383             framesettings.BarBlue(),
00384             1.0
00385             );
00386     }
00387     m_dome->Draw();
00388     // Draw Callback for the last scene
00389 #ifdef WITH_PYTHON
00390     scene->RunDrawingCallbacks(scene->GetPostDrawCB());
00391 #endif  
00392     EndFrame();
00393 }
00394 
00400 void KX_KetsjiEngine::StartEngine(bool clearIpo)
00401 {
00402     m_clockTime = m_kxsystem->GetTimeInSeconds();
00403     m_frameTime = m_kxsystem->GetTimeInSeconds();
00404     m_previousClockTime = m_kxsystem->GetTimeInSeconds();
00405 
00406     m_firstframe = true;
00407     m_bInitialized = true;
00408     // there is always one scene enabled at startup
00409     Scene* scene = m_scenes[0]->GetBlenderScene();
00410     if (scene)
00411     {
00412         m_ticrate = scene->gm.ticrate ? scene->gm.ticrate : DEFAULT_LOGIC_TIC_RATE;
00413         m_maxLogicFrame = scene->gm.maxlogicstep ? scene->gm.maxlogicstep : 5;
00414         m_maxPhysicsFrame = scene->gm.maxphystep ? scene->gm.maxlogicstep : 5;
00415     }
00416     else
00417     {
00418         m_ticrate = DEFAULT_LOGIC_TIC_RATE;
00419         m_maxLogicFrame = 5;
00420         m_maxPhysicsFrame = 5;
00421     }
00422     
00423     if (m_animation_record)
00424     {
00425         m_sceneconverter->ResetPhysicsObjectsAnimationIpo(clearIpo);
00426         m_sceneconverter->WritePhysicsObjectToAnimationIpo(m_currentFrame);
00427     }
00428 
00429 }
00430 
00431 void KX_KetsjiEngine::ClearFrame()
00432 {
00433     // clear unless we're drawing overlapping stereo
00434     if(m_rasterizer->InterlacedStereo() &&
00435         m_rasterizer->GetEye() == RAS_IRasterizer::RAS_STEREO_RIGHTEYE)
00436         return;
00437 
00438     // clear the viewports with the background color of the first scene
00439     bool doclear = false;
00440     KX_SceneList::iterator sceneit;
00441     RAS_Rect clearvp, area, viewport;
00442 
00443     for (sceneit = m_scenes.begin(); sceneit != m_scenes.end(); sceneit++)
00444     {
00445         KX_Scene* scene = *sceneit;
00446         //const RAS_FrameSettings &framesettings = scene->GetFramingType();
00447         list<class KX_Camera*>* cameras = scene->GetCameras();
00448 
00449         list<KX_Camera*>::iterator it;
00450         for(it = cameras->begin(); it != cameras->end(); it++)
00451         {
00452             GetSceneViewport(scene, (*it), area, viewport);
00453 
00454             if(!doclear) {
00455                 clearvp = viewport;
00456                 doclear = true;
00457             }
00458             else {
00459                 if(viewport.GetLeft() < clearvp.GetLeft())
00460                     clearvp.SetLeft(viewport.GetLeft());
00461                 if(viewport.GetBottom() < clearvp.GetBottom())
00462                     clearvp.SetBottom(viewport.GetBottom());
00463                 if(viewport.GetRight() > clearvp.GetRight())
00464                     clearvp.SetRight(viewport.GetRight());
00465                 if(viewport.GetTop() > clearvp.GetTop())
00466                     clearvp.SetTop(viewport.GetTop());
00467 
00468             }
00469         }
00470     }
00471 
00472     if(doclear) {
00473         KX_Scene* firstscene = *m_scenes.begin();
00474         SetBackGround(firstscene->GetWorldInfo());
00475 
00476         m_canvas->SetViewPort(clearvp.GetLeft(), clearvp.GetBottom(),
00477             clearvp.GetRight(), clearvp.GetTop());  
00478         m_rasterizer->ClearColorBuffer();
00479     }
00480 }
00481 
00482 bool KX_KetsjiEngine::BeginFrame()
00483 {
00484     // set the area used for rendering (stereo can assign only a subset)
00485     m_rasterizer->SetRenderArea();
00486 
00487     if (m_canvas->BeginDraw())
00488     {
00489         ClearFrame();
00490 
00491         m_rasterizer->BeginFrame(m_drawingmode , m_kxsystem->GetTimeInSeconds());
00492         m_rendertools->BeginFrame(m_rasterizer);
00493 
00494         return true;
00495     }
00496     
00497     return false;
00498 }       
00499 
00500 
00501 void KX_KetsjiEngine::EndFrame()
00502 {
00503     // Show profiling info
00504     m_logger->StartLog(tc_overhead, m_kxsystem->GetTimeInSeconds(), true);
00505     if (m_show_framerate || m_show_profile || (m_show_debug_properties && m_propertiesPresent))
00506     {
00507         RenderDebugProperties();
00508     }
00509 
00510     m_average_framerate = m_logger->GetAverage();
00511     if (m_average_framerate < 1e-6)
00512         m_average_framerate = 1e-6;
00513     m_average_framerate = 1.0/m_average_framerate;
00514 
00515     // Go to next profiling measurement, time spend after this call is shown in the next frame.
00516     m_logger->NextMeasurement(m_kxsystem->GetTimeInSeconds());
00517 
00518     m_logger->StartLog(tc_rasterizer, m_kxsystem->GetTimeInSeconds(), true);
00519     m_rasterizer->EndFrame();
00520     // swap backbuffer (drawing into this buffer) <-> front/visible buffer
00521     m_rasterizer->SwapBuffers();
00522     m_rendertools->EndFrame(m_rasterizer);
00523 
00524     
00525     m_canvas->EndDraw();
00526 }
00527 
00528 //#include "PIL_time.h"
00529 //#include "LinearMath/btQuickprof.h"
00530 
00531 
00532 bool KX_KetsjiEngine::NextFrame()
00533 {
00534     double timestep = 1.0/m_ticrate;
00535     double framestep = timestep;
00536 //  static hidden::Clock sClock;
00537 
00538 m_logger->StartLog(tc_services, m_kxsystem->GetTimeInSeconds(),true);
00539 
00540 //float dt = sClock.getTimeMicroseconds() * 0.000001f;
00541 //sClock.reset();
00542 
00543 if (m_bFixedTime)
00544     m_clockTime += timestep;
00545 else
00546 {
00547 
00548 //  m_clockTime += dt;
00549     m_clockTime = m_kxsystem->GetTimeInSeconds();
00550 }
00551     
00552     double deltatime = m_clockTime - m_frameTime;
00553     if (deltatime<0.f)
00554     {
00555         printf("problem with clock\n");
00556         deltatime = 0.f;
00557         m_clockTime = 0.f;
00558         m_frameTime = 0.f;
00559     }
00560 
00561 
00562     // Compute the number of logic frames to do each update (fixed tic bricks)
00563     int frames =int(deltatime*m_ticrate+1e-6);
00564 //  if (frames>1)
00565 //      printf("****************************************");
00566 //  printf("dt = %f, deltatime = %f, frames = %d\n",dt, deltatime,frames);
00567     
00568 //  if (!frames)
00569 //      PIL_sleep_ms(1);
00570     
00571     KX_SceneList::iterator sceneit;
00572     
00573     if (frames>m_maxPhysicsFrame)
00574     {
00575     
00576     //  printf("framedOut: %d\n",frames);
00577         m_frameTime+=(frames-m_maxPhysicsFrame)*timestep;
00578         frames = m_maxPhysicsFrame;
00579     }
00580     
00581 
00582     bool doRender = frames>0;
00583 
00584     if (frames > m_maxLogicFrame)
00585     {
00586         framestep = (frames*timestep)/m_maxLogicFrame;
00587         frames = m_maxLogicFrame;
00588     }
00589 
00590     while (frames)
00591     {
00592     
00593 
00594         m_frameTime += framestep;
00595         
00596         for (sceneit = m_scenes.begin();sceneit != m_scenes.end(); ++sceneit)
00597         // for each scene, call the proceed functions
00598         {
00599             KX_Scene* scene = *sceneit;
00600     
00601             /* Suspension holds the physics and logic processing for an
00602             * entire scene. Objects can be suspended individually, and
00603             * the settings for that preceed the logic and physics
00604             * update. */
00605             m_logger->StartLog(tc_logic, m_kxsystem->GetTimeInSeconds(), true);
00606 
00607             m_sceneconverter->resetNoneDynamicObjectToIpo();//this is for none dynamic objects with ipo
00608 
00609             scene->UpdateObjectActivity();
00610     
00611             if (!scene->IsSuspended())
00612             {
00613                 // if the scene was suspended recalcutlate the delta tu "curtime"
00614                 m_suspendedtime = scene->getSuspendedTime();
00615                 if (scene->getSuspendedTime()!=0.0)
00616                     scene->setSuspendedDelta(scene->getSuspendedDelta()+m_clockTime-scene->getSuspendedTime());
00617                 m_suspendeddelta = scene->getSuspendedDelta();
00618 
00619                 
00620                 m_logger->StartLog(tc_network, m_kxsystem->GetTimeInSeconds(), true);
00621                 SG_SetActiveStage(SG_STAGE_NETWORK);
00622                 scene->GetNetworkScene()->proceed(m_frameTime);
00623     
00624                 //m_logger->StartLog(tc_scenegraph, m_kxsystem->GetTimeInSeconds(), true);
00625                 //SG_SetActiveStage(SG_STAGE_NETWORK_UPDATE);
00626                 //scene->UpdateParents(m_frameTime);
00627                 
00628                 m_logger->StartLog(tc_physics, m_kxsystem->GetTimeInSeconds(), true);
00629                 SG_SetActiveStage(SG_STAGE_PHYSICS1);
00630                 // set Python hooks for each scene
00631 #ifdef WITH_PYTHON
00632                 PHY_SetActiveEnvironment(scene->GetPhysicsEnvironment());
00633 #endif
00634                 KX_SetActiveScene(scene);
00635     
00636                 scene->GetPhysicsEnvironment()->endFrame();
00637                 
00638                 // Update scenegraph after physics step. This maps physics calculations
00639                 // into node positions.     
00640                 //m_logger->StartLog(tc_scenegraph, m_kxsystem->GetTimeInSeconds(), true);
00641                 //SG_SetActiveStage(SG_STAGE_PHYSICS1_UPDATE);
00642                 //scene->UpdateParents(m_frameTime);
00643                 
00644                 // Process sensors, and controllers
00645                 m_logger->StartLog(tc_logic, m_kxsystem->GetTimeInSeconds(), true);
00646                 SG_SetActiveStage(SG_STAGE_CONTROLLER);
00647                 scene->LogicBeginFrame(m_frameTime);
00648     
00649                 // Scenegraph needs to be updated again, because Logic Controllers 
00650                 // can affect the local matrices.
00651                 m_logger->StartLog(tc_scenegraph, m_kxsystem->GetTimeInSeconds(), true);
00652                 SG_SetActiveStage(SG_STAGE_CONTROLLER_UPDATE);
00653                 scene->UpdateParents(m_frameTime);
00654     
00655                 // Process actuators
00656     
00657                 // Do some cleanup work for this logic frame
00658                 m_logger->StartLog(tc_logic, m_kxsystem->GetTimeInSeconds(), true);
00659                 SG_SetActiveStage(SG_STAGE_ACTUATOR);
00660                 scene->LogicUpdateFrame(m_frameTime, true);
00661                 
00662                 scene->LogicEndFrame();
00663     
00664                 // Actuators can affect the scenegraph
00665                 m_logger->StartLog(tc_scenegraph, m_kxsystem->GetTimeInSeconds(), true);
00666                 SG_SetActiveStage(SG_STAGE_ACTUATOR_UPDATE);
00667                 scene->UpdateParents(m_frameTime);
00668 
00669                 if (!GetRestrictAnimationFPS())
00670                 {
00671                     m_logger->StartLog(tc_animations, m_kxsystem->GetTimeInSeconds(), true);
00672                     SG_SetActiveStage(SG_STAGE_ANIMATION_UPDATE);
00673                     scene->UpdateAnimations(m_frameTime);
00674                 }
00675 
00676                 m_logger->StartLog(tc_physics, m_kxsystem->GetTimeInSeconds(), true);
00677                 SG_SetActiveStage(SG_STAGE_PHYSICS2);
00678                 scene->GetPhysicsEnvironment()->beginFrame();
00679         
00680                 // Perform physics calculations on the scene. This can involve 
00681                 // many iterations of the physics solver.
00682                 scene->GetPhysicsEnvironment()->proceedDeltaTime(m_frameTime,timestep,framestep);//m_deltatimerealDeltaTime);
00683 
00684                 m_logger->StartLog(tc_scenegraph, m_kxsystem->GetTimeInSeconds(), true);
00685                 SG_SetActiveStage(SG_STAGE_PHYSICS2_UPDATE);
00686                 scene->UpdateParents(m_frameTime);
00687             
00688             
00689                 if (m_animation_record)
00690                 {                   
00691                     m_sceneconverter->WritePhysicsObjectToAnimationIpo(++m_currentFrame);
00692                 }
00693 
00694                 scene->setSuspendedTime(0.0);
00695             } // suspended
00696             else
00697                 if(scene->getSuspendedTime()==0.0)
00698                     scene->setSuspendedTime(m_clockTime);
00699             
00700             m_logger->StartLog(tc_services, m_kxsystem->GetTimeInSeconds(), true);
00701         }
00702 
00703         // update system devices
00704         m_logger->StartLog(tc_logic, m_kxsystem->GetTimeInSeconds(), true);
00705         if (m_keyboarddevice)
00706             m_keyboarddevice->NextFrame();
00707     
00708         if (m_mousedevice)
00709             m_mousedevice->NextFrame();
00710         
00711         if (m_networkdevice)
00712             m_networkdevice->NextFrame();
00713 
00714         // scene management
00715         ProcessScheduledScenes();
00716         
00717         frames--;
00718     }
00719 
00720     bool bUseAsyncLogicBricks= false;//true;
00721 
00722     if (bUseAsyncLogicBricks)
00723     {   
00724         // Logic update sub frame: this will let some logic bricks run at the
00725         // full frame rate.
00726         for (sceneit = m_scenes.begin();sceneit != m_scenes.end(); ++sceneit)
00727         // for each scene, call the proceed functions
00728         {
00729             KX_Scene* scene = *sceneit;
00730 
00731             if (!scene->IsSuspended())
00732             {
00733                 // if the scene was suspended recalcutlate the delta tu "curtime"
00734                 m_suspendedtime = scene->getSuspendedTime();
00735                 if (scene->getSuspendedTime()!=0.0)
00736                     scene->setSuspendedDelta(scene->getSuspendedDelta()+m_clockTime-scene->getSuspendedTime());
00737                 m_suspendeddelta = scene->getSuspendedDelta();
00738                 
00739                 // set Python hooks for each scene
00740 #ifdef WITH_PYTHON
00741                 PHY_SetActiveEnvironment(scene->GetPhysicsEnvironment());
00742 #endif
00743                 KX_SetActiveScene(scene);
00744                 
00745                 m_logger->StartLog(tc_scenegraph, m_kxsystem->GetTimeInSeconds(), true);
00746                 SG_SetActiveStage(SG_STAGE_PHYSICS1);
00747                 scene->UpdateParents(m_clockTime);
00748 
00749                 // Perform physics calculations on the scene. This can involve 
00750                 // many iterations of the physics solver.
00751                 m_logger->StartLog(tc_physics, m_kxsystem->GetTimeInSeconds(), true);
00752                 scene->GetPhysicsEnvironment()->proceedDeltaTime(m_clockTime,timestep,timestep);
00753                 // Update scenegraph after physics step. This maps physics calculations
00754                 // into node positions.     
00755                 m_logger->StartLog(tc_scenegraph, m_kxsystem->GetTimeInSeconds(), true);
00756                 SG_SetActiveStage(SG_STAGE_PHYSICS2);
00757                 scene->UpdateParents(m_clockTime);
00758                 
00759                 // Do some cleanup work for this logic frame
00760                 m_logger->StartLog(tc_logic, m_kxsystem->GetTimeInSeconds(), true);
00761                 scene->LogicUpdateFrame(m_clockTime, false);
00762 
00763                 // Actuators can affect the scenegraph
00764                 m_logger->StartLog(tc_scenegraph, m_kxsystem->GetTimeInSeconds(), true);
00765                 SG_SetActiveStage(SG_STAGE_ACTUATOR);
00766                 scene->UpdateParents(m_clockTime);
00767 
00768                 scene->setSuspendedTime(0.0);
00769             } // suspended
00770             else
00771                 if(scene->getSuspendedTime()==0.0)
00772                     scene->setSuspendedTime(m_clockTime);
00773 
00774             m_logger->StartLog(tc_services, m_kxsystem->GetTimeInSeconds(), true);
00775         }
00776     }
00777 
00778         
00779     // Handle the animations independently of the logic time step
00780     if (GetRestrictAnimationFPS())
00781     {
00782         m_logger->StartLog(tc_animations, m_kxsystem->GetTimeInSeconds(), true);
00783         SG_SetActiveStage(SG_STAGE_ANIMATION_UPDATE);
00784 
00785         double anim_timestep = 1.0/KX_GetActiveScene()->GetAnimationFPS();
00786         if (m_clockTime - m_previousAnimTime > anim_timestep)
00787         {
00788             // Sanity/debug print to make sure we're actually going at the fps we want (should be close to anim_timestep)
00789             // printf("Anim fps: %f\n", 1.0/(m_clockTime - m_previousAnimTime));
00790             m_previousAnimTime = m_clockTime;
00791             for (sceneit = m_scenes.begin();sceneit != m_scenes.end(); ++sceneit)
00792             {
00793                 (*sceneit)->UpdateAnimations(m_frameTime);
00794             }
00795         }
00796         m_previousClockTime = m_clockTime;
00797     }
00798     
00799     // Start logging time spend outside main loop
00800     m_logger->StartLog(tc_outside, m_kxsystem->GetTimeInSeconds(), true);
00801     
00802     return doRender;
00803 }
00804 
00805 
00806 
00807 void KX_KetsjiEngine::Render()
00808 {
00809     if(m_usedome){
00810         RenderDome();
00811         return;
00812     }
00813     KX_Scene* firstscene = *m_scenes.begin();
00814     const RAS_FrameSettings &framesettings = firstscene->GetFramingType();
00815 
00816     m_logger->StartLog(tc_rasterizer, m_kxsystem->GetTimeInSeconds(), true);
00817     SG_SetActiveStage(SG_STAGE_RENDER);
00818 
00819     // hiding mouse cursor each frame
00820     // (came back when going out of focus and then back in again)
00821     if (m_hideCursor)
00822         m_canvas->SetMouseState(RAS_ICanvas::MOUSE_INVISIBLE);
00823 
00824     // clear the entire game screen with the border color
00825     // only once per frame
00826     m_canvas->BeginDraw();
00827     if (m_drawingmode == RAS_IRasterizer::KX_TEXTURED) {
00828         m_canvas->SetViewPort(0, 0, m_canvas->GetWidth(), m_canvas->GetHeight());
00829         if (m_overrideFrameColor)
00830         {
00831             // Do not use the framing bar color set in the Blender scenes
00832             m_canvas->ClearColor(
00833                 m_overrideFrameColorR,
00834                 m_overrideFrameColorG,
00835                 m_overrideFrameColorB,
00836                 1.0
00837                 );
00838         }
00839         else
00840         {
00841             // Use the framing bar color set in the Blender scenes
00842             m_canvas->ClearColor(
00843                 framesettings.BarRed(),
00844                 framesettings.BarGreen(),
00845                 framesettings.BarBlue(),
00846                 1.0
00847                 );
00848         }
00849         // clear the -whole- viewport
00850         m_canvas->ClearBuffer(RAS_ICanvas::COLOR_BUFFER|RAS_ICanvas::DEPTH_BUFFER);
00851     }
00852 
00853     m_rasterizer->SetEye(RAS_IRasterizer::RAS_STEREO_LEFTEYE);
00854 
00855     // BeginFrame() sets the actual drawing area. You can use a part of the window
00856     if (!BeginFrame())
00857         return;
00858 
00859     KX_SceneList::iterator sceneit;
00860     for (sceneit = m_scenes.begin();sceneit != m_scenes.end(); sceneit++)
00861     // for each scene, call the proceed functions
00862     {
00863         KX_Scene* scene = *sceneit;
00864         KX_Camera* cam = scene->GetActiveCamera();
00865         // pass the scene's worldsettings to the rasterizer
00866         SetWorldSettings(scene->GetWorldInfo());
00867 
00868         // this is now done incrementatlly in KX_Scene::CalculateVisibleMeshes
00869         //scene->UpdateMeshTransformations();
00870 
00871         // shadow buffers
00872         RenderShadowBuffers(scene);
00873 
00874         // Avoid drawing the scene with the active camera twice when it's viewport is enabled
00875         if(cam && !cam->GetViewport())
00876         {
00877             if (scene->IsClearingZBuffer())
00878                 m_rasterizer->ClearDepthBuffer();
00879     
00880             m_rendertools->SetAuxilaryClientInfo(scene);
00881     
00882             // do the rendering
00883             RenderFrame(scene, cam);
00884         }
00885         
00886         list<class KX_Camera*>* cameras = scene->GetCameras();
00887         
00888         // Draw the scene once for each camera with an enabled viewport
00889         list<KX_Camera*>::iterator it = cameras->begin();
00890         while(it != cameras->end())
00891         {
00892             if((*it)->GetViewport())
00893             {
00894                 if (scene->IsClearingZBuffer())
00895                     m_rasterizer->ClearDepthBuffer();
00896         
00897                 m_rendertools->SetAuxilaryClientInfo(scene);
00898         
00899                 // do the rendering
00900                 RenderFrame(scene, (*it));
00901             }
00902             
00903             it++;
00904         }
00905         PostRenderScene(scene);
00906     }
00907 
00908     // only one place that checks for stereo
00909     if(m_rasterizer->Stereo())
00910     {
00911         m_rasterizer->SetEye(RAS_IRasterizer::RAS_STEREO_RIGHTEYE);
00912 
00913         if (!BeginFrame())
00914             return;
00915 
00916 
00917         for (sceneit = m_scenes.begin();sceneit != m_scenes.end(); sceneit++)
00918         // for each scene, call the proceed functions
00919         {
00920             KX_Scene* scene = *sceneit;
00921             KX_Camera* cam = scene->GetActiveCamera();
00922 
00923             // pass the scene's worldsettings to the rasterizer
00924             SetWorldSettings(scene->GetWorldInfo());
00925         
00926             if (scene->IsClearingZBuffer())
00927                 m_rasterizer->ClearDepthBuffer();
00928 
00929             //pass the scene, for picking and raycasting (shadows)
00930             m_rendertools->SetAuxilaryClientInfo(scene);
00931 
00932             // do the rendering
00933             //RenderFrame(scene);
00934             RenderFrame(scene, cam);
00935 
00936             list<class KX_Camera*>* cameras = scene->GetCameras();          
00937     
00938             // Draw the scene once for each camera with an enabled viewport
00939             list<KX_Camera*>::iterator it = cameras->begin();
00940             while(it != cameras->end())
00941             {
00942                 if((*it)->GetViewport())
00943                 {
00944                     if (scene->IsClearingZBuffer())
00945                         m_rasterizer->ClearDepthBuffer();
00946             
00947                     m_rendertools->SetAuxilaryClientInfo(scene);
00948             
00949                     // do the rendering
00950                     RenderFrame(scene, (*it));
00951                 }
00952                 
00953                 it++;
00954             }
00955             PostRenderScene(scene);
00956         }
00957     } // if(m_rasterizer->Stereo())
00958 
00959     EndFrame();
00960 }
00961 
00962 
00963 
00964 void KX_KetsjiEngine::RequestExit(int exitrequestmode)
00965 {
00966     m_exitcode = exitrequestmode;
00967 }
00968 
00969 
00970 
00971 void KX_KetsjiEngine::SetNameNextGame(const STR_String& nextgame)
00972 {
00973     m_exitstring = nextgame;
00974 }
00975 
00976 
00977 
00978 int KX_KetsjiEngine::GetExitCode()
00979 {
00980     // if a gameactuator has set an exitcode or if there are no scenes left
00981     if (!m_exitcode)
00982     {
00983         if (m_scenes.begin()==m_scenes.end())
00984             m_exitcode = KX_EXIT_REQUEST_NO_SCENES_LEFT;
00985     }
00986     
00987     // check if the window has been closed.
00988     if(!m_exitcode)
00989     {
00990         //if(!m_canvas->Check()) {
00991         //  m_exitcode = KX_EXIT_REQUEST_OUTSIDE;
00992         //}
00993     }
00994 
00995     return m_exitcode;
00996 }
00997 
00998 
00999 
01000 const STR_String& KX_KetsjiEngine::GetExitString()
01001 {
01002     return m_exitstring;
01003 }
01004 
01005 
01006 void KX_KetsjiEngine::SetBackGround(KX_WorldInfo* wi)
01007 {
01008     if (wi->hasWorld())
01009     {
01010         if (m_drawingmode == RAS_IRasterizer::KX_TEXTURED)
01011         {   
01012             m_rasterizer->SetBackColor(
01013                 wi->getBackColorRed(),
01014                 wi->getBackColorGreen(),
01015                 wi->getBackColorBlue(),
01016                 0.0
01017             );
01018         }
01019     }
01020 }
01021 
01022 
01023 
01024 void KX_KetsjiEngine::SetWorldSettings(KX_WorldInfo* wi)
01025 {
01026     if (wi->hasWorld())
01027     {
01028         // ...
01029         m_rasterizer->SetAmbientColor(
01030             wi->getAmbientColorRed(),
01031             wi->getAmbientColorGreen(),
01032             wi->getAmbientColorBlue()
01033         );
01034 
01035         if (m_drawingmode >= RAS_IRasterizer::KX_SOLID)
01036         {   
01037             if (wi->hasMist())
01038             {
01039                 m_rasterizer->SetFog(
01040                     wi->getMistStart(),
01041                     wi->getMistDistance(),
01042                     wi->getMistColorRed(),
01043                     wi->getMistColorGreen(),
01044                     wi->getMistColorBlue()
01045                 );
01046             }
01047         }
01048     }
01049 }
01050 
01051 
01052 
01053 void KX_KetsjiEngine::SetDrawType(int drawingmode)
01054 {
01055     m_drawingmode = drawingmode;
01056 }
01057 
01058 
01059     
01060 void KX_KetsjiEngine::EnableCameraOverride(const STR_String& forscene)
01061 {
01062     m_overrideCam = true;
01063     m_overrideSceneName = forscene;
01064 }
01065 
01066 
01067 
01068 void KX_KetsjiEngine::SetCameraZoom(float camzoom)
01069 {
01070     m_cameraZoom = camzoom;
01071 }
01072 
01073 
01074 
01075 void KX_KetsjiEngine::SetCameraOverrideUseOrtho(bool useOrtho)
01076 {
01077     m_overrideCamUseOrtho = useOrtho;
01078 }
01079 
01080 
01081 
01082 void KX_KetsjiEngine::SetCameraOverrideProjectionMatrix(const MT_CmMatrix4x4& mat)
01083 {
01084     m_overrideCamProjMat = mat;
01085 }
01086 
01087 
01088 void KX_KetsjiEngine::SetCameraOverrideViewMatrix(const MT_CmMatrix4x4& mat)
01089 {
01090     m_overrideCamViewMat = mat;
01091 }
01092 
01093 void KX_KetsjiEngine::SetCameraOverrideClipping(float near, float far)
01094 {
01095     m_overrideCamNear = near;
01096     m_overrideCamFar = far;
01097 }
01098 
01099 void KX_KetsjiEngine::SetCameraOverrideLens(float lens)
01100 {
01101     m_overrideCamLens = lens;
01102 }
01103 
01104 void KX_KetsjiEngine::GetSceneViewport(KX_Scene *scene, KX_Camera* cam, RAS_Rect& area, RAS_Rect& viewport)
01105 {
01106     // In this function we make sure the rasterizer settings are upto
01107     // date. We compute the viewport so that logic
01108     // using this information is upto date.
01109 
01110     // Note we postpone computation of the projection matrix
01111     // so that we are using the latest camera position.
01112     if (cam->GetViewport()) {
01113         RAS_Rect userviewport;
01114 
01115         userviewport.SetLeft(cam->GetViewportLeft()); 
01116         userviewport.SetBottom(cam->GetViewportBottom());
01117         userviewport.SetRight(cam->GetViewportRight());
01118         userviewport.SetTop(cam->GetViewportTop());
01119 
01120         // Don't do bars on user specified viewport
01121         RAS_FrameSettings settings = scene->GetFramingType();
01122         if(settings.FrameType() == RAS_FrameSettings::e_frame_bars)
01123             settings.SetFrameType(RAS_FrameSettings::e_frame_extend);
01124 
01125         RAS_FramingManager::ComputeViewport(
01126             scene->GetFramingType(),
01127             userviewport,
01128             viewport
01129         );
01130 
01131         area = userviewport;
01132     }
01133     else if ( !m_overrideCam || (scene->GetName() != m_overrideSceneName) ||  m_overrideCamUseOrtho ) {
01134         RAS_FramingManager::ComputeViewport(
01135             scene->GetFramingType(),
01136             m_canvas->GetDisplayArea(),
01137             viewport
01138         );
01139 
01140         area = m_canvas->GetDisplayArea();
01141     } else {
01142         viewport.SetLeft(0); 
01143         viewport.SetBottom(0);
01144         viewport.SetRight(int(m_canvas->GetWidth()));
01145         viewport.SetTop(int(m_canvas->GetHeight()));
01146 
01147         area = m_canvas->GetDisplayArea();
01148     }
01149 }
01150 
01151 void KX_KetsjiEngine::RenderShadowBuffers(KX_Scene *scene)
01152 {
01153     CListValue *lightlist = scene->GetLightList();
01154     int i, drawmode;
01155 
01156     m_rendertools->SetAuxilaryClientInfo(scene);
01157 
01158     for(i=0; i<lightlist->GetCount(); i++) {
01159         KX_GameObject *gameobj = (KX_GameObject*)lightlist->GetValue(i);
01160 
01161         KX_LightObject *light = (KX_LightObject*)gameobj;
01162 
01163         light->Update();
01164 
01165         if(m_drawingmode == RAS_IRasterizer::KX_TEXTURED && light->HasShadowBuffer()) {
01166             /* make temporary camera */
01167             RAS_CameraData camdata = RAS_CameraData();
01168             KX_Camera *cam = new KX_Camera(scene, scene->m_callbacks, camdata, true, true);
01169             cam->SetName("__shadow__cam__");
01170 
01171             MT_Transform camtrans;
01172 
01173             /* switch drawmode for speed */
01174             drawmode = m_rasterizer->GetDrawingMode();
01175             m_rasterizer->SetDrawingMode(RAS_IRasterizer::KX_SHADOW);
01176 
01177             /* binds framebuffer object, sets up camera .. */
01178             light->BindShadowBuffer(m_rasterizer, cam, camtrans);
01179 
01180             /* update scene */
01181             scene->CalculateVisibleMeshes(m_rasterizer, cam, light->GetShadowLayer());
01182 
01183             /* render */
01184             m_rasterizer->ClearDepthBuffer();
01185             scene->RenderBuckets(camtrans, m_rasterizer, m_rendertools);
01186 
01187             /* unbind framebuffer object, restore drawmode, free camera */
01188             light->UnbindShadowBuffer(m_rasterizer);
01189             m_rasterizer->SetDrawingMode(drawmode);
01190             cam->Release();
01191         }
01192     }
01193 }
01194     
01195 // update graphics
01196 void KX_KetsjiEngine::RenderFrame(KX_Scene* scene, KX_Camera* cam)
01197 {
01198     bool override_camera;
01199     RAS_Rect viewport, area;
01200     float nearfrust, farfrust, focallength;
01201 //  KX_Camera* cam = scene->GetActiveCamera();
01202     
01203     if (!cam)
01204         return;
01205     GetSceneViewport(scene, cam, area, viewport);
01206 
01207     // store the computed viewport in the scene
01208     scene->SetSceneViewport(viewport);  
01209 
01210     // set the viewport for this frame and scene
01211     m_canvas->SetViewPort(viewport.GetLeft(), viewport.GetBottom(),
01212         viewport.GetRight(), viewport.GetTop());    
01213     
01214     // see KX_BlenderMaterial::Activate
01215     //m_rasterizer->SetAmbient();
01216     m_rasterizer->DisplayFog();
01217 
01218     override_camera = m_overrideCam && (scene->GetName() == m_overrideSceneName);
01219     override_camera = override_camera && (cam->GetName() == "__default__cam__");
01220 
01221     if (override_camera && m_overrideCamUseOrtho) {
01222         m_rasterizer->SetProjectionMatrix(m_overrideCamProjMat);
01223         if (!cam->hasValidProjectionMatrix()) {
01224             // needed to get frustrum planes for culling
01225             MT_Matrix4x4 projmat;
01226             projmat.setValue(m_overrideCamProjMat.getPointer());
01227             cam->SetProjectionMatrix(projmat);
01228         }
01229     } else if (cam->hasValidProjectionMatrix())
01230     {
01231         m_rasterizer->SetProjectionMatrix(cam->GetProjectionMatrix());
01232     } else
01233     {
01234         RAS_FrameFrustum frustum;
01235         bool orthographic = !cam->GetCameraData()->m_perspective;
01236         nearfrust = cam->GetCameraNear();
01237         farfrust = cam->GetCameraFar();
01238         focallength = cam->GetFocalLength();
01239         MT_Matrix4x4 projmat;
01240 
01241         if(override_camera) {
01242             nearfrust = m_overrideCamNear;
01243             farfrust = m_overrideCamFar;
01244         }
01245 
01246         if (orthographic) {
01247 
01248             RAS_FramingManager::ComputeOrtho(
01249                 scene->GetFramingType(),
01250                 area,
01251                 viewport,
01252                 cam->GetScale(),
01253                 nearfrust,
01254                 farfrust,
01255                 cam->GetSensorFit(),
01256                 frustum
01257             );
01258             if (!cam->GetViewport()) {
01259                 frustum.x1 *= m_cameraZoom;
01260                 frustum.x2 *= m_cameraZoom;
01261                 frustum.y1 *= m_cameraZoom;
01262                 frustum.y2 *= m_cameraZoom;
01263             }
01264             projmat = m_rasterizer->GetOrthoMatrix(
01265                 frustum.x1, frustum.x2, frustum.y1, frustum.y2, frustum.camnear, frustum.camfar);
01266 
01267         } else {
01268             RAS_FramingManager::ComputeFrustum(
01269                 scene->GetFramingType(),
01270                 area,
01271                 viewport,
01272                 cam->GetLens(),
01273                 cam->GetSensorWidth(),
01274                 cam->GetSensorHeight(),
01275                 cam->GetSensorFit(),
01276                 nearfrust,
01277                 farfrust,
01278                 frustum
01279             );
01280 
01281             if (!cam->GetViewport()) {
01282                 frustum.x1 *= m_cameraZoom;
01283                 frustum.x2 *= m_cameraZoom;
01284                 frustum.y1 *= m_cameraZoom;
01285                 frustum.y2 *= m_cameraZoom;
01286             }
01287             projmat = m_rasterizer->GetFrustumMatrix(
01288                 frustum.x1, frustum.x2, frustum.y1, frustum.y2, frustum.camnear, frustum.camfar, focallength);
01289         }
01290         cam->SetProjectionMatrix(projmat);
01291         
01292         // Otherwise the projection matrix for each eye will be the same...
01293         if (!orthographic && m_rasterizer->Stereo())
01294             cam->InvalidateProjectionMatrix();
01295     }
01296 
01297     MT_Transform camtrans(cam->GetWorldToCamera());
01298     MT_Matrix4x4 viewmat(camtrans);
01299     
01300     m_rasterizer->SetViewMatrix(viewmat, cam->NodeGetWorldOrientation(), cam->NodeGetWorldPosition(), cam->GetCameraData()->m_perspective);
01301     cam->SetModelviewMatrix(viewmat);
01302 
01303     // The following actually reschedules all vertices to be
01304     // redrawn. There is a cache between the actual rescheduling
01305     // and this call though. Visibility is imparted when this call
01306     // runs through the individual objects.
01307 
01308     m_logger->StartLog(tc_scenegraph, m_kxsystem->GetTimeInSeconds(), true);
01309     SG_SetActiveStage(SG_STAGE_CULLING);
01310 
01311     scene->CalculateVisibleMeshes(m_rasterizer,cam);
01312 
01313     m_logger->StartLog(tc_rasterizer, m_kxsystem->GetTimeInSeconds(), true);
01314     SG_SetActiveStage(SG_STAGE_RENDER);
01315 
01316 #ifdef WITH_PYTHON
01317     // Run any pre-drawing python callbacks
01318     scene->RunDrawingCallbacks(scene->GetPreDrawCB());
01319 #endif
01320 
01321     scene->RenderBuckets(camtrans, m_rasterizer, m_rendertools);
01322 
01323     //render all the font objects for this scene
01324     RenderFonts(scene);
01325     
01326     if (scene->GetPhysicsEnvironment())
01327         scene->GetPhysicsEnvironment()->debugDrawWorld();
01328 }
01329 
01330 void KX_KetsjiEngine::RenderFonts(KX_Scene* scene)
01331 {
01332     list<class KX_FontObject*>* fonts = scene->GetFonts();
01333     
01334     list<KX_FontObject*>::iterator it = fonts->begin();
01335     while(it != fonts->end())
01336     {
01337         (*it)->DrawText();
01338         ++it;
01339     }
01340 }
01341 
01342 /*
01343 To run once per scene
01344 */
01345 void KX_KetsjiEngine::PostRenderScene(KX_Scene* scene)
01346 {
01347     // We need to first make sure our viewport is correct (enabling multiple viewports can mess this up)
01348     m_canvas->SetViewPort(0, 0, m_canvas->GetWidth(), m_canvas->GetHeight());
01349 
01350     m_rendertools->MotionBlur(m_rasterizer);
01351     scene->Render2DFilters(m_canvas);
01352 #ifdef WITH_PYTHON
01353     scene->RunDrawingCallbacks(scene->GetPostDrawCB()); 
01354 #endif
01355     m_rasterizer->FlushDebugShapes();
01356 }
01357 
01358 void KX_KetsjiEngine::StopEngine()
01359 {
01360     if (m_bInitialized)
01361     {
01362 
01363         if (m_animation_record)
01364         {
01365 //          printf("TestHandlesPhysicsObjectToAnimationIpo\n");
01366             m_sceneconverter->TestHandlesPhysicsObjectToAnimationIpo();
01367         }
01368 
01369         KX_SceneList::iterator sceneit;
01370         for (sceneit = m_scenes.begin();sceneit != m_scenes.end() ; sceneit++)
01371         {
01372             KX_Scene* scene = *sceneit;
01373             m_sceneconverter->RemoveScene(scene);
01374         }   
01375         m_scenes.clear();
01376 
01377         // cleanup all the stuff        
01378         m_rasterizer->Exit();
01379     }
01380 }
01381 
01382 // Scene Management is able to switch between scenes
01383 // and have several scene's running in parallel
01384 void KX_KetsjiEngine::AddScene(KX_Scene* scene)
01385 { 
01386     m_scenes.push_back(scene);
01387     PostProcessScene(scene);
01388     SceneListsChanged();
01389 }
01390 
01391 
01392 
01393 void KX_KetsjiEngine::PostProcessScene(KX_Scene* scene)
01394 {
01395     bool override_camera = (m_overrideCam && (scene->GetName() == m_overrideSceneName));
01396 
01397     SG_SetActiveStage(SG_STAGE_SCENE);
01398 
01399     // if there is no activecamera, or the camera is being
01400     // overridden we need to construct a temporarily camera
01401     if (!scene->GetActiveCamera() || override_camera)
01402     {
01403         KX_Camera* activecam = NULL;
01404 
01405         RAS_CameraData camdata = RAS_CameraData();
01406         if (override_camera)
01407         {
01408             camdata.m_lens = m_overrideCamLens;
01409             camdata.m_clipstart = m_overrideCamNear;
01410             camdata.m_clipend = m_overrideCamFar;
01411             
01412             camdata.m_perspective= !m_overrideCamUseOrtho;
01413         }
01414         activecam = new KX_Camera(scene,KX_Scene::m_callbacks,camdata);
01415         activecam->SetName("__default__cam__");
01416     
01417             // set transformation
01418         if (override_camera) {
01419             const MT_CmMatrix4x4& cammatdata = m_overrideCamViewMat;
01420             MT_Transform trans = MT_Transform(cammatdata.getPointer());
01421             MT_Transform camtrans;
01422             camtrans.invert(trans);
01423             
01424             activecam->NodeSetLocalPosition(camtrans.getOrigin());
01425             activecam->NodeSetLocalOrientation(camtrans.getBasis());
01426             activecam->NodeUpdateGS(0);
01427         } else {
01428             activecam->NodeSetLocalPosition(MT_Point3(0.0, 0.0, 0.0));
01429             activecam->NodeSetLocalOrientation(MT_Vector3(0.0, 0.0, 0.0));
01430             activecam->NodeUpdateGS(0);
01431         }
01432 
01433         scene->AddCamera(activecam);
01434         scene->SetActiveCamera(activecam);
01435         scene->GetObjectList()->Add(activecam->AddRef());
01436         scene->GetRootParentList()->Add(activecam->AddRef());
01437         //done with activecam
01438         activecam->Release();
01439     }
01440     
01441     scene->UpdateParents(0.0);
01442 }
01443 
01444 
01445 
01446 void KX_KetsjiEngine::RenderDebugProperties()
01447 {
01448     STR_String debugtxt;
01449     int xcoord = 10;    // mmmm, these constants were taken from blender source
01450     int ycoord = 14;    // to 'mimic' behaviour
01451 
01452     float tottime = m_logger->GetAverage();
01453     if (tottime < 1e-6f) {
01454         tottime = 1e-6f;
01455     }
01456 
01457     // Set viewport to entire canvas
01458     RAS_Rect viewport;
01459     m_canvas->SetViewPort(0, 0, int(m_canvas->GetWidth()), int(m_canvas->GetHeight()));
01460     
01461     /* Framerate display */
01462     if (m_show_framerate) {
01463         debugtxt.Format("swap : %.3f (%.3f frames per second)", tottime, 1.0/tottime);
01464         m_rendertools->RenderText2D(RAS_IRenderTools::RAS_TEXT_PADDED, 
01465                                     debugtxt.Ptr(),
01466                                     xcoord,
01467                                     ycoord, 
01468                                     m_canvas->GetWidth() /* RdV, TODO ?? */, 
01469                                     m_canvas->GetHeight() /* RdV, TODO ?? */);
01470         ycoord += 14;
01471     }
01472 
01473     /* Profile and framerate display */
01474     if (m_show_profile)
01475     {       
01476         for (int j = tc_first; j < tc_numCategories; j++)
01477         {
01478             debugtxt.Format(m_profileLabels[j]);
01479             m_rendertools->RenderText2D(RAS_IRenderTools::RAS_TEXT_PADDED, 
01480                                         debugtxt.Ptr(),
01481                                         xcoord,ycoord,
01482                                         m_canvas->GetWidth(), 
01483                                         m_canvas->GetHeight());
01484             double time = m_logger->GetAverage((KX_TimeCategory)j);
01485             debugtxt.Format("%.3fms (%2.2f %%)", time*1000.f, time/tottime * 100.f);
01486             m_rendertools->RenderText2D(RAS_IRenderTools::RAS_TEXT_PADDED, 
01487                                         debugtxt.Ptr(),
01488                                         xcoord + 60 ,ycoord,
01489                                         m_canvas->GetWidth(), 
01490                                         m_canvas->GetHeight());
01491             ycoord += 14;
01492         }
01493     }
01494 
01495     /* Property display*/
01496     if (m_show_debug_properties && m_propertiesPresent)
01497     {
01498         KX_SceneList::iterator sceneit;
01499         for (sceneit = m_scenes.begin();sceneit != m_scenes.end() ; sceneit++)
01500         {
01501             KX_Scene* scene = *sceneit;
01502             /* the 'normal' debug props */
01503             vector<SCA_DebugProp*>& debugproplist = scene->GetDebugProperties();
01504             
01505             for (vector<SCA_DebugProp*>::iterator it = debugproplist.begin();
01506                  !(it==debugproplist.end());it++)
01507             {
01508                 CValue* propobj = (*it)->m_obj;
01509                 STR_String objname = propobj->GetName();
01510                 STR_String propname = (*it)->m_name;
01511                 if (propname == "__state__")
01512                 {
01513                     // reserve name for object state
01514                     KX_GameObject* gameobj = static_cast<KX_GameObject*>(propobj);
01515                     unsigned int state = gameobj->GetState();
01516                     debugtxt = objname + "." + propname + " = ";
01517                     bool first = true;
01518                     for (int statenum=1;state;state >>= 1, statenum++)
01519                     {
01520                         if (state & 1)
01521                         {
01522                             if (!first)
01523                             {
01524                                 debugtxt += ",";
01525                             }
01526                             debugtxt += STR_String(statenum);
01527                             first = false;
01528                         }
01529                     }
01530                     m_rendertools->RenderText2D(RAS_IRenderTools::RAS_TEXT_PADDED, 
01531                                                     debugtxt.Ptr(),
01532                                                     xcoord,
01533                                                     ycoord,
01534                                                     m_canvas->GetWidth(),
01535                                                     m_canvas->GetHeight());
01536                     ycoord += 14;
01537                 }
01538                 else
01539                 {
01540                     CValue* propval = propobj->GetProperty(propname);
01541                     if (propval)
01542                     {
01543                         STR_String text = propval->GetText();
01544                         debugtxt = objname + "." + propname + " = " + text;
01545                         m_rendertools->RenderText2D(RAS_IRenderTools::RAS_TEXT_PADDED, 
01546                                                     debugtxt.Ptr(),
01547                                                     xcoord,
01548                                                     ycoord,
01549                                                     m_canvas->GetWidth(),
01550                                                     m_canvas->GetHeight());
01551                         ycoord += 14;
01552                     }
01553                 }
01554             }
01555         }
01556     }
01557 }
01558 
01559 
01560 KX_SceneList* KX_KetsjiEngine::CurrentScenes()
01561 {
01562     return &m_scenes;   
01563 }
01564 
01565 
01566 
01567 KX_Scene* KX_KetsjiEngine::FindScene(const STR_String& scenename)
01568 {
01569     KX_SceneList::iterator sceneit = m_scenes.begin();
01570 
01571     // bit risky :) better to split the second clause 
01572     while ( (sceneit != m_scenes.end()) 
01573             && ((*sceneit)->GetName() != scenename))
01574     {
01575         sceneit++;
01576     }
01577 
01578     return ((sceneit == m_scenes.end()) ? NULL : *sceneit); 
01579 }
01580 
01581 
01582 
01583 void KX_KetsjiEngine::ConvertAndAddScene(const STR_String& scenename,bool overlay)
01584 {
01585     // only add scene when it doesn't exist!
01586     if (FindScene(scenename))
01587     {
01588         STR_String tmpname = scenename;
01589         printf("warning: scene %s already exists, not added!\n",tmpname.Ptr());
01590     }
01591     else
01592     {
01593         if (overlay)
01594         {
01595             m_addingOverlayScenes.insert(scenename);
01596         }
01597         else
01598         {
01599             m_addingBackgroundScenes.insert(scenename);
01600         }
01601     }
01602 }
01603 
01604 
01605 
01606 
01607 void KX_KetsjiEngine::RemoveScene(const STR_String& scenename)
01608 {
01609     if (FindScene(scenename))
01610     {
01611         m_removingScenes.insert(scenename);
01612     }
01613     else
01614     {
01615 //      STR_String tmpname = scenename;
01616         std::cout << "warning: scene " << scenename << " does not exist, not removed!" << std::endl;
01617     }
01618 }
01619 
01620 
01621 
01622 void KX_KetsjiEngine::RemoveScheduledScenes()
01623 {
01624     if (m_removingScenes.size())
01625     {
01626         set<STR_String>::iterator scenenameit;
01627         for (scenenameit=m_removingScenes.begin();scenenameit != m_removingScenes.end();scenenameit++)
01628         {
01629             STR_String scenename = *scenenameit;
01630 
01631             KX_SceneList::iterator sceneit;
01632             for (sceneit = m_scenes.begin();sceneit != m_scenes.end() ; sceneit++)
01633             {
01634                 KX_Scene* scene = *sceneit;
01635                 if (scene->GetName()==scenename)
01636                 {
01637                     m_sceneconverter->RemoveScene(scene);
01638                     m_scenes.erase(sceneit);
01639                     break;
01640                 }
01641             }   
01642         }
01643         m_removingScenes.clear();
01644     }
01645 }
01646 
01647 KX_Scene* KX_KetsjiEngine::CreateScene(Scene *scene)
01648 {
01649     KX_Scene* tmpscene = new KX_Scene(m_keyboarddevice,
01650                                       m_mousedevice,
01651                                       m_networkdevice,
01652                                       scene->id.name+2,
01653                                       scene,
01654                                       m_canvas);
01655 
01656     m_sceneconverter->ConvertScene(tmpscene,
01657                               m_rendertools,
01658                               m_canvas);
01659 
01660     return tmpscene;
01661 }
01662 
01663 KX_Scene* KX_KetsjiEngine::CreateScene(const STR_String& scenename)
01664 {
01665     Scene *scene = m_sceneconverter->GetBlenderSceneForName(scenename);
01666     return CreateScene(scene);
01667 }
01668 
01669 void KX_KetsjiEngine::AddScheduledScenes()
01670 {
01671     set<STR_String>::iterator scenenameit;
01672 
01673     if (m_addingOverlayScenes.size())
01674     {
01675         for (scenenameit = m_addingOverlayScenes.begin();
01676             scenenameit != m_addingOverlayScenes.end();
01677             scenenameit++)
01678         {
01679             STR_String scenename = *scenenameit;
01680             KX_Scene* tmpscene = CreateScene(scenename);
01681             m_scenes.push_back(tmpscene);
01682             PostProcessScene(tmpscene);
01683         }
01684         m_addingOverlayScenes.clear();
01685     }
01686     
01687     if (m_addingBackgroundScenes.size())
01688     {
01689         for (scenenameit = m_addingBackgroundScenes.begin();
01690             scenenameit != m_addingBackgroundScenes.end();
01691             scenenameit++)
01692         {
01693             STR_String scenename = *scenenameit;
01694             KX_Scene* tmpscene = CreateScene(scenename);
01695             m_scenes.insert(m_scenes.begin(),tmpscene);
01696             PostProcessScene(tmpscene);
01697 
01698         }
01699         m_addingBackgroundScenes.clear();
01700     }
01701 }
01702 
01703 
01704 
01705 void KX_KetsjiEngine::ReplaceScene(const STR_String& oldscene,const STR_String& newscene)
01706 {
01707     m_replace_scenes.insert(std::make_pair(oldscene,newscene));
01708 }
01709 
01710 // replace scene is not the same as removing and adding because the
01711 // scene must be in exact the same place (to maintain drawingorder)
01712 // (nzc) - should that not be done with a scene-display list? It seems
01713 // stupid to rely on the mem allocation order...
01714 void KX_KetsjiEngine::ReplaceScheduledScenes()
01715 {
01716     if (m_replace_scenes.size())
01717     {
01718         set<pair<STR_String,STR_String> >::iterator scenenameit;
01719         
01720         for (scenenameit = m_replace_scenes.begin();
01721             scenenameit != m_replace_scenes.end();
01722             scenenameit++)
01723         {
01724             STR_String oldscenename = (*scenenameit).first;
01725             STR_String newscenename = (*scenenameit).second;
01726             int i=0;
01727             /* Scenes are not supposed to be included twice... I think */
01728             KX_SceneList::iterator sceneit;
01729             for (sceneit = m_scenes.begin();sceneit != m_scenes.end() ; sceneit++)
01730             {
01731                 KX_Scene* scene = *sceneit;
01732                 if (scene->GetName() == oldscenename)
01733                 {
01734                     m_sceneconverter->RemoveScene(scene);
01735                     KX_Scene* tmpscene = CreateScene(newscenename);
01736                     m_scenes[i]=tmpscene;
01737                     PostProcessScene(tmpscene);
01738                 }
01739                 i++;
01740             }
01741         }
01742         m_replace_scenes.clear();
01743     }   
01744 }
01745 
01746 
01747 
01748 void KX_KetsjiEngine::SuspendScene(const STR_String& scenename)
01749 {
01750     KX_Scene*  scene = FindScene(scenename);
01751     if (scene) scene->Suspend();
01752 }
01753 
01754 
01755 
01756 void KX_KetsjiEngine::ResumeScene(const STR_String& scenename)
01757 {
01758     KX_Scene*  scene = FindScene(scenename);
01759     if (scene) scene->Resume();
01760 }
01761 
01762 
01763 
01764 void KX_KetsjiEngine::SetUseFixedTime(bool bUseFixedTime)
01765 {
01766     m_bFixedTime = bUseFixedTime;
01767 }
01768 
01769 
01770 void    KX_KetsjiEngine::SetAnimRecordMode(bool animation_record, int startFrame)
01771 {
01772     m_animation_record = animation_record;
01773     if (animation_record)
01774     {
01775         //when recording physics keyframes, always run at a fixed framerate
01776         m_bFixedTime = true;
01777     }
01778     m_currentFrame = startFrame;
01779 }
01780 
01781 bool KX_KetsjiEngine::GetUseFixedTime(void) const
01782 {
01783     return m_bFixedTime;
01784 }
01785 
01786 double KX_KetsjiEngine::GetSuspendedDelta()
01787 {
01788     return m_suspendeddelta;
01789 }
01790 
01791 double KX_KetsjiEngine::GetTicRate()
01792 {
01793     return m_ticrate;
01794 }
01795 
01796 void KX_KetsjiEngine::SetTicRate(double ticrate)
01797 {
01798     m_ticrate = ticrate;
01799 }
01800 
01801 int KX_KetsjiEngine::GetMaxLogicFrame()
01802 {
01803     return m_maxLogicFrame;
01804 }
01805 
01806 void KX_KetsjiEngine::SetMaxLogicFrame(int frame)
01807 {
01808     m_maxLogicFrame = frame;
01809 }
01810 
01811 int KX_KetsjiEngine::GetMaxPhysicsFrame()
01812 {
01813     return m_maxPhysicsFrame;
01814 }
01815 
01816 void KX_KetsjiEngine::SetMaxPhysicsFrame(int frame)
01817 {
01818     m_maxPhysicsFrame = frame;
01819 }
01820 
01821 bool KX_KetsjiEngine::GetRestrictAnimationFPS()
01822 {
01823     return m_restrict_anim_fps;
01824 }
01825 
01826 void KX_KetsjiEngine::SetRestrictAnimationFPS(bool bRestrictAnimFPS)
01827 {
01828     m_restrict_anim_fps = bRestrictAnimFPS;
01829 }
01830 
01831 double KX_KetsjiEngine::GetAnimFrameRate()
01832 {
01833     return m_anim_framerate;
01834 }
01835 
01836 double KX_KetsjiEngine::GetClockTime(void) const
01837 {
01838     return m_clockTime;
01839 }
01840 
01841 double KX_KetsjiEngine::GetFrameTime(void) const
01842 {
01843     return m_frameTime;
01844 }
01845 
01846 double KX_KetsjiEngine::GetRealTime(void) const
01847 {
01848     return m_kxsystem->GetTimeInSeconds();
01849 }
01850 
01851 void KX_KetsjiEngine::SetAnimFrameRate(double framerate)
01852 {
01853     m_anim_framerate = framerate;
01854 }
01855 
01856 double KX_KetsjiEngine::GetAverageFrameRate()
01857 {
01858     return m_average_framerate;
01859 }
01860 
01861 void KX_KetsjiEngine::SetExitKey(short key)
01862 {
01863     m_exitkey = key;
01864 }
01865 
01866 short KX_KetsjiEngine::GetExitKey()
01867 {
01868     return m_exitkey;
01869 }
01870 
01871 void KX_KetsjiEngine::SetTimingDisplay(bool frameRate, bool profile, bool properties)
01872 {
01873     m_show_framerate = frameRate;
01874     m_show_profile = profile;
01875     m_show_debug_properties = properties;
01876 }
01877 
01878 
01879 
01880 void KX_KetsjiEngine::GetTimingDisplay(bool& frameRate, bool& profile, bool& properties) const
01881 {
01882     frameRate = m_show_framerate;
01883     profile = m_show_profile;
01884     properties = m_show_debug_properties;
01885 }
01886 
01887 
01888 
01889 void KX_KetsjiEngine::ProcessScheduledScenes(void)
01890 {
01891     // Check whether there will be changes to the list of scenes
01892     if (m_addingOverlayScenes.size() ||
01893         m_addingBackgroundScenes.size() ||
01894         m_replace_scenes.size() ||
01895         m_removingScenes.size()) {
01896 
01897         // Change the scene list
01898         ReplaceScheduledScenes();
01899         RemoveScheduledScenes();
01900         AddScheduledScenes();
01901 
01902         // Notify
01903         SceneListsChanged();
01904     }
01905 }
01906 
01907 
01908 
01909 void KX_KetsjiEngine::SceneListsChanged(void)
01910 {
01911     m_propertiesPresent = false;
01912     KX_SceneList::iterator sceneit = m_scenes.begin();
01913     while ((sceneit != m_scenes.end()) && (!m_propertiesPresent))
01914     {
01915         KX_Scene* scene = *sceneit;
01916         vector<SCA_DebugProp*>& debugproplist = scene->GetDebugProperties();    
01917         m_propertiesPresent = !debugproplist.empty();
01918         sceneit++;
01919     }
01920 }
01921 
01922 
01923 void KX_KetsjiEngine::SetHideCursor(bool hideCursor)
01924 {
01925     m_hideCursor = hideCursor;
01926 }
01927 
01928 
01929 bool KX_KetsjiEngine::GetHideCursor(void) const
01930 {
01931     return m_hideCursor;
01932 }
01933 
01934 
01935 void KX_KetsjiEngine::SetUseOverrideFrameColor(bool overrideFrameColor)
01936 {
01937     m_overrideFrameColor = overrideFrameColor;
01938 }
01939 
01940 
01941 bool KX_KetsjiEngine::GetUseOverrideFrameColor(void) const
01942 {
01943     return m_overrideFrameColor;
01944 }
01945 
01946 
01947 void KX_KetsjiEngine::SetOverrideFrameColor(float r, float g, float b)
01948 {
01949     m_overrideFrameColorR = r;
01950     m_overrideFrameColorG = g;
01951     m_overrideFrameColorB = b;
01952 }
01953 
01954 
01955 void KX_KetsjiEngine::GetOverrideFrameColor(float& r, float& g, float& b) const
01956 {
01957     r = m_overrideFrameColorR;
01958     g = m_overrideFrameColorG;
01959     b = m_overrideFrameColorB;
01960 }
01961 
01962 void KX_KetsjiEngine::SetGlobalSettings(GlobalSettings* gs)
01963 {
01964     m_globalsettings.matmode = gs->matmode;
01965     m_globalsettings.glslflag = gs->glslflag;
01966 }
01967 
01968 GlobalSettings* KX_KetsjiEngine::GetGlobalSettings(void)
01969 {
01970     return &m_globalsettings;
01971 }
01972