|
Blender
V2.59
|
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