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