/** * @brief * Performs picking by using the given line start and end positions */ bool Picking::PerformPicking(PickingResult &cPickingResult, SceneContainer &cContainer, const Vector3 &vLineStartPos, const Vector3 &vLineEndPos, Cull::Enum nCull) { // Initialize the picking result m_pPickingResult = &cPickingResult; cPickingResult.m_pSceneNode = nullptr; cPickingResult.m_nGeometry = 0; cPickingResult.m_nTriangle = 0; cPickingResult.m_vPoint = Vector3::Zero; cPickingResult.m_pSceneContainer = &cContainer; cPickingResult.m_vLineStartPos = vLineStartPos; cPickingResult.m_fNearestSquaredDistance = -1.0f; // Trace line SQLine *pQuery = static_cast<SQLine*>(cContainer.CreateQuery("PLScene::SQLine")); if (pQuery) { pQuery->SignalSceneNode.Connect(EventHandlerSceneNode); pQuery->GetLine().Set(vLineStartPos, vLineEndPos); pQuery->SetCull(nCull); pQuery->PerformQuery(); cContainer.DestroyQuery(*pQuery); } // Was something picked? if (cPickingResult.m_pSceneNode) { // Ensure that the picking distance is not greater than the possible maximum if ((vLineEndPos-vLineStartPos).GetSquaredLength() >= cPickingResult.m_fNearestSquaredDistance) return (cPickingResult.m_pSceneNode != nullptr); } // Nothing (in range) was picked return false; }
/** * @brief * Loads/reloads the sound */ void SNMSound::Load() { // Destroy currently used sound source Source *pSS = static_cast<Source*>(m_pSoundSourceHandler->GetResource()); if (pSS) delete pSS; // Get the PL sound container this scene node is in SceneContainer *pContainer = GetSceneNode().GetContainer(); while (pContainer && !pContainer->IsInstanceOf("PLSound::SCSound")) pContainer = pContainer->GetContainer(); if (pContainer) { SoundManager *pSoundManager = static_cast<SCSound*>(pContainer)->GetSoundManager(); if (pSoundManager) { Source *pSoundSource = pSoundManager->CreateSoundSource(pSoundManager->CreateSoundBuffer(m_sSound, (GetFlags() & Stream) != 0)); m_pSoundSourceHandler->SetResource(pSoundSource); pSoundSource->SetAttribute(Source::Position, GetSceneNode().GetTransform().GetPosition()); pSoundSource->SetVolume(m_fVolume); pSoundSource->Set2D((GetFlags() & No3D) != 0); pSoundSource->SetLooping(!(GetFlags() & NoLoop)); pSoundSource->SetPitch(m_fPitch); pSoundSource->SetReferenceDistance(m_fReferenceDistance); pSoundSource->SetMaxDistance(m_fMaxDistance); pSoundSource->SetRolloffFactor(m_fRolloffFactor); OnPosition(); if (!(GetFlags() & NoStartPlayback)) pSoundSource->Play(); } } }
/** * @brief * Restarts the game */ void Application67::Restart() { // Get the scene container SceneContainer *pSceneContainer = GetScene(); if (pSceneContainer) { // Clean up your scene container pSceneContainer->Clear(); // Create the camera (we need the camera to control the post processing) SceneNode *pCamera = pSceneContainer->Create("PLScene::SNCamera", "FixedCamera"); if (pCamera && pCamera->IsInstanceOf("PLScene::SNCamera")) { // Add a post process scene node modifier from the 'PLPostProcessEffects'-plugin pCamera->AddModifier("PLPostProcessEffects::SNMPostProcessOldFilm", "Flags='Inactive'"); // Make this to our main scene camera SetCamera(reinterpret_cast<SNCamera*>(pCamera)); } // Create an UFO from mars attacking the earth :D pSceneContainer->Create("SNUFO", "Ufo"); // Create the gun (the player) pSceneContainer->Create("SNGun", "Gun", "Position=\"157 155\""); } }
//[-------------------------------------------------------] //[ Private virtual PLEngine::EngineApplication functions ] //[-------------------------------------------------------] void Application60::OnCreateScene(SceneContainer &cContainer) { // Create a camera scene node SceneNode *pCameraSceneNode = cContainer.Create("PLScene::SNCamera", "FreeCamera", "Position=\"1 2 -3\" Rotation=\"25 210 0\""); if (pCameraSceneNode && pCameraSceneNode->IsInstanceOf("PLScene::SNCamera")) { // Make this to our main scene camera SetCamera(reinterpret_cast<SNCamera*>(pCameraSceneNode)); } // Create a scene node with the soldier mesh which can produce a shadow SceneNode *pSoldierSceneNode = cContainer.Create("PLScene::SNMesh", "Soldier", "Flags=\"CastShadow|ReceiveShadow\" Position=\"0.0 0.1 -5.0\" Scale=\"0.008 0.008 0.008\" Mesh=\"Data/Meshes/Soldier.mesh\""); if (pSoldierSceneNode) { // Add a scene node modifier which will constantly rotate the soldier pSoldierSceneNode->AddModifier("PLScene::SNMRotationLinearAnimation", "Velocity=\"0 10 0\""); // Add a scene node modifier which will playback the animation named "walk_0" letting the soldier walk pSoldierSceneNode->AddModifier("PLScene::SNMMeshAnimation", "Name=\"walk_0\""); // Add a scene node modifier which will animate the morph target named "blink" letting the soldier blink from time to time pSoldierSceneNode->AddModifier("PLScene::SNMMeshMorphBlink", "Name=\"blink\""); } // Create a light source scene node to illuminate the scene - this light can cast shadows cContainer.Create("PLScene::SNPointLight", "Light", "Flags=\"CastShadow|Flares|Corona\" Range=\"4\""); // Create the floor scene node cContainer.Create("PLScene::SNMesh", "Floor", "Flags=\"CastShadow|ReceiveShadow\" Position=\"0.0 0.0 -5.0\" Rotation=\"0.0 180.0 0.0\" Scale=\"4.0 0.1 4.0\" Mesh=\"Default\""); // Set scene container SetScene(&cContainer); }
/** * @brief * Returns the sound container this sound is in */ SCSound *SNMSound::GetSoundContainer() const { // Get the PL sound container this scene node is in SceneContainer *pContainer = GetSceneNode().GetContainer(); while (pContainer && !pContainer->IsInstanceOf("PLSound::SCSound")) pContainer = pContainer->GetContainer(); // Done return (pContainer && pContainer->IsInstanceOf("PLSound::SCSound")) ? static_cast<SCSound*>(pContainer) : nullptr; }
//[-------------------------------------------------------] //[ Protected virtual PLFrontendQt::QPLSceneContext functions ] //[-------------------------------------------------------] void MySceneContext::OnCreateScene(SceneContainer &cContainer) { // Create a camera SceneNode *pCamera = cContainer.Create("PLScene::SNCamera", "FreeCamera", "Position=\"1 2 -3\" Rotation=\"25 0 0\""); if (pCamera && pCamera->IsInstanceOf("PLScene::SNCamera")) SetCamera(reinterpret_cast<SNCamera*>(pCamera)); // Create the floor cContainer.Create("PLScene::SNMesh", "Floor", "Position=\"0.0 0.0 5.0\" Rotation=\"0.0 180.0 0.0\" Scale=\"4.0 0.1 4.0\" Mesh=\"Default\""); // Set scene container SetScene(&cContainer); }
//[-------------------------------------------------------] //[ Private virtual PLEngine::EngineApplication functions ] //[-------------------------------------------------------] void Application67::OnCreateScene(SceneContainer &cContainer) { // Create a scene container with our 'concrete sound scene' using the default sound API SceneNode *pSceneContainerNode = cContainer.Create("PLSound::SCSound", "SoundScene"); if (pSceneContainerNode && pSceneContainerNode->IsInstanceOf("PLScene::SceneContainer")) { SceneContainer *pSceneContainer = static_cast<SceneContainer*>(pSceneContainerNode); // Protect this important container! pSceneContainer->SetProtected(true); // Populate the scene container // Setup scene surface painter SurfacePainter *pPainter = GetPainter(); if (pPainter && pPainter->IsInstanceOf("PLScene::SPScene")) { SPScene *pSPScene = static_cast<SPScene*>(pPainter); pSPScene->SetRootContainer(cContainer.GetContainer()); pSPScene->SetSceneContainer(pSceneContainer); // Get the scene context SceneContext *pSceneContext = GetSceneContext(); if (pSceneContext) { // Create us a scene renderer SceneRenderer *pSceneRenderer = pSceneContext->GetSceneRendererManager().Create("2DGame"); if (pSceneRenderer) { // Add begin scene renderer pass pSceneRenderer->Create("PLCompositing::SRPBegin", "Begin", "TextureFormat=\"R8G8B8A8\" Flags=\"Inactive\""); // Add our own scene renderer pass pSceneRenderer->Create("SRP2DGame", "2DGame"); // Add post processing scene renderer pass pSceneRenderer->Create("PLCompositing::SRPPostProcessing", "PostProcessing"); // Add end scene renderer pass pSceneRenderer->Create("PLCompositing::SRPEnd", "End"); // Make this scene renderer to the default scene renderer of our scene surface painter pSPScene->SetDefaultSceneRenderer(pSceneRenderer->GetName()); } } } // Set scene container SetScene(pSceneContainer); // Start the game Restart(); } }
/** * @brief * Updates the text of the time scale text node */ void Application61::UpdateTimeScaleTextNode() { // Get the scene SceneContainer *pSceneContainer = GetScene(); if (pSceneContainer) { // Get the scene info text container SceneContainer *pInfoTextContainer = static_cast<SceneContainer*>(pSceneContainer->GetByName("Parent.InfoText")); if (pInfoTextContainer) { // Get the time scale text scene node SceneNode *pInfoTextNode = pInfoTextContainer->GetByName("TimeScale"); if (pInfoTextNode) pInfoTextNode->SetAttribute("Text", PLT("1/2/0=Decrease/increase/reset timescale (current: ") + Timing::GetInstance()->GetTimeScaleFactor() + ')'); } } }
/** * @brief * Returns the target position within the container space of the owner node */ bool SNMRotationTarget::GetTargetPosition(Vector3 &vPos) const { // Target scene node given? if (Target.Get().GetLength()) { // Get the target scene node const SceneNode *pTarget; if (GetSceneNode().GetContainer()) pTarget = GetSceneNode().GetContainer()->GetByName(Target.Get()); else { // This must be the root :() pTarget = static_cast<const SceneContainer&>(GetSceneNode()).GetByName(Target.Get()); } if (pTarget) { // Set the position of the attached node vPos = pTarget->GetTransform().GetPosition(); // Are we in luck and the target is within the same container as the owner node? if (GetSceneNode().GetContainer() != pTarget->GetContainer()) { // Nope, we have to translate the position into the correct space :( SceneContainer *pContainer = pTarget->GetContainer(); while (pContainer) { vPos *= pContainer->GetTransform().GetMatrix(); pContainer = pContainer->GetContainer(); } // To container space of the owner node pContainer = GetSceneNode().GetContainer(); Stack<SceneContainer*> lstStack; while (pContainer) { lstStack.Push(pContainer); pContainer = pContainer->GetContainer(); } while (lstStack.GetNumOfElements()) { pContainer = lstStack.Top(); lstStack.Pop(); vPos *= pContainer->GetTransform().GetInverseMatrix(); } } // Done return true; } } // Error - no valid target scene node, no target rotation :( return false; }
/** * @brief * Clears the scene, after calling this method the scene is empty */ void EngineApplication::ClearScene() { // Get the scene container holding our scene SceneContainer *pContainer = GetScene(); if (pContainer) { // Clear the old scene pContainer->Clear(); // Cleanup the scene context right now to ensure that all 'delete this'-marked scene nodes are really gone! // If this is not done, we may get problems with for example the names of dynamic textures because there may // occur name conflicts if multiple render-to-texture scene containers want to render into a same named texture... // Topics like 'the new scene is using resources that are already loaded in' must be handled on another level, e.g. // by delaying the unloading of currently unreferenced resources. if (m_pSceneContext) m_pSceneContext->Cleanup(); } }
/** * @brief * Returns the gravity vector */ Vector3 PGPhysics::GetGravity() const { // Get the PL physics world this scene node is in SceneContainer *pContainer = GetContainer(); while (pContainer && !pContainer->IsInstanceOf("PLPhysics::SCPhysicsWorld")) pContainer = pContainer->GetContainer(); // Get the gravity vector Vector3 vGravity; if (pContainer && static_cast<SCPhysicsWorld*>(pContainer)->GetWorld()) static_cast<SCPhysicsWorld*>(pContainer)->GetWorld()->GetGravity(vGravity); else vGravity.SetXYZ(0.0f, -9.81f, 0.0f); // Return the gravity vector return vGravity; }
//[-------------------------------------------------------] //[ Private virtual PLEngine::EngineApplication functions ] //[-------------------------------------------------------] void Application66::OnCreateScene(SceneContainer &cContainer) { // Set scene container flags cContainer.SetFlags(SceneNode::NoCulling); // Setup scene surface painter SurfacePainter *pPainter = GetPainter(); if (pPainter && pPainter->IsInstanceOf("PLScene::SPScene")) { SPScene *pSPScene = static_cast<SPScene*>(pPainter); pSPScene->SetRootContainer(cContainer.GetContainer()); pSPScene->SetSceneContainer(&cContainer); } // Within the parent container... SceneContainer *pContainer = cContainer.GetContainer(); if (pContainer) { // Create a 'ingame'-GUI scene node const SNGui *pGuiSceneNode = static_cast<SNGui*>(pContainer->Create("PLFrontendPLGui::SNGui", "GUI")); if (pGuiSceneNode) { // Setup the GUI Gui *pGui = pGuiSceneNode->GetGui(); if (pGui) { // Create the GUI font if (!GuiFont) { GuiFont = new Font(*pGui); GuiFont->LoadFromFile("Data/Fonts/LinLibertine_Re-2.7.9.9.otf", 18); } // Set GUI options pGui->SetMouseVisible(false); // Create ingame GUI container m_pIngameGui = new IngameGui(*this, pGui->GetRootWidget()); m_pIngameGui->SetSize(Vector2i(1024, 768)); m_pIngameGui->SetBackgroundColor(PLGraphics::Color4::Transparent); m_pIngameGui->SetFocus(); m_pIngameGui->SetVisible(true); } } } // Set scene container SetScene(&cContainer); }
/** * @brief * Called when a control event has occurred */ void Application61::OnControl(Control &cControl) { // Is it a button? if (cControl.GetType() == ControlButton && static_cast<Button&>(cControl).IsPressed()) { // Check whether the escape key was pressed if (cControl.GetName() == "KeyboardEscape") { // Shut down the application Exit(0); } else { // Get current time difference Timing *pTimer = Timing::GetInstance(); const float fTimeScaleFactor = pTimer->GetTimeScaleFactor(); // Check button if (cControl.GetName() == "Keyboard1") { // Decrease timescale pTimer->SetTimeScaleFactor(fTimeScaleFactor - 0.1f); if (pTimer->GetTimeScaleFactor() < 0.1f) pTimer->SetTimeScaleFactor(0.1f); } else if (cControl.GetName() == "Keyboard2") { // Increase timescale pTimer->SetTimeScaleFactor(fTimeScaleFactor + 0.1f); if (pTimer->GetTimeScaleFactor() > 4.0f) pTimer->SetTimeScaleFactor(4.0f); } else if (cControl.GetName() == "Keyboard3") { // Reset timescale pTimer->SetTimeScaleFactor(); } // Time scale factor changed? if (fTimeScaleFactor != pTimer->GetTimeScaleFactor()) { // Update the time scale text node UpdateTimeScaleTextNode(); // Update the pitch variable of the sound container using the time scale factor SceneContainer *pSceneContainer = GetScene(); if (pSceneContainer) pSceneContainer->SetAttribute("Pitch", pTimer->GetTimeScaleFactor()); } } } }
/** * @brief * Post draw all scene nodes recursive */ void SPScene::DrawPost(Renderer &cRenderer, SceneContainer &cContainer) { // Get the scene container (can be a null pointer) SceneContainer *pContainer = GetSceneContainer(); // Draw parent container if (&cContainer != pContainer) cContainer.DrawPost(cRenderer); // Loop through all nodes for (uint32 i=0; i<cContainer.GetNumOfElements(); i++) { SceneNode *pNode = cContainer.GetByIndex(i); if (pNode != pContainer && pNode->IsVisible() && (pNode->GetDrawFunctionFlags() & SceneNode::UseDrawPost)) { if (pNode->IsContainer()) DrawPost(cRenderer, static_cast<SceneContainer&>(*pNode)); else pNode->DrawPost(cRenderer); } } }
/** * @brief * Returns the default scene renderer */ SceneRenderer *SPScene::GetDefaultSceneRenderer() const { // Get/load the scene renderer SceneRenderer *pSceneRenderer = m_pDefaultSceneRendererHandler->GetResource(); if (!pSceneRenderer && m_sDefaultSceneRenderer.GetLength()) { // Get the root scene container SceneContainer *pRootContainer = GetRootContainer(); if (pRootContainer) { // Get the scene context SceneContext *pSceneContext = pRootContainer->GetSceneContext(); if (pSceneContext) { pSceneRenderer = pSceneContext->GetSceneRendererManager().LoadResource(m_sDefaultSceneRenderer); m_pDefaultSceneRendererHandler->SetResource(pSceneRenderer); } } } // Return the scene renderer return pSceneRenderer; }
/** * @brief * Function that is called to create the application's scene container */ void EngineApplication::OnCreateScene(SceneContainer &cContainer) { // [TODO] Load 'm_sSceneFilename' if provided // Set scene container flags cContainer.SetFlags(SceneNode::NoCulling); // Setup scene surface painter SurfacePainter *pPainter = GetPainter(); if (pPainter && pPainter->IsInstanceOf("PLScene::SPScene")) { SPScene *pSPScene = static_cast<SPScene*>(pPainter); pSPScene->SetRootContainer(cContainer.GetContainer()); pSPScene->SetSceneContainer(&cContainer); } // Configure scene and set the currently used application camera SetCamera(SceneCreator::ConfigureScene(cContainer, "PLEngine::SceneCreatorDefault")); // Set scene container SetScene(&cContainer); }
//[-------------------------------------------------------] //[ Private virtual PLEngine::EngineApplication functions ] //[-------------------------------------------------------] void Application64::OnCreateScene(SceneContainer &cContainer) { // Create a camera SceneNode *pCamera = cContainer.Create("PLScene::SNCamera", "FreeCamera", "Position=\"1 2 -3\" Rotation=\"25 210 0\""); if (pCamera && pCamera->IsInstanceOf("PLScene::SNCamera")) { // Make this to our main scene camera SetCamera(reinterpret_cast<SNCamera*>(pCamera)); } // Create a scene node with the soldier mesh - in debug mode, show some fancy technical visualizations SceneNode *pSceneNode = cContainer.Create("PLScene::SNMesh", "Soldier", "Position=\"0.0 0.1 -5.0\" Scale=\"0.008 0.008 0.008\" Mesh=\"Data/Meshes/Soldier.mesh\" DebugFlags=\"DebugShowWireframe|DebugShowJoints|DebugShowJointNames|DebugShowSkeleton\""); if (pSceneNode) { // Rotate the soldier pSceneNode->AddModifier("PLScene::SNMRotationLinearAnimation", "Velocity=\"0 10 0\""); // Playback the animation named "walk_0" letting the soldier walk pSceneNode->AddModifier("PLScene::SNMMeshAnimation", "Name=\"walk_0\""); // Animate the morph target named "blink" letting the soldier blink from time to time pSceneNode->AddModifier("PLScene::SNMMeshMorphBlink", "Name=\"blink\""); } // Create the floor cContainer.Create("PLScene::SNMesh", "Floor", "Position=\"0.0 0.0 -5.0\" Rotation=\"0.0 180.0 0.0\" Scale=\"4.0 0.1 4.0\" Mesh=\"Default\""); // Setup scene surface painter SurfacePainter *pPainter = GetPainter(); if (pPainter && pPainter->IsInstanceOf("PLScene::SPScene")) { SPScene *pSPScene = static_cast<SPScene*>(pPainter); pSPScene->SetRootContainer(cContainer.GetContainer()); pSPScene->SetSceneContainer(&cContainer); } // Set scene container SetScene(&cContainer); // Create the picking component m_pMyPicking = new MyPicking(*this); }
//[-------------------------------------------------------] //[ Protected virtual PLScene::SceneApplication functions ] //[-------------------------------------------------------] void EngineApplication::OnCreateRootScene() { // Get the scene context SceneContext *pSceneContext = GetSceneContext(); if (pSceneContext) { // First, create the scene root container which holds the scene container with our 'concrete' scene within it SceneContainer *pRootContainer = pSceneContext->GetRoot() ? static_cast<SceneContainer*>(pSceneContext->GetRoot()->Create("PLScene::SceneContainer", "RootScene")) : nullptr; if (pRootContainer) { // Protect this important container! pRootContainer->SetProtected(true); // Create a scene container with our 'concrete scene' SceneNode *pSceneContainerNode = pRootContainer->Create("PLScene::SceneContainer", "Scene"); if (pSceneContainerNode && pSceneContainerNode->IsInstanceOf("PLScene::SceneContainer")) { SceneContainer *pSceneContainer = static_cast<SceneContainer*>(pSceneContainerNode); // Protect this important container! pSceneContainer->SetProtected(true); // Connect event handler if (pSceneContainerNode->IsInstanceOf("PLScene::SceneContainer")) static_cast<SceneContainer*>(pSceneContainerNode)->SignalLoadProgress.Connect(EventHandlerLoadProgress); // Create the 'concrete scene' OnCreateScene(*pSceneContainer); } // Create scene node for engine information SceneNode *pSceneNode = pRootContainer->Create("PLEngine::SNEngineInformation"); if (pSceneNode) pSceneNode->SetActive(m_bEditModeEnabled); // Create console scene node - using the console command 'timescale <value>' we // can change the scene time (slowdown or accelerate) pSceneNode = pRootContainer->Create("PLEngine::SNConsole"); if (pSceneNode && pSceneNode->GetClass()->IsDerivedFrom("PLEngine::SNConsoleBase")) { SNConsoleBase *pConsole = static_cast<SNConsoleBase*>(pSceneNode); // Register default commands pConsole->RegisterCommand(0, "quit", "", "", Functor<void, ConsoleCommand &>(&EngineApplication::ConsoleCommandQuit, this)); pConsole->RegisterCommand(0, "exit", "", "", Functor<void, ConsoleCommand &>(&EngineApplication::ConsoleCommandQuit, this)); pConsole->RegisterCommand(0, "bye", "", "", Functor<void, ConsoleCommand &>(&EngineApplication::ConsoleCommandQuit, this)); pConsole->RegisterCommand(0, "logout", "", "", Functor<void, ConsoleCommand &>(&EngineApplication::ConsoleCommandQuit, this)); // Set active state pConsole->SetActive(m_bEditModeEnabled); } } // Set the root scene SetRootScene(pRootContainer); } }
/** * @brief * Sets whether or not edit mode is enabled */ void EngineApplication::SetEditModeEnabled(bool bEnabled) { // State change? if (m_bEditModeEnabled != bEnabled) { // Backup the new state m_bEditModeEnabled = bEnabled; // Get the root scene SceneContainer *pRootScene = GetRootScene(); if (pRootScene) { // Enable/disable standard edit features from the PixelLight scene graph (if the user hasn't changed anything :) SceneNode *pSceneNode = pRootScene->GetByName("PLEngine::SNEngineInformation0"); if (pSceneNode) pSceneNode->SetActive(bEnabled); pSceneNode = pRootScene->GetByName("PLEngine::SNConsole0"); if (pSceneNode) pSceneNode->SetActive(bEnabled); } // Setup log level Log::GetInstance()->SetLogLevel(static_cast<uint8>(m_bEditModeEnabled ? Log::Debug : Log::Info)); } }
//[-------------------------------------------------------] //[ Private virtual PLCore::AbstractFrontend functions ] //[-------------------------------------------------------] void Application60::OnUpdate() { // One important word at the beginning: DON'T COPYCAT THIS! // The following is 'just' a simple demonstration how the scene graph 'can' be used. It's // definitely not good to update your scene nodes in the way you can see within this function. // Its quite to intricate, inflexible and not performant. Use for example a scene node modifier // added to your scene node (in this case 'the white light') for this job! // Call base implementation EngineApplication::OnUpdate(); // Get the scene container with our 'concrete scene' SceneContainer *pSceneContainer = GetScene(); if (pSceneContainer) { // Get the scene node with the name 'Light' (our 'white light') SceneNode *pLightSceneNode = pSceneContainer->GetByName("Light"); if (pLightSceneNode) { // This variable is used for the light animation. Its just static you keep the implementation // for a good sample overview completely within this function. static float fLightTimer = 0.0f; // Get a new fancy light position const Vector3 vPosition(Math::Sin(fLightTimer), Math::Sin(fLightTimer)/2+2, -(Math::Cos(fLightTimer)+5)); // We set the current light position using the RTTI class interface. This is quite comfortable and // universal because you haven't to care about the concrete class type - just set the variable values. pLightSceneNode->SetAttribute("Position", Var<Vector3>(vPosition)); // More efficient // Another way by using strings: // pLightSceneNode->SetAttribute("Position", vPosition.ToString()); // More generic // For highly performance critical situations it's recommend to avoid using these RTTI // functions to set your variables and use the concrete provided class interfaces instead. // Update the light timer by using the time difference between the last and the current frame fLightTimer += Timing::GetInstance()->GetTimeDifference(); } } }
/** * @brief * Function that is called to create the application's root scene */ void SceneApplication::OnCreateRootScene() { // [TODO] Load 'm_sSceneFilename' if provided // Is there a scene context? if (m_pSceneContext) { // First, create the scene root container which holds the scene container with our 'concrete' scene within it SceneContainer *pRootContainer = m_pSceneContext->GetRoot() ? static_cast<SceneContainer*>(m_pSceneContext->GetRoot()->Create("PLScene::SceneContainer", "RootScene")) : nullptr; if (pRootContainer) { // Protect this important container! pRootContainer->SetProtected(true); // Create a scene container with our 'concrete scene' SceneNode *pSceneContainerNode = pRootContainer->Create("PLScene::SceneContainer", "Scene"); if (pSceneContainerNode && pSceneContainerNode->IsContainer()) { // Protect this important container! pSceneContainerNode->SetProtected(true); } } // Set the root scene SetRootScene(pRootContainer); } }
//[-------------------------------------------------------] //[ Private virtual PLEngine::EngineApplication functions ] //[-------------------------------------------------------] void Application70::OnCreateScene(SceneContainer &cContainer) { // Create a camera SceneNode *pCamera = cContainer.Create("PLScene::SNCamera", "FreeCamera", "Position=\"1 2 -3\" Rotation=\"25 210 0\""); if (pCamera && pCamera->IsInstanceOf("PLScene::SNCamera")) { // Make this to our main scene camera SetCamera(reinterpret_cast<SNCamera*>(pCamera)); // Add a controller modifier so we can look around the camera by using a default control pCamera->AddModifier("PLEngine::SNMEgoLookController"); // Add a controller modifier so we can move around the camera by using a default control pCamera->AddModifier("PLEngine::SNMMoveController"); } // Create the floor cContainer.Create("PLScene::SNMesh", "Floor", "Position=\"0 0 -5\" Scale=\"4 0.1 4\" Mesh=\"Default\""); // Create an instance of the fire particle effect scene node cContainer.Create("SNFireSample", "Fire", "Position=\"0.5 0.3 -5\" Scale=\"0.1 0.1 0.1\""); // Create an instance of the basic particle effect scene node cContainer.Create("SNBasicSample", "Basic", "Position=\"-0.5 0.1 -8\" Scale=\"0.5 0.5 0.5\""); // Create an instance of the gravitation particle effect scene node cContainer.Create("SNGravitationSample", "Gravitation", "Position=\"-1 1 -5\" Scale=\"0.5 0.5 0.5\""); // Create an instance of the galaxy particle effect scene node cContainer.Create("SNGalaxySample", "Galaxy", "Position=\"-3 0.5 -8\" Scale=\"0.5 0.5 0.5\""); // Setup scene surface painter SurfacePainter *pPainter = GetPainter(); if (pPainter && pPainter->IsInstanceOf("PLScene::SPScene")) { SPScene *pSPScene = static_cast<SPScene*>(pPainter); pSPScene->SetRootContainer(cContainer.GetContainer()); pSPScene->SetSceneContainer(&cContainer); } // Set scene container SetScene(&cContainer); }
bool EngineApplication::LoadScene(const String &sFilename) { // Get the scene container holding our scene SceneContainer *pContainer = GetScene(); if (!pContainer) return false; // Error! (should NEVER happen...) // Disable the ingame GUI SceneNode *pGui = pContainer->GetContainer()->GetByName("GUI"); if (pGui) pGui->SetActive(false); // Clear the scene, after calling this method the scene is empty ClearScene(); // Load the scene bool bResult = pContainer->LoadByFilename(sFilename); if (bResult) { // Set a null pointer camera and default scene renderer m_sDefaultSceneRenderer = ""; m_sSceneRendererVariables = ""; m_sClearColor = ""; m_sStartCamera = ""; m_pFirstFoundCamera = nullptr; m_bHasLoadScreen = false; // Get scene surface painter SurfacePainter *pPainter = GetPainter(); if (pPainter && pPainter->IsInstanceOf("PLScene::SPScene")) { // Assign the first found camera scene node to your surface listener and look for // known key/value data scene nodes SceneQuery *pSceneQuery = pContainer->CreateQuery("PLScene::SQEnumerate"); if (pSceneQuery) { // Connect event handler pSceneQuery->SignalSceneNode.Connect(EventHandlerSceneNode); // Perform the query pSceneQuery->PerformQuery(); // Destroy the query pContainer->DestroyQuery(*pSceneQuery); } // Set to default scene renderer? if (!m_sDefaultSceneRenderer.GetLength()) m_sDefaultSceneRenderer = DefaultSceneRenderer; // Sets all scene renderer pass attribute values to their default value GetSceneRendererTool().SetDefaultValues(); // Set the used scene renderer GetSceneRendererTool().SetSceneRenderer(pContainer, m_sDefaultSceneRenderer, DefaultSceneRenderer); // Set clear color GetSceneRendererTool().SetPassAttribute("Begin", "ColorClear", m_sClearColor); // Set scene renderer variables if (m_sSceneRendererVariables.GetLength()) GetSceneRendererTool().SetValues(m_sSceneRendererVariables); // Is there a given start camera? SceneNode *pCamera = nullptr; if (m_sStartCamera.GetLength()) { SceneNode *pStartCamera = pContainer->GetByName(m_sStartCamera); if (pStartCamera && pStartCamera->IsCamera()) pCamera = pStartCamera; } // Use the first found camera? if (!pCamera) pCamera = m_pFirstFoundCamera; // Activate the current used camera by default if (pCamera) pCamera->SetActive(true); // Assign this camera to the scene renderer and to the application SetCamera(reinterpret_cast<SNCamera*>(pCamera)); } // Emit the scene loading has been finished successfully event SignalSceneLoadingFinished(); } // Enable the ingame GUI if (pGui) pGui->SetActive(true); // Done return bResult; }
//[-------------------------------------------------------] //[ Public virtual PLRenderer::SurfacePainter functions ] //[-------------------------------------------------------] void SPScene::OnPaint(Surface &cSurface) { // Get the used renderer Renderer &cRenderer = GetRenderer(); // Get camera SNCamera *pCamera = nullptr; SceneRenderer *pSceneRenderer = nullptr; if (m_pCameraNodeHandler->GetElement()) { pCamera = static_cast<SNCamera*>(m_pCameraNodeHandler->GetElement()); if (pCamera) pSceneRenderer = pCamera->GetSceneRenderer(); } SNCamera::SetCamera(pCamera, &cRenderer); // Check the used scene renderer if (!pSceneRenderer) pSceneRenderer = GetDefaultSceneRenderer(); // Check the used scene renderer if (pSceneRenderer) { // Get the root scene container SceneContainer *pRootContainer = GetRootContainer(); if (pRootContainer) { // Get the cull query SQCull *pCullQuery = static_cast<SQCull*>(m_pCullQuery->GetElement()); if (pCullQuery) { // Set camera (can be a null pointer) if (pCamera) { // Setup render query SceneContainer *pCameraContainer = pCamera->GetContainer(); pCullQuery->SetCameraContainer((pCameraContainer && pCameraContainer->IsCell()) ? pCameraContainer : nullptr); pCullQuery->SetCameraPosition(pCamera->GetTransform().GetPosition()); pCullQuery->SetViewFrustum(pCamera->GetFrustum(cRenderer.GetViewport())); pCullQuery->SetProjectionMatrix(pCamera->GetProjectionMatrix(cRenderer.GetViewport())); pCullQuery->SetViewMatrix(pCamera->GetViewMatrix()); pCullQuery->SetViewProjectionMatrix(pCullQuery->GetProjectionMatrix()*pCamera->GetViewMatrix()); } else { // Set default states pCullQuery->SetCameraContainer(nullptr); pCullQuery->SetCameraPosition(Vector3::Zero); Matrix4x4 mProj; mProj.PerspectiveFov(static_cast<float>(90.0f*Math::DegToRad), 1.0f, 0.001f, 10000.0f); Frustum cFrustum; cFrustum.CreateViewPlanes(mProj, false); pCullQuery->SetViewFrustum(cFrustum); } // Perform the visibility determination pCullQuery->PerformQuery(); } // Get the scene container (can be a null pointer) SceneContainer *pContainer = GetSceneContainer(); // Pre all scene nodes DrawPre(cRenderer, *pRootContainer); // Draw all scene nodes solid DrawSolid(cRenderer, *pRootContainer); // Draw the scene container (if there's one) if (pContainer && pCullQuery) pSceneRenderer->DrawScene(cRenderer, *pCullQuery); // Draw all scene nodes transparent DrawTransparent(cRenderer, *pRootContainer); // Debug all scene nodes DrawDebug(cRenderer, *pRootContainer); // Post all scene nodes DrawPost(cRenderer, *pRootContainer); } } }
/** * @brief * Returns the used scene context */ SceneContext *SPScene::GetSceneContext() const { SceneContainer *pSceneContainer = static_cast<SceneContainer*>(m_pRootContainerHandler->GetElement()); return pSceneContainer ? pSceneContainer->GetSceneContext() : nullptr; }
//[-------------------------------------------------------] //[ Private virtual PLEngine::EngineApplication functions ] //[-------------------------------------------------------] void Application65::OnCreateScene(SceneContainer &cContainer) { // Create a scene node with the soldier mesh cContainer.Create("PLScene::SNMesh", "Soldier", "Position=\"0.0 -0.7 -4.0\" Scale=\"0.008 0.008 0.008\" Mesh=\"Data/Meshes/Soldier.mesh\""); // Create a nice particle effect behind the soldier cContainer.Create("PLParticleGroups::PGMagic2", "Magic2", "Position=\"0.0 0.0 -25.0\""); // Create a moving light source to illuminate the scene cContainer.Create("PLScene::SNPointLight", "Light", "Position=\"1.0 2.0 -2.0\" Flags=\"Flares|Corona|Blend\" Range=\"15.0\""); // Create a camera - this time we increase the camera FOV to get a better space feeling :) SceneNode *pCamera = cContainer.Create("PLScene::SNCamera", "FixedCamera", "Position=\"0.0 0.0 -2.5\" Rotation=\"0.0 180.0 0.0\" FOV=\"60\""); if (pCamera && pCamera->IsInstanceOf("PLScene::SNCamera")) { // Make this to our main scene camera SetCamera(reinterpret_cast<SNCamera*>(pCamera)); // Get class list of all available post process scene node modifiers m_lstModifierClasses.Clear(); ClassManager::GetInstance()->GetClasses(m_lstModifierClasses, "PLCompositing::SNMPostProcess", Recursive, NoBase, NoAbstract); // 'Activate' the first effect if (m_lstModifierClasses.GetNumOfElements()) pCamera->AddModifier(m_lstModifierClasses[m_nCurrentSelectedModifier]->GetClassName()); } // Setup scene surface painter SurfacePainter *pPainter = GetPainter(); if (pPainter && pPainter->IsInstanceOf("PLScene::SPScene")) { SPScene *pSPScene = static_cast<SPScene*>(pPainter); pSPScene->SetRootContainer(cContainer.GetContainer()); pSPScene->SetSceneContainer(&cContainer); } // Within the parent container... SceneContainer *pContainer = cContainer.GetContainer(); if (pContainer) { // Add our information text scene nodes SceneNode *pInfoText = pContainer->Create("PLScene::SceneContainer", "InfoText", "Flags=\"NoCulling\""); if (pInfoText && pInfoText->IsInstanceOf("PLScene::SceneContainer")) { SceneContainer *pInfoTextContainer = static_cast<SceneContainer*>(pInfoText); pInfoTextContainer->Create("PLScene::SNText2D", '0', "Position=\"0.01 0.01\" Flags=\"No3DPosition|NoCenter\" Text=\"" + PLT("'F1' = Show/hide this help text") + '\"'); pInfoTextContainer->Create("PLScene::SNText2D", '1', "Position=\"0.01 0.03\" Flags=\"No3DPosition|NoCenter\" Text=\"" + PLT("'Space' = Enable/disable post processing") + '\"'); pInfoTextContainer->Create("PLScene::SNText2D", '2', "Position=\"0.01 0.05\" Flags=\"No3DPosition|NoCenter\" Text=\"" + PLT("'1-7' = Custom post process effects") + '\"'); pInfoTextContainer->Create("PLScene::SNText2D", '3', "Position=\"0.01 0.07\" Flags=\"No3DPosition|NoCenter\" Text=\"" + PLT("'Page up' = Next post process effect") + '\"'); pInfoTextContainer->Create("PLScene::SNText2D", '4', "Position=\"0.01 0.09\" Flags=\"No3DPosition|NoCenter\" Text=\"" + PLT("'Page down' = Previous post process effect") + '\"'); } } // Set scene container SetScene(&cContainer); }
/** * @brief * Recursive part of PerformQuery() */ bool SQPlaneSet::PerformQueryRec(SceneHierarchyNode &cHierarchyNode) { // Is this scene hierarchy node intersecting the plane set? if (!cHierarchyNode.CheckPlaneSet(m_cPlaneSet)) return true; // Continue the query // Touch this node cHierarchyNode.Touch(); // Get the scene context SceneContext *pSceneContext = GetSceneContext(); if (pSceneContext) { // Inform all listeners const SceneHierarchyNodeItem *pItem = cHierarchyNode.GetFirstItem(); while (pItem) { // Get the linked scene node SceneNode *pSceneNode = pItem->GetSceneNode(); // Was this scene node already processed? if (pSceneNode && !pSceneContext->IsNodeTouched(*pSceneNode)) { // Check scene node const AABoundingBox &cAABB = pSceneNode->GetContainerAABoundingBox(); if (Intersect::PlaneSetAABox(m_cPlaneSet, cAABB.vMin, cAABB.vMax)) { // Touch this node pSceneContext->TouchNode(*pSceneNode); // Emit signal SignalSceneNode(*this, *pSceneNode); if (m_nFlags & StopQuery) return false; // Stop the query right now // Continue recursive? if (m_nFlags & Recursive) { // Is this a container and is recursion allowed? if (pSceneNode->IsContainer() && !(pSceneNode->GetFlags() & SceneContainer::NoRecursion)) { // Backup current plane set const PlaneSet cPlaneSet = m_cPlaneSet; // Transform the plane set into container space m_cPlaneSet *= pSceneNode->GetTransform().GetInverseMatrix(); // Container recursion const bool bContinue = PerformQueryRec(static_cast<SceneContainer*>(pSceneNode)->GetHierarchyInstance()->GetRootNode()); // Restore plane set m_cPlaneSet = cPlaneSet; // Stop the query right now? if (!bContinue) return false; // Is this a cell-portal? } else if (pSceneNode->IsPortal() && pSceneNode->IsInstanceOf("PLScene::SNCellPortal") && !(pSceneNode->GetFlags() & SNCellPortal::NoPassThrough)) { // Get the target cell SNCellPortal &cCellPortal = static_cast<SNCellPortal&>(*pSceneNode); SceneContainer *pCell = reinterpret_cast<SceneContainer*>(cCellPortal.GetTargetCellInstance()); if (pCell && pCell != pSceneNode->GetContainer()) { // Backup current plane set const PlaneSet cPlaneSet = m_cPlaneSet; // Transform the plane set into container space m_cPlaneSet *= cCellPortal.GetWarpMatrix(); // Container recursion const bool bContinue = PerformQueryRec(pCell->GetHierarchyInstance()->GetRootNode()); // Restore plane set m_cPlaneSet = cPlaneSet; // Stop the query right now? if (!bContinue) return false; } } } } } // Next item, please pItem = pItem->GetNextItem(); } } // Check all sub-hierarchies for (uint32 i=0; i<cHierarchyNode.GetNumOfNodes(); i++) { if (!PerformQueryRec(*cHierarchyNode.GetNode(i))) return false; // Stop the query right now } // Done, continue the query return true; }
//[-------------------------------------------------------] //[ Private virtual PLEngine::EngineApplication functions ] //[-------------------------------------------------------] void Application61::OnCreateScene(SceneContainer &cContainer) { // Set no scene container as default SetScene(nullptr); // Sound API given? if (m_sSoundAPI.GetLength()) { // Create a scene container with our 'concrete sound scene' using the chosen sound API SceneNode *pSceneContainerNode = cContainer.Create("PLSound::SCSound", "SoundScene", "SoundAPI=\"" + m_sSoundAPI + "\" Pitch=\"" + Timing::GetInstance()->GetTimeScaleFactor() + '\"'); if (pSceneContainerNode && pSceneContainerNode->IsInstanceOf("PLScene::SceneContainer")) { SceneContainer *pSceneContainer = static_cast<SceneContainer*>(pSceneContainerNode); // Protect this important container! pSceneContainer->SetProtected(true); // Set scene container SetScene(pSceneContainer); // Populate the scene container // Create a camera SceneNode *pCamera = pSceneContainer->Create("PLScene::SNCamera", "FreeCamera", "Position=\"0.0 -1.5 1.4\" Rotation=\"-14.0 180.0 0.0\""); if (pCamera && pCamera->IsInstanceOf("PLScene::SNCamera")) { // Make this to our main scene camera SetCamera(reinterpret_cast<SNCamera*>(pCamera)); // Add a controller modifier so we can look around the camera by using a default control pCamera->AddModifier("PLEngine::SNMEgoLookController"); // Add a controller modifier so we can move around the camera by using a default control pCamera->AddModifier("PLEngine::SNMMoveController", "Speed=\"2\""); // Make this camera to the 'sound listener' pSceneContainer->SetAttribute("Listener", pCamera->GetName()); } // Create the floor pSceneContainer->Create("PLScene::SNMesh", "Floor", "Position=\"0.0 -2.1 -5.0\" Rotation=\"0.0 180.0 0.0\" Scale=\"4.0 0.1 4.0\" Mesh=\"Default\""); // Create a box on the floor pSceneContainer->Create("PLScene::SNMesh", "Box", "Position=\"0.0 -1.5 -5.0\" Scale=\"0.5 0.5 0.5\" Mesh=\"Default\""); // Create rain particles and rain sound pSceneContainer->Create("PLParticleGroups::PGRain", "Rain", "Position=\"0.0 15.0 -5.0\" Flags=\"ForceUpdate\" MediumSize=\"3\""); pSceneContainer->Create("PLSound::SNSound", "RainSound", "Sound=\"Data/Sounds/Rain.ogg\" Volume=\"0.2\""); // Create the soldier walking in the rain :) SceneNode *pSoldier = pSceneContainer->Create("PLScene::SNMesh", "Soldier", "Position=\"0.0 -1.5 -5.0\" Scale=\"0.007 0.007 0.007\" Mesh=\"Data/Meshes/Soldier.mesh\""); if (pSoldier) { // Add animation modifier pSoldier->AddModifier("PLScene::SNMMeshAnimation", "Name=\"walk_0\" Speed=\"2\""); // Let the soldier walk on a path... pSoldier->AddModifier("PLScene::SNMPositionPath", "Filename=\"Data/Misc/61Sound_Soldier.path\" Speed=\"0.5\" Flags=\"NodeIndexProgress\" Interpolation=\"CatmullRomCurve\""); // ... and we should look into the direction he's moving pSoldier->AddModifier("PLScene::SNMRotationMoveDirection"); // Link a footsteps sound to the soldier pSoldier->AddModifier("PLSound::SNMSound","Sound=\"Data/Sounds/Walking.ogg\""); } // Setup scene surface painter SurfacePainter *pPainter = GetPainter(); if (pPainter && pPainter->IsInstanceOf("PLScene::SPScene")) { SPScene *pSPScene = static_cast<SPScene*>(pPainter); pSPScene->SetRootContainer(cContainer.GetContainer()); pSPScene->SetSceneContainer(pSceneContainer); } // Within the parent container... SceneContainer *pContainer = pSceneContainer->GetContainer(); if (pContainer) { // Get/add our information text scene nodes SceneNode *pInfoText = pContainer->Create("PLScene::SceneContainer", "InfoText", "Flags=\"NoCulling\""); if (pInfoText && pInfoText->IsInstanceOf("PLScene::SceneContainer")) { SceneContainer *pInfoTextContainer = static_cast<SceneContainer*>(pInfoText); // The name of the used sound API pInfoTextContainer->Create("PLScene::SNText2D", "SoundAPI", "Position=\"0.01 0.01\" Flags=\"No3DPosition|NoCenter\" Text=\"" + PLT("Sound API: ") + GetSoundAPI() + '\"'); // Draw keys information pInfoTextContainer->Create("PLScene::SNText2D", "Keys", "Position=\"0.01 0.04\" Flags=\"No3DPosition|NoCenter\" Text=\"" + PLT("Keys:") + '\"'); pInfoTextContainer->Create("PLScene::SNText2D", "TimeScale", "Position=\"0.06 0.08\" Flags=\"No3DPosition|NoCenter\""); UpdateTimeScaleTextNode(); } } } } }