Browse Source

Adding Decals example with ray casting, add UI text for samples

Josh Engebretson 9 years ago
parent
commit
055950cb9c

+ 1 - 1
FeatureExamples/Resources/Scripts/04_StaticScene.cs

@@ -41,7 +41,7 @@ namespace FeatureExamples
             base.Start();
             base.Start();
             CreateScene();
             CreateScene();
             SimpleCreateInstructionsWithWasd();
             SimpleCreateInstructionsWithWasd();
-            SetupViewport();            
+            SetupViewport();
         }
         }
 
 
         void CreateScene()
         void CreateScene()

+ 1 - 1
FeatureExamples/Resources/Scripts/05_AnimatingScene.cs

@@ -72,7 +72,7 @@ namespace FeatureExamples
                 // Add our custom Rotator component which will rotate the scene node each frame, when the scene sends its update event.
                 // Add our custom Rotator component which will rotate the scene node each frame, when the scene sends its update event.
                 // The Rotator component derives from the base class CSComponent, which has convenience functionality to subscribe
                 // The Rotator component derives from the base class CSComponent, which has convenience functionality to subscribe
                 // to the various update events
                 // to the various update events
-                
+
                 // Now we simply set same rotation speed for all objects
                 // Now we simply set same rotation speed for all objects
                 var rotationSpeed = new Vector3(10.0f, 20.0f, 30.0f);
                 var rotationSpeed = new Vector3(10.0f, 20.0f, 30.0f);
 
 

+ 20 - 11
FeatureExamples/Resources/Scripts/06_SkeletalAnimation.cs

@@ -176,6 +176,8 @@ namespace FeatureExamples
             float RotationSpeed { get; }
             float RotationSpeed { get; }
             BoundingBox Bounds { get; }
             BoundingBox Bounds { get; }
 
 
+            AnimationState animState;
+
             public Mover(float moveSpeed, float rotateSpeed, BoundingBox bounds)
             public Mover(float moveSpeed, float rotateSpeed, BoundingBox bounds)
             {
             {
                 MoveSpeed = moveSpeed;
                 MoveSpeed = moveSpeed;
@@ -183,16 +185,8 @@ namespace FeatureExamples
                 Bounds = bounds;
                 Bounds = bounds;
             }
             }
 
 
-            void Update(float timeStep)
+            void Start()
             {
             {
-                // This moves the character position
-                Node.Translate(Vector3.UnitZ * MoveSpeed * timeStep, TransformSpace.TS_LOCAL);
-
-                // If in risk of going outside the plane, rotate the model right
-                var pos = Node.Position;
-                if (pos.X < Bounds.Min.X || pos.X > Bounds.Max.X || pos.Z < Bounds.Min.Z || pos.Z > Bounds.Max.Z)
-                    Node.Yaw(RotationSpeed * timeStep, TransformSpace.TS_LOCAL);
-
                 // Get the model's first (only) animation
                 // Get the model's first (only) animation
                 // state and advance its time. Note the
                 // state and advance its time. Note the
                 // convenience accessor to other components in
                 // convenience accessor to other components in
@@ -202,9 +196,24 @@ namespace FeatureExamples
 
 
                 if (model.NumAnimationStates > 0)
                 if (model.NumAnimationStates > 0)
                 {
                 {
-                    var state = model.AnimationStates.First();
-                    state.AddTime(timeStep);
+                    animState = model.AnimationStates.First();
                 }
                 }
+
+            }
+
+            void Update(float timeStep)
+            {
+                // This moves the character position
+                Node.Translate(Vector3.UnitZ * MoveSpeed * timeStep, TransformSpace.TS_LOCAL);
+
+                // If in risk of going outside the plane, rotate the model right
+                var pos = Node.Position;
+                if (pos.X < Bounds.Min.X || pos.X > Bounds.Max.X || pos.Z < Bounds.Min.Z || pos.Z > Bounds.Max.Z)
+                    Node.Yaw(RotationSpeed * timeStep, TransformSpace.TS_LOCAL);
+
+                if (animState != null)
+                    animState.AddTime(timeStep);
+
             }
             }
         }
         }
     }
     }

+ 247 - 0
FeatureExamples/Resources/Scripts/08_Decals.cs

