// Helper function which checks whether the current context is registered in an active renderer node static inline bool IsContextRegistered(VisRenderContext_cl *pContext) { for (int iRendererNode=0; iRendererNode<Vision::Renderer.GetRendererNodeCount(); iRendererNode++) { IVRendererNode *pNode = Vision::Renderer.GetRendererNode(iRendererNode); if (pNode) { if (pNode->IsContextRegistered(pContext)) return true; } } return false; }
void VTimeOfDayComponent::UpdateParent() { IVTimeOfDay *pTimeOfDayInterface = Vision::Renderer.GetTimeOfDayHandler(); if (pTimeOfDayInterface == NULL) return; VisObject3D_cl *pOwnerObject = (VisObject3D_cl *)m_pOwner; VASSERT(pOwnerObject); hkvVec3 vDirection(hkvNoInitialization); pTimeOfDayInterface->GetSunDirection(vDirection); vDirection.normalizeIfNotZero(); if (AttachmentType == TIMEOFDAY_ATTACHMENT_MOONLIGHTSOURCE) { vDirection = -vDirection; } else if(AttachmentType == TIMEOFDAY_ATTACHMENT_SUNBACKLIGHTSOURCE) { vDirection.x = -vDirection.x; vDirection.y = -vDirection.y; } if (AttachmentType != TIMEOFDAY_ATTACHMENT_ENABLEDATNIGHTLIGHTSOURCE) { pOwnerObject->SetDirection(vDirection); } if (AttachmentType == TIMEOFDAY_ATTACHMENT_CORONALIGHTSOURCE) { // TODO (multiple renderer nodes) IVRendererNode *pRenderer = Vision::Renderer.GetRendererNode(0); float fNear, fFar; pRenderer->GetReferenceContext()->GetClipPlanes(fNear, fFar); hkvVec3 vCamPos = pRenderer->GetReferenceContext()->GetCamera()->GetPosition(); hkvVec3 vCoronaPos = -vDirection; vCoronaPos *= 0.95f * fFar; vCoronaPos += vCamPos; pOwnerObject->SetPosition(vCoronaPos); } if (m_bIsLightClass) { VisLightSource_cl *pLight = (VisLightSource_cl*)m_pOwner; VColorRef sunColor = pTimeOfDayInterface->GetSunColor(); bool bSwitchable = (AttachmentType == TIMEOFDAY_ATTACHMENT_ENABLEDATNIGHTLIGHTSOURCE); float fBelowHorizonMultiplier = hkvMath::pow (hkvMath::Max(-vDirection.z+0.1f, 0.0f), bSwitchable ? 1.0f : 0.1f); fBelowHorizonMultiplier = hkvMath::Min(1.0f, fBelowHorizonMultiplier); if (bSwitchable && fBelowHorizonMultiplier < 1.0f && fBelowHorizonMultiplier > 0.f) { pLight->SetColor(m_iColor); pLight->SetMultiplier(Intensity * (1.0f - fBelowHorizonMultiplier)); } else if (AttachmentType == TIMEOFDAY_ATTACHMENT_SUNLIGHTSOURCE) { pLight->SetColor(sunColor); pLight->SetMultiplier(Intensity * fBelowHorizonMultiplier); } else if ((AttachmentType == TIMEOFDAY_ATTACHMENT_MOONLIGHTSOURCE) || (AttachmentType == TIMEOFDAY_ATTACHMENT_SUNBACKLIGHTSOURCE)) { // TODO VColorRef negativeColor = V_RGBA_WHITE - sunColor; pLight->SetColor(negativeColor); pLight->SetMultiplier(Intensity * fBelowHorizonMultiplier * 0.333f); } else if (AttachmentType == TIMEOFDAY_ATTACHMENT_CORONALIGHTSOURCE) { hkvVec3 vSunColorFloat = sunColor.ToFloat(); float fLargestComponent = hkvMath::Max(hkvMath::Max(vSunColorFloat.x, vSunColorFloat.y), vSunColorFloat.z); if (fLargestComponent <= 0.0f) fLargestComponent = 1.0f; sunColor.FromFloat(vSunColorFloat * (1.0f / fLargestComponent)); pLight->SetColor(sunColor * fBelowHorizonMultiplier); pLight->SetMultiplier(0.0f); } } }
//Update, render and display the scene bool VisionApp_cl::Run() { static bool bInsideGameLoop = false; // Make sure the game loop isn't executed recursively. In Windows builds, this could for example happen if a shown message box triggers // a repaint message. This case needs to be handled by the code calling the game loop. if(bInsideGameLoop) { // We can't report this error in a form that could trigger a message box, so reporting a warning and breaking the debugger is the best we can do. Vision::Error.Warning("VisionApp_cl::Run called recursively! This is usually caused by triggering a repaint from inside the game loop."); #if defined(HK_DEBUG) VDBGBREAK; #endif // Just skip the game loop - this may invoke weird behavior if the calling code expects the game loop to complete, but is better // than recursing return true; } bInsideGameLoop = true; //Update the scene m_iUpdateSceneTickCount = 1; // by default one simulation tick per loop if (m_spUpdateSceneController!=NULL) m_iUpdateSceneTickCount = m_spUpdateSceneController->GetUpdateTickCount(); for (int i=0;i<m_iUpdateSceneTickCount;i++) { OnUpdateScene(); if (i<m_iUpdateSceneTickCount-1) // the last one is performed after rendering { OnFinishScene(); UpdateTimer(); } } // update everything that has to be done once per loop rather than per simulation steps OnFrameUpdatePreRender(); Vision::Profiling.Update(); VASSERT_MSG(Vision::Renderer.GetRendererNode(0) != NULL, "No renderer node is set. This isn't supported anymore. Use a VSimpleRendererNode instead of registering the main context globally."); // If in debug build, perform a sanity check - no context registered with the main context should also be registered // with a renderer node! #ifdef HK_DEBUG_SLOW static bool bContextErrorShown = false; if (!bContextErrorShown) { int iContextCount = Vision::Contexts.GetContextCount(); for (int iContext = 0; iContext < iContextCount; iContext++) { for (int iRendererNode=0; iRendererNode<V_MAX_RENDERER_NODES; iRendererNode++) { IVRendererNode *pNode = Vision::Renderer.GetRendererNode(iRendererNode); VisRenderContext_cl* pContext = Vision::Contexts.GetContext(iContext); if (pNode != NULL && pNode->IsContextRegistered(Vision::Contexts.GetContext(iContext))) { Vision::Error.Warning("Context %s (%p) is registered globally AND in renderer node %s (%p). This may be intended, but it is most likely a porting issue introduced by porting from a pre-8.0 version of the Vision Engine.", pContext->GetName(), pContext, pNode->GetTypeId()->m_lpszClassName, pNode); bContextErrorShown = true; } } } } #endif { INSERT_PERF_MARKER_SCOPE("BeginRendering"); // Inform the renderer that we are now going to start rendering Vision::Renderer.BeginRendering(); Vision::Callbacks.BeginRendering.TriggerCallbacks(); } Vision::Renderer.SetCurrentRendererNode(NULL); VisRendererNodeDataObject_cl data(&Vision::Callbacks.OnRendererNodeSwitching, NULL); Vision::Callbacks.OnRendererNodeSwitching.TriggerCallbacks(&data); { INSERT_PERF_MARKER_SCOPE("PreRendererNodeContexts"); Vision::Contexts.PerformVisibilityTests(); Vision::Contexts.RenderContexts(-FLT_MAX, VIS_RENDERCONTEXTPRIORITY_SCENE); } { for (int iRendererNode=0; iRendererNode<V_MAX_RENDERER_NODES; iRendererNode++) { IVRendererNode *pNode = Vision::Renderer.GetRendererNode(iRendererNode); if (pNode != NULL && pNode->GetRenderingEnabled()) { char buffer[192]; sprintf(buffer, "RendererNode %d (%s)", iRendererNode, pNode->GetTypeId()->m_lpszClassName); INSERT_PERF_MARKER_SCOPE(buffer); VASSERT_MSG(pNode->IsInitialized(), "Renderer Node is registered and enabled, but not initialized"); pNode->Execute(); } } } { INSERT_PERF_MARKER_SCOPE("PostRendererNodeContexts"); Vision::Renderer.SetCurrentRendererNode(NULL); Vision::Contexts.RenderContexts(VIS_RENDERCONTEXTPRIORITY_SCENE, FLT_MAX); } { INSERT_PERF_MARKER_SCOPE("EndRendering"); // Tell the renderer that we have finished rendering Vision::Callbacks.EndRendering.TriggerCallbacks(); Vision::Renderer.EndRendering(); } //Finish the scene - the last tick is performed here if (m_iUpdateSceneTickCount>0) OnFinishScene(); // update everything that has to be done once per loop rather than per simulation steps OnFrameUpdatePostRender(); //Display the scene Vision::Callbacks.OnBeforeSwapBuffers.TriggerCallbacks(); #ifdef WIN32 if (m_bUpdateScreen) // only supported on win32 #endif Vision::Video.UpdateScreen(); if (m_iUpdateSceneTickCount>0) // same as for OnFinishScene UpdateTimer(); bInsideGameLoop = false; return !WantsToQuit(); }
void VTimeOfDayComponent::UpdateParent() { VTimeOfDay *pTimeOfDayInterface = (VTimeOfDay*)Vision::Renderer.GetTimeOfDayHandler(); if (pTimeOfDayInterface == NULL) return; VisObject3D_cl *pOwnerObject = (VisObject3D_cl *)m_pOwner; VASSERT(pOwnerObject); hkvVec3 vDirection(hkvNoInitialization); pTimeOfDayInterface->GetSunDirection(vDirection); // The Moon and back light direction is calculated from the Sun direction if (AttachmentType == TIMEOFDAY_ATTACHMENT_MOONLIGHTSOURCE) { vDirection = -vDirection; } else if(AttachmentType == TIMEOFDAY_ATTACHMENT_SUNBACKLIGHTSOURCE) { vDirection.x = -vDirection.x; vDirection.y = -vDirection.y; } if (AttachmentType != TIMEOFDAY_ATTACHMENT_ENABLEDATNIGHTLIGHTSOURCE) { pOwnerObject->SetDirection(vDirection); } if (AttachmentType == TIMEOFDAY_ATTACHMENT_CORONALIGHTSOURCE) { // TODO (multiple renderer nodes) IVRendererNode *pRenderer = Vision::Renderer.GetRendererNode(0); float fNear, fFar; pRenderer->GetReferenceContext()->GetClipPlanes(fNear, fFar); hkvVec3 vCamPos = pRenderer->GetReferenceContext()->GetCamera()->GetPosition(); hkvVec3 vCoronaPos = -vDirection; vCoronaPos *= 0.95f * fFar; vCoronaPos += vCamPos; pOwnerObject->SetPosition(vCoronaPos); } // Set the color and intensity of the light if (m_bIsLightClass) { VisLightSource_cl *pLight = (VisLightSource_cl*)m_pOwner; VColorRef color; float intensity = 0.0f; switch (AttachmentType) { case TIMEOFDAY_ATTACHMENT_ENABLEDATNIGHTLIGHTSOURCE: { color = m_iColor; const float fMarginNearHorizon = 0.1f; //10% - Margin above the horizon to switch lights ON/OFF const float fBelowHorizonMultiplier = hkvMath::Max(-vDirection.z + fMarginNearHorizon, 0.0f); intensity = 1.0f - hkvMath::Min(1.0f, fBelowHorizonMultiplier); break; } case TIMEOFDAY_ATTACHMENT_CORONALIGHTSOURCE: { color = pTimeOfDayInterface->GetSunColor(); hkvVec3 vSunColorFloat = color.ToFloat(); float fLargestComponent = hkvMath::Max(hkvMath::Max(vSunColorFloat.x, vSunColorFloat.y), vSunColorFloat.z); if (fLargestComponent > 0.0f) { color.FromFloat(vSunColorFloat / fLargestComponent); } intensity = 0.0f; break; } case TIMEOFDAY_ATTACHMENT_SUNLIGHTSOURCE: { color = pTimeOfDayInterface->GetSunColor(); intensity = pTimeOfDayInterface->GetSunIntensity(); break; } case TIMEOFDAY_ATTACHMENT_SUNBACKLIGHTSOURCE: { color = pTimeOfDayInterface->GetBackLightColor(); intensity = pTimeOfDayInterface->GetBackLightIntensity(); break; } case TIMEOFDAY_ATTACHMENT_MOONLIGHTSOURCE: { color = pTimeOfDayInterface->GetMoonColor(); intensity = pTimeOfDayInterface->GetMoonIntensity(); break; } default: VASSERT_MSG(0,"Unknown time of day attachment type"); } pLight->SetColor(color); pLight->SetMultiplier(intensity * Intensity); } }