Blender V2.61 - r43446
|
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