@@ -0,0 +1,247 @@
+//
+// Copyright (c) 2008-2015 the Urho3D project.
+// Copyright (c) 2015 Xamarin Inc
+// Copyright (c) 2016 THUNDERBEAST GAMES LLC
+//
+// 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.
+//
+
+using System;
+using System.Linq;
+using AtomicEngine;
+
+namespace FeatureExamples
+{
+    public class DecalSample : Sample
+    {
+        Scene scene;
+        bool drawDebug;
+        Camera camera;
+
+        public DecalSample() : base() { }
+
+        public override void Start()
+        {
+            base.Start();
+            CreateScene();
+            CreateUI();
+            SetupViewport();
+            SubscribeToEvents();
+        }
+
+        void CreateUI()
+        {
+            SimpleCreateInstructionsWithWasd(
+                "\nLMB to paint decals, RMB to rotate view\n" +
+                "Space to toggle debug geometry\n" +
+                "7 to toggle occlusion culling");
+        }
+
+        void SubscribeToEvents()
+        {
+            // Subscribe HandlePostRenderUpdate() function for
+            // processing the post-render update event, sent after
+            // Renderer subsystem is done with defining the draw
+            // calls for the viewports (but before actually
+            // executing them.) We will request debug geometry
+            // rendering during that event
+
+            SubscribeToEvent<PostRenderUpdateEvent>(e =>
+            {
+                // If draw debug mode is enabled, draw viewport debug geometry, which will show eg. drawable bounding boxes and skeleton
+                // bones. Note that debug geometry has to be separately requested each frame. Disable depth test so that we can see the
+                // bones properly
+                if (drawDebug)
+                {
+                    GetSubsystem<Renderer>().DrawDebugGeometry(false);
+                }
+            });
+        }
+
+        protected override void Update(float timeStep)
+        {
+            UI ui = GetSubsystem<UI>();
+            var input = GetSubsystem<Input>();
+
+
+            const float mouseSensitivity = .1f;
+            const float moveSpeed = 40f;
+
+            if (input.GetMouseButtonDown(Constants.MOUSEB_RIGHT))
+            {
+                var mouseMove = input.MouseMove;
+                Yaw += mouseSensitivity * mouseMove.X;
+                Pitch += mouseSensitivity * mouseMove.Y;
+                Pitch = MathHelper.Clamp(Pitch, -90, 90);
+            }
+
+            CameraNode.Rotation = new Quaternion(Pitch, Yaw, 0);
+
+            if (input.GetKeyDown(Constants.KEY_W))
+                CameraNode.Translate(Vector3.UnitZ * moveSpeed * timeStep);
+            if (input.GetKeyDown(Constants.KEY_S))
+                CameraNode.Translate(-Vector3.UnitZ * moveSpeed * timeStep);
+            if (input.GetKeyDown(Constants.KEY_A))
+                CameraNode.Translate(-Vector3.UnitX * moveSpeed * timeStep);
+            if (input.GetKeyDown(Constants.KEY_D))
+                CameraNode.Translate(Vector3.UnitX * moveSpeed * timeStep);
+
+            if (input.GetKeyPress(Constants.KEY_SPACE))
+                drawDebug = !drawDebug;
+
+            if (input.GetMouseButtonPress(Constants.MOUSEB_LEFT))
+                PaintDecal();
+
+            base.Update(timeStep);
+        }
+
+        void SetupViewport()
+        {
+            var renderer = GetSubsystem<Renderer>();
+            renderer.SetViewport(0, new Viewport(scene, CameraNode.GetComponent<Camera>()));
+        }
+
+        void CreateScene()
+        {
+            var cache = GetSubsystem<ResourceCache>();
+            scene = new Scene();
+
+            // Create octree, use default volume (-1000, -1000, -1000) to (1000, 1000, 1000)
+            // Also create a DebugRenderer component so that we can draw debug geometry
+            scene.CreateComponent<Octree>();
+            scene.CreateComponent<DebugRenderer>();
+
+            // Create scene node & StaticModel component for showing a static plane
+            var planeNode = scene.CreateChild("Plane");
+            planeNode.Scale = new Vector3(100.0f, 1.0f, 100.0f);
+            var planeObject = planeNode.CreateComponent<StaticModel>();
+            planeObject.Model = cache.Get<Model>("Models/Plane.mdl");
+            planeObject.SetMaterial(cache.Get<Material>("Materials/StoneTiled.xml"));
+
+            // Create a Zone component for ambient lighting & fog control
+            var zoneNode = scene.CreateChild("Zone");
+            var zone = zoneNode.CreateComponent<Zone>();
+            zone.SetBoundingBox(new BoundingBox(-1000.0f, 1000.0f));
+            zone.AmbientColor = new Color(0.15f, 0.15f, 0.15f);
+            zone.FogColor = new Color(0.5f, 0.5f, 0.7f);
+            zone.FogStart = 100.0f;
+            zone.FogEnd = 300.0f;
+
+            // Create a directional light to the world. Enable cascaded shadows on it
+            var lightNode = scene.CreateChild("DirectionalLight");
+            lightNode.SetDirection(new Vector3(0.6f, -1.0f, 0.8f));
+            var light = lightNode.CreateComponent<Light>();
+            light.LightType = LightType.LIGHT_DIRECTIONAL;
+            light.CastShadows = true;
+            light.ShadowBias = new BiasParameters(0.00025f, 0.5f);
+            // Set cascade splits at 10, 50 and 200 world units, fade shadows out at 80% of maximum shadow distance
+            light.ShadowCascade = new CascadeParameters(10.0f, 50.0f, 200.0f, 0.0f, 0.8f);
+
+            // Create some mushrooms
+            const uint numMushrooms = 240;
+            for (uint i = 0; i < numMushrooms; ++i)
+            {
+                var mushroomNode = scene.CreateChild("Mushroom");
+                mushroomNode.Position = new Vector3(NextRandom(90.0f) - 45.0f, 0.0f, NextRandom(90.0f) - 45.0f);
+                mushroomNode.Rotation = new Quaternion(0.0f, NextRandom(360.0f), 0.0f);
+                mushroomNode.SetScale(0.5f + NextRandom(2.0f));
+                var mushroomObject = mushroomNode.CreateComponent<StaticModel>();
+                mushroomObject.Model = cache.Get<Model>("Models/Mushroom.mdl");
+                mushroomObject.SetMaterial(cache.Get<Material>("Materials/Mushroom.xml"));
+                mushroomObject.CastShadows = true;
+            }
+
+            // Create randomly sized boxes. If boxes are big enough, make them occluders. Occluders will be software rasterized before
+            // rendering to a low-resolution depth-only buffer to test the objects in the view frustum for visibility
+            const uint numBoxes = 20;
+            for (uint i = 0; i < numBoxes; ++i)
+            {
+                var boxNode = scene.CreateChild("Box");
+                float size = 1.0f + NextRandom(10.0f);
+                boxNode.Position = new Vector3(NextRandom(80.0f) - 40.0f, size * 0.5f, NextRandom(80.0f) - 40.0f);
+                boxNode.SetScale(size);
+                var boxObject = boxNode.CreateComponent<StaticModel>();
+                boxObject.Model = cache.Get<Model>("Models/Box.mdl");
+                boxObject.SetMaterial(cache.Get<Material>("Materials/Stone.xml"));
+                boxObject.CastShadows = true;
+                if (size >= 3.0f)
+                    boxObject.Occluder = true;
+            }
+
+            // Create the camera. Limit far clip distance to match the fog
+            CameraNode = scene.CreateChild("Camera");
+            camera = CameraNode.CreateComponent<Camera>();
+            camera.FarClip = 300.0f;
+            // Set an initial position for the camera scene node above the plane
+            CameraNode.Position = new Vector3(0.0f, 5.0f, 0.0f);
+        }
+
+        bool Raycast(float maxDistance, out Vector3 hitPos, out Drawable hitDrawable)
+        {
+            hitDrawable = null;
+            hitPos = Vector3.Zero;
+
+            var graphics = GetSubsystem<Graphics>();
+            var input = GetSubsystem<Input>();
+
+            IntVector2 pos = input.MousePosition;
+            Ray cameraRay = camera.GetScreenRay((float)pos.X / graphics.Width, (float)pos.Y / graphics.Height);
+
+            RayOctreeQuery query = new RayOctreeQuery(cameraRay, RayQueryLevel.RAY_TRIANGLE, maxDistance, Constants.DRAWABLE_GEOMETRY);
+
+            scene.GetComponent<Octree>().RaycastSingle(query);
+
+            if (query.Results.Count > 0)
+            {
+                var first = query.Results.First();
+                hitPos = first.Position;
+                hitDrawable = first.Drawable;
+                return true;
+            }
+            return false;
+        }
+
+        void PaintDecal()
+        {
+            Vector3 hitPos;
+            Drawable hitDrawable;
+
+            if (Raycast(250.0f, out hitPos, out hitDrawable))
+            {
+                var targetNode = hitDrawable.Node;
+                var decal = targetNode.GetComponent<DecalSet>();
+
+                if (decal == null)
+                {
+                    var cache = GetSubsystem<ResourceCache>();
+                    decal = targetNode.CreateComponent<DecalSet>();
+                    decal.Material = cache.Get<Material>("Materials/UrhoDecal.xml");
+                }
+
+                // Add a square decal to the decal set using the geometry of the drawable that was hit, orient it to face the camera,
+                // use full texture UV's (0,0) to (1,1). Note that if we create several decals to a large object (such as the ground
+                // plane) over a large area using just one DecalSet component, the decals will all be culled as one unit. If that is
+                // undesirable, it may be necessary to create more than one DecalSet based on the distance
+                decal.AddDecal(hitDrawable, hitPos, CameraNode.Rotation, 0.5f, 1.0f, 1.0f, Vector2.Zero,
+                    Vector2.One, 0.0f, 0.1f, uint.MaxValue);
+            }
+        }
+
+    }
+}

+ 5 - 0
FeatureExamples/Resources/Scripts/08_Decals.cs.asset

@@ -0,0 +1,5 @@
+{
+	"version": 1,
+	"guid": "91a310326884f026608ccc4b2b55c406",
+	"CSharpImporter": null
+}

+ 26 - 3
FeatureExamples/Resources/Scripts/Sample.cs

@@ -56,7 +56,7 @@ namespace FeatureExamples
             SubscribeToEvent<KeyDownEvent>(HandleKeyDown);
             SubscribeToEvent<KeyDownEvent>(HandleKeyDown);
 
 
 
 
-            
+
         }
         }
 
 
         protected virtual void Update(float timeStep)
         protected virtual void Update(float timeStep)
@@ -154,6 +154,29 @@ namespace FeatureExamples
 
 
         protected void SimpleCreateInstructions(string text = "")
         protected void SimpleCreateInstructions(string text = "")
         {
         {
+            var view = new UIView();
+
+            var layout = new UILayout();
+
+            layout.Rect = view.Rect;
+
+            layout.LayoutPosition = UI_LAYOUT_POSITION.UI_LAYOUT_POSITION_RIGHT_BOTTOM;
+            layout.LayoutDistributionPosition = UI_LAYOUT_DISTRIBUTION_POSITION.UI_LAYOUT_DISTRIBUTION_POSITION_RIGHT_BOTTOM;
+
+            var fontDesc = new UIFontDescription();
+            fontDesc.Id = "Vera";
+            fontDesc.Size = 18;
+
+            var label = new UIEditField();
+            label.FontDescription = fontDesc;
+            label.ReadOnly = true;
+            label.Multiline = true;
+            label.AdaptToContentSize = true;
+            label.Text = text;
+            layout.AddChild(label);
+
+            view.AddChild(layout);
+
         }
         }
 
 
         void CreateLogo()
         void CreateLogo()
@@ -176,10 +199,10 @@ namespace FeatureExamples
                     GetSubsystem<Engine>().Exit();
                     GetSubsystem<Engine>().Exit();
                     return;
                     return;
                 case Constants.KEY_F1:
                 case Constants.KEY_F1:
-                    // console.Toggle();
+                    GetSubsystem<UI>().ToggleConsole();
                     return;
                     return;
                 case Constants.KEY_F2:
                 case Constants.KEY_F2:
-                    // debugHud.ToggleAll();
+                    GetSubsystem<UI>().ToggleDebugHud();
                     return;
                     return;
             }
             }