From 00b57c1231ce78f21922410bd921a648d54938c2 Mon Sep 17 00:00:00 2001 From: aster2013 Date: Wed, 9 Apr 2014 23:01:39 +0800 Subject: [PATCH] Add LightAnimation sample, revert StaticScene. --- Source/Samples/04_StaticScene/StaticScene.cpp | 26 +-- .../Samples/30_LightAnimation/CMakeLists.txt | 33 +++ .../30_LightAnimation/LightAnimation.cpp | 212 ++++++++++++++++++ .../30_LightAnimation/LightAnimation.h | 71 ++++++ Source/Samples/CMakeLists.txt | 1 + 5 files changed, 319 insertions(+), 24 deletions(-) create mode 100644 Source/Samples/30_LightAnimation/CMakeLists.txt create mode 100644 Source/Samples/30_LightAnimation/LightAnimation.cpp create mode 100644 Source/Samples/30_LightAnimation/LightAnimation.h diff --git a/Source/Samples/04_StaticScene/StaticScene.cpp b/Source/Samples/04_StaticScene/StaticScene.cpp index 233d6e5c9..782eb9c85 100644 --- a/Source/Samples/04_StaticScene/StaticScene.cpp +++ b/Source/Samples/04_StaticScene/StaticScene.cpp @@ -21,7 +21,6 @@ // #include "Camera.h" -#include "AttributeAnimation.h" #include "CoreEvents.h" #include "Engine.h" #include "Font.h" @@ -40,7 +39,6 @@ #include "StaticScene.h" #include "DebugNew.h" -#include "Animatable.h" DEFINE_APPLICATION_MAIN(StaticScene) @@ -97,16 +95,7 @@ void StaticScene::CreateScene() lightNode->SetDirection(Vector3(0.6f, -1.0f, 0.8f)); // The direction vector does not need to be normalized Light* light = lightNode->CreateComponent(); light->SetLightType(LIGHT_DIRECTIONAL); - - /// Create light color animation - SharedPtr colorAnimation(new AttributeAnimation(context_)); - colorAnimation->SetKeyFrame(0.0f, Color::WHITE); - colorAnimation->SetKeyFrame(4.0f, Color::WHITE); - colorAnimation->SetKeyFrame(1.0f, Color::RED); - colorAnimation->SetKeyFrame(2.0f, Color::YELLOW); - colorAnimation->SetKeyFrame(3.0f, Color::GREEN); - light->SetAttributeAnimation("Color", colorAnimation); - + // Create more StaticModel objects to the scene, randomly positioned, rotated and scaled. For rotation, we construct a // quaternion from Euler angles where the Y angle (rotation about the Y axis) is randomized. The mushroom model contains // LOD levels, so the StaticModel component will automatically select the LOD level according to the view distance (you'll @@ -117,23 +106,12 @@ void StaticScene::CreateScene() for (unsigned i = 0; i < NUM_OBJECTS; ++i) { Node* mushroomNode = scene_->CreateChild("Mushroom"); - - Vector3 position(Random(90.0f) - 45.0f, 0.0f, Random(90.0f) - 45.0f); - mushroomNode->SetPosition(position); + mushroomNode->SetPosition(Vector3(Random(90.0f) - 45.0f, 0.0f, Random(90.0f) - 45.0f)); mushroomNode->SetRotation(Quaternion(0.0f, Random(360.0f), 0.0f)); mushroomNode->SetScale(0.5f + Random(2.0f)); StaticModel* mushroomObject = mushroomNode->CreateComponent(); mushroomObject->SetModel(cache->GetResource("Models/Mushroom.mdl")); mushroomObject->SetMaterial(cache->GetResource("Materials/Mushroom.xml")); - - // Create mushroom position animation. - SharedPtr positionAnimaiton(new AttributeAnimation(context_)); - // Set same value for begin and end key frames - positionAnimaiton->SetKeyFrame(0.0f, position); - positionAnimaiton->SetKeyFrame(3.0f, position); - positionAnimaiton->SetKeyFrame(1.0f, position + Vector3(Random(2.0f) - 1.0f, 0.0f, Random(2.0f) - 1.0f)); - positionAnimaiton->SetKeyFrame(2.0f, position + Vector3(Random(2.0f) - 1.0f, 0.0f, Random(2.0f) - 1.0f)); - mushroomNode->SetAttributeAnimation("Position", positionAnimaiton); } // Create a scene node for the camera, which we will move around diff --git a/Source/Samples/30_LightAnimation/CMakeLists.txt b/Source/Samples/30_LightAnimation/CMakeLists.txt new file mode 100644 index 000000000..90b795828 --- /dev/null +++ b/Source/Samples/30_LightAnimation/CMakeLists.txt @@ -0,0 +1,33 @@ +# +# Copyright (c) 2008-2014 the Urho3D project. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. +# + +# Define target name +set (TARGET_NAME 30_LightAnimation) + +# Define source files +define_source_files (EXTRA_H_FILES ${COMMON_SAMPLE_H_FILES}) + +# Setup target with resource copying +setup_main_executable () + +# Setup test cases +add_test (NAME ${TARGET_NAME} COMMAND ${TARGET_NAME} -timeout ${URHO3D_TEST_TIME_OUT}) diff --git a/Source/Samples/30_LightAnimation/LightAnimation.cpp b/Source/Samples/30_LightAnimation/LightAnimation.cpp new file mode 100644 index 000000000..9c22308af --- /dev/null +++ b/Source/Samples/30_LightAnimation/LightAnimation.cpp @@ -0,0 +1,212 @@ +// +// Copyright (c) 2008-2014 the Urho3D project. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// + +#include "AttributeAnimation.h" +#include "Camera.h" +#include "CoreEvents.h" +#include "Engine.h" +#include "Font.h" +#include "Graphics.h" +#include "Input.h" +#include "LightAnimation.h" +#include "Material.h" +#include "Model.h" +#include "Octree.h" +#include "Renderer.h" +#include "ResourceCache.h" +#include "Scene.h" +#include "StaticModel.h" +#include "Text.h" +#include "UI.h" + +#include "DebugNew.h" +#include "Animatable.h" + +DEFINE_APPLICATION_MAIN(LightAnimation) + +LightAnimation::LightAnimation(Context* context) : + Sample(context), + yaw_(0.0f), + pitch_(0.0f) +{ +} + +void LightAnimation::Start() +{ + // Execute base class startup + Sample::Start(); + + // Create the scene content + CreateScene(); + + // Create the UI content + CreateInstructions(); + + // Setup the viewport for displaying the scene + SetupViewport(); + + // Hook up to the frame update events + SubscribeToEvents(); +} + +void LightAnimation::CreateScene() +{ + ResourceCache* cache = GetSubsystem(); + + scene_ = new Scene(context_); + + // Create the Octree component to the scene. This is required before adding any drawable components, or else nothing will + // show up. The default octree volume will be from (-1000, -1000, -1000) to (1000, 1000, 1000) in world coordinates; it + // is also legal to place objects outside the volume but their visibility can then not be checked in a hierarchically + // optimizing manner + scene_->CreateComponent(); + + // Create a child scene node (at world origin) and a StaticModel component into it. Set the StaticModel to show a simple + // plane mesh with a "stone" material. Note that naming the scene nodes is optional. Scale the scene node larger + // (100 x 100 world units) + Node* planeNode = scene_->CreateChild("Plane"); + planeNode->SetScale(Vector3(100.0f, 1.0f, 100.0f)); + StaticModel* planeObject = planeNode->CreateComponent(); + planeObject->SetModel(cache->GetResource("Models/Plane.mdl")); + planeObject->SetMaterial(cache->GetResource("Materials/StoneTiled.xml")); + + // Create a directional light to the world so that we can see something. The light scene node's orientation controls the + // light direction; we will use the SetDirection() function which calculates the orientation from a forward direction vector. + // The light will use default settings (white light, no shadows) + Node* lightNode = scene_->CreateChild("DirectionalLight"); + lightNode->SetDirection(Vector3(0.6f, -1.0f, 0.8f)); // The direction vector does not need to be normalized + Light* light = lightNode->CreateComponent(); + light->SetLightType(LIGHT_DIRECTIONAL); + + /// Create light color animation + SharedPtr colorAnimation(new AttributeAnimation(context_)); + colorAnimation->SetKeyFrame(0.0f, Color::WHITE); + colorAnimation->SetKeyFrame(1.0f, Color::RED); + colorAnimation->SetKeyFrame(2.0f, Color::YELLOW); + colorAnimation->SetKeyFrame(3.0f, Color::GREEN); + colorAnimation->SetKeyFrame(4.0f, Color::WHITE); + light->SetAttributeAnimation("Color", colorAnimation); + + // Create more StaticModel objects to the scene, randomly positioned, rotated and scaled. For rotation, we construct a + // quaternion from Euler angles where the Y angle (rotation about the Y axis) is randomized. The mushroom model contains + // LOD levels, so the StaticModel component will automatically select the LOD level according to the view distance (you'll + // see the model get simpler as it moves further away). Finally, rendering a large number of the same object with the + // same material allows instancing to be used, if the GPU supports it. This reduces the amount of CPU work in rendering the + // scene. + const unsigned NUM_OBJECTS = 200; + for (unsigned i = 0; i < NUM_OBJECTS; ++i) + { + Node* mushroomNode = scene_->CreateChild("Mushroom"); + mushroomNode->SetPosition(Vector3(Random(90.0f) - 45.0f, 0.0f, Random(90.0f) - 45.0f)); + mushroomNode->SetRotation(Quaternion(0.0f, Random(360.0f), 0.0f)); + mushroomNode->SetScale(0.5f + Random(2.0f)); + StaticModel* mushroomObject = mushroomNode->CreateComponent(); + mushroomObject->SetModel(cache->GetResource("Models/Mushroom.mdl")); + mushroomObject->SetMaterial(cache->GetResource("Materials/Mushroom.xml")); + } + + // Create a scene node for the camera, which we will move around + // The camera will use default settings (1000 far clip distance, 45 degrees FOV, set aspect ratio automatically) + cameraNode_ = scene_->CreateChild("Camera"); + cameraNode_->CreateComponent(); + + // Set an initial position for the camera scene node above the plane + cameraNode_->SetPosition(Vector3(0.0f, 5.0f, 0.0f)); +} + +void LightAnimation::CreateInstructions() +{ + ResourceCache* cache = GetSubsystem(); + UI* ui = GetSubsystem(); + + // Construct new Text object, set string to display and font to use + Text* instructionText = ui->GetRoot()->CreateChild(); + instructionText->SetText("Use WASD keys and mouse to move"); + instructionText->SetFont(cache->GetResource("Fonts/Anonymous Pro.ttf"), 15); + + // Position the text relative to the screen center + instructionText->SetHorizontalAlignment(HA_CENTER); + instructionText->SetVerticalAlignment(VA_CENTER); + instructionText->SetPosition(0, ui->GetRoot()->GetHeight() / 4); +} + +void LightAnimation::SetupViewport() +{ + Renderer* renderer = GetSubsystem(); + + // Set up a viewport to the Renderer subsystem so that the 3D scene can be seen. We need to define the scene and the camera + // at minimum. Additionally we could configure the viewport screen size and the rendering path (eg. forward / deferred) to + // use, but now we just use full screen and default render path configured in the engine command line options + SharedPtr viewport(new Viewport(context_, scene_, cameraNode_->GetComponent())); + renderer->SetViewport(0, viewport); +} + +void LightAnimation::MoveCamera(float timeStep) +{ + // Do not move if the UI has a focused element (the console) + if (GetSubsystem()->GetFocusElement()) + return; + + Input* input = GetSubsystem(); + + // Movement speed as world units per second + const float MOVE_SPEED = 20.0f; + // Mouse sensitivity as degrees per pixel + const float MOUSE_SENSITIVITY = 0.1f; + + // Use this frame's mouse motion to adjust camera node yaw and pitch. Clamp the pitch between -90 and 90 degrees + IntVector2 mouseMove = input->GetMouseMove(); + yaw_ += MOUSE_SENSITIVITY * mouseMove.x_; + pitch_ += MOUSE_SENSITIVITY * mouseMove.y_; + pitch_ = Clamp(pitch_, -90.0f, 90.0f); + + // Construct new orientation for the camera scene node from yaw and pitch. Roll is fixed to zero + cameraNode_->SetRotation(Quaternion(pitch_, yaw_, 0.0f)); + + // Read WASD keys and move the camera scene node to the corresponding direction if they are pressed + // Use the Translate() function (default local space) to move relative to the node's orientation. + if (input->GetKeyDown('W')) + cameraNode_->Translate(Vector3::FORWARD * MOVE_SPEED * timeStep); + if (input->GetKeyDown('S')) + cameraNode_->Translate(Vector3::BACK * MOVE_SPEED * timeStep); + if (input->GetKeyDown('A')) + cameraNode_->Translate(Vector3::LEFT * MOVE_SPEED * timeStep); + if (input->GetKeyDown('D')) + cameraNode_->Translate(Vector3::RIGHT * MOVE_SPEED * timeStep); +} + +void LightAnimation::SubscribeToEvents() +{ + // Subscribe HandleUpdate() function for processing update events + SubscribeToEvent(E_UPDATE, HANDLER(LightAnimation, HandleUpdate)); +} + +void LightAnimation::HandleUpdate(StringHash eventType, VariantMap& eventData) +{ + using namespace Update; + + // Take the frame time step, which is stored as a float + float timeStep = eventData[P_TIMESTEP].GetFloat(); + + // Move the camera, scale movement with time step + MoveCamera(timeStep); +} diff --git a/Source/Samples/30_LightAnimation/LightAnimation.h b/Source/Samples/30_LightAnimation/LightAnimation.h new file mode 100644 index 000000000..4c93c6174 --- /dev/null +++ b/Source/Samples/30_LightAnimation/LightAnimation.h @@ -0,0 +1,71 @@ +// +// Copyright (c) 2008-2014 the Urho3D project. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// + +#pragma once + +#include "Sample.h" + +namespace Urho3D +{ + +class Node; +class Scene; + +} + +/// Light animation example. +/// This sample is base on StaticScene, and it demonstrates: +/// - Usage of attribute animation for light color animation. +class LightAnimation : public Sample +{ + OBJECT(LightAnimation); + +public: + /// Construct. + LightAnimation(Context* context); + + /// Setup after engine initialization and before running the main loop. + virtual void Start(); + +private: + /// Construct the scene content. + void CreateScene(); + /// Construct an instruction text to the UI. + void CreateInstructions(); + /// Set up a viewport for displaying the scene. + void SetupViewport(); + /// Read input and moves the camera. + void MoveCamera(float timeStep); + /// Subscribe to application-wide logic update events. + void SubscribeToEvents(); + /// Handle the logic update event. + void HandleUpdate(StringHash eventType, VariantMap& eventData); + + /// Scene. + SharedPtr scene_; + /// Camera scene node. + SharedPtr cameraNode_; + /// Camera yaw angle. + float yaw_; + /// Camera pitch angle. + float pitch_; +}; diff --git a/Source/Samples/CMakeLists.txt b/Source/Samples/CMakeLists.txt index 13c570c7e..799385e54 100644 --- a/Source/Samples/CMakeLists.txt +++ b/Source/Samples/CMakeLists.txt @@ -67,3 +67,4 @@ add_subdirectory (26_ConsoleInput) add_subdirectory (27_Urho2DPhysics) add_subdirectory (28_Urho2DPhysicsRope) add_subdirectory (29_SoundSynthesis) +add_subdirectory (30_LightAnimation)