public static void UpdateParameters(RenderContext context, CameraComponent camera)
        {
            if (camera == null) throw new ArgumentNullException("camera");

            // Setup viewport size
            var currentViewport = context.GraphicsDevice.Viewport;
            var aspectRatio = currentViewport.AspectRatio;

            // Update the aspect ratio
            if (camera.UseCustomAspectRatio)
            {
                aspectRatio = camera.AspectRatio;
            }

            // If the aspect ratio is calculated automatically from the current viewport, update matrices here
            camera.Update(aspectRatio);

            // Store the current view/projection matrix in the context
            var viewParameters = context.Parameters;
            viewParameters.Set(TransformationKeys.View, camera.ViewMatrix);
            viewParameters.Set(TransformationKeys.Projection, camera.ProjectionMatrix);
            viewParameters.Set(TransformationKeys.ViewProjection, camera.ViewProjectionMatrix);
            viewParameters.Set(CameraKeys.NearClipPlane, camera.NearClipPlane);
            viewParameters.Set(CameraKeys.FarClipPlane, camera.FarClipPlane);
            viewParameters.Set(CameraKeys.VerticalFieldOfView, camera.VerticalFieldOfView);
            viewParameters.Set(CameraKeys.OrthoSize, camera.OrthographicSize);
            viewParameters.Set(CameraKeys.ViewSize, new Vector2(currentViewport.Width, currentViewport.Height));
            viewParameters.Set(CameraKeys.AspectRatio, aspectRatio);

            //viewParameters.Set(CameraKeys.FocusDistance, camera.FocusDistance);
        }
Пример #2
0
        public static bool ScreenPositionToWorldPositionRaycast(Vector2 screenPos, CameraComponent camera, Simulation simulation)
        {
            var invViewProj = Matrix.Invert(camera.ViewProjectionMatrix);

            Vector3 sPos;
            sPos.X = screenPos.X * 2f - 1f;
            sPos.Y = 1f - screenPos.Y * 2f;

            sPos.Z = 0f;
            var vectorNear = Vector3.Transform(sPos, invViewProj);
            vectorNear /= vectorNear.W;

            sPos.Z = 1f;
            var vectorFar = Vector3.Transform(sPos, invViewProj);
            vectorFar /= vectorFar.W;

            var result = simulation.RaycastPenetrating(vectorNear.XYZ(), vectorFar.XYZ());
            foreach (var hitResult in result)
            {
                if (hitResult.Succeeded)
                {
                    return true;
                }
            }

            return false;
        }
Пример #3
0
        public static Vector3 LogicDirectionToWorldDirection(Vector2 logicDirection, CameraComponent camera, Vector3 upVector)
        {
            var inverseView = Matrix.Invert(camera.ViewMatrix);

            var forward = Vector3.Cross(upVector, inverseView.Right);
            forward.Normalize();

            var right = Vector3.Cross(forward, upVector);
            var worldDirection = forward * logicDirection.Y + right * logicDirection.X;
            worldDirection.Normalize();
            return worldDirection;
        }
Пример #4
0
        protected override float ComputeScreenCoverage(CameraComponent camera, Vector3 position, Vector3 direction, float width, float height)
        {
            // http://stackoverflow.com/questions/21648630/radius-of-projected-sphere-in-screen-space
            var targetPosition = new Vector4(position, 1.0f);
            Vector4 projectedTarget;
            Vector4.Transform(ref targetPosition, ref camera.ViewProjectionMatrix, out projectedTarget);

            var d = Math.Abs(projectedTarget.W) + 0.00001f;
            var r = Radius;
            var coTanFovBy2 = camera.ProjectionMatrix.M22;
            var pr = r * coTanFovBy2 / (Math.Sqrt(d * d - r * r) + 0.00001f);

            // Size on screen
            return (float)pr * Math.Max(width, height);
        }
        protected CameraComponent GetUICameraComponent(UIComponent uiComponent)
        {
            var virtualResolution = uiComponent.Resolution;

            var nearPlane   = virtualResolution.Z / 2;
            var farPlane    = nearPlane + virtualResolution.Z;
            var zOffset     = nearPlane + virtualResolution.Z / 2;
            var aspectRatio = virtualResolution.X / virtualResolution.Y;
            var verticalFov = (float)Math.Atan2(virtualResolution.Y / 2, zOffset) * 2;

            var cameraComponent = new CameraComponent(nearPlane, farPlane)
            {
                UseCustomAspectRatio = true,
                AspectRatio          = aspectRatio,
                VerticalFieldOfView  = MathUtil.RadiansToDegrees(verticalFov),
                ViewMatrix           = Matrix.LookAtRH(new Vector3(0, 0, zOffset), Vector3.Zero, Vector3.UnitY),
                ProjectionMatrix     = Matrix.PerspectiveFovRH(verticalFov, aspectRatio, nearPlane, farPlane),
            };

            return(cameraComponent);
        }
Пример #6
0
 /// <summary>
 /// Initializes a new instance of the <see cref="SceneCameraSlot"/> class.
 /// </summary>
 /// <param name="camera">The camera.</param>
 public SceneCameraSlot(CameraComponent camera)
 {
     Camera = camera;
 }
Пример #7
0
        private void SetupScene()
        {
            graphicsCompositor = new SceneGraphicsCompositorLayers
            {
                Cameras = { Camera.Get<CameraComponent>() },
                Master =
                {
                    Renderers =
                    {
                        new ClearRenderFrameRenderer { Color = Color.Green, Name = "Clear frame" },
                        //new SceneCameraRenderer { Mode = new CameraRendererModeForward { Name = "Camera renderer", ModelEffect = "XenkoForwardShadingEffect" } },
                        new SceneCameraRenderer { Mode = new CameraRendererModeForward { Name = "Camera renderer" } },
                    }
                }
            };

            Scene = new Scene { Settings = { GraphicsCompositor = graphicsCompositor } };
            Scene.Entities.Add(Camera);

            //var ambientLight = new Entity { new LightComponent { Type = new LightAmbient { Color = new ColorRgbProvider(Color.White) }, Intensity = 1 } };
            ////var ambientLight = new Entity { new LightComponent { Type = new LightDirectional { Color = new ColorRgbProvider(Color.White) }, Intensity = 1 } };
            ////ambientLight.Transform.RotationEulerXYZ = new Vector3(0.0f, (float) Math.PI, 0.0f);
            //Scene.Entities.Add(ambientLight);

            var directionalLight = new Entity { new LightComponent { Type = new LightDirectional { Color = new ColorRgbProvider(Color.White), Shadow = { Enabled = true } }, Intensity = 1 }, };
            directionalLight.Transform.Rotation = Quaternion.RotationY(MathUtil.PiOverTwo * 0.2f);
            Scene.Entities.Add(directionalLight);

            //var pointLight1 = new Entity { new LightComponent() { Type = new LightPoint { Color = new ColorRgbProvider(Color.Red), Radius = 100.0f, Shadow = { Enabled = false } }, Intensity = 1.0f } };
            //pointLight1.Transform.Position.X = 5.0f;
            //Scene.Entities.Add(pointLight1);

            //var directionalLight2 = new Entity { new LightComponent { Type = new LightSpot { Range = 25, Color = new ColorRgbProvider(Color.White), Shadow = { Enabled = false } }, Intensity = 20 }, };
            //directionalLight2.Transform.Position = Vector3.UnitX * 40;
            //directionalLight2.Transform.Rotation = Quaternion.RotationY(MathUtil.PiOverTwo);
            //Scene.Entities.Add(directionalLight2);

            var rand = new Random();
            for (int i = 0; i < 512; ++i)
            {
                var pointLight1 = new Entity
                {
                    new LightComponent()
                    {
                        Type = i % 2 == 0 ? (ILight)new LightPoint
                        {
                            Color = new ColorRgbProvider(new Color((float)rand.NextDouble(), (float)rand.NextDouble(), (float)rand.NextDouble(), 1.0f)),
                            Radius = 2.0f,
                            Shadow = { Enabled = false },
                        }
                        : new LightSpot
                        {
                            Color = new ColorRgbProvider(new Color((float)rand.NextDouble(), (float)rand.NextDouble(), (float)rand.NextDouble(), 1.0f)),
                            Range = 4.0f,
                            Shadow = { Enabled = false },
                        },
                        Intensity = 10.0f
                    }
                };
                pointLight1.Transform.Position = new Vector3(
                    (float)rand.NextDouble() * 20.0f - 10.0f,
                    (float)rand.NextDouble() * 20.0f - 10.0f,
                    (float)rand.NextDouble() * 20.0f - 10.0f
                    );
                Scene.Entities.Add(pointLight1);
            }


            SceneSystem.SceneInstance = new SceneInstance(Services, Scene);

            camera = new TestCamera();
            CameraComponent = camera.Camera;
            Script.Add(camera);
        }
Пример #8
0
        /// <summary>
        /// Calculate camera view parameters based on the entity bounding box.
        /// </summary>
        /// <param name="entity">The entity that we want to display</param>
        /// <param name="up">The vector representing the up of the entity</param>
        /// <param name="front">The vector representing the front of the entity</param>
        /// <param name="cameraComponent">The camera component used to render to object</param>
        /// <returns>Appropriate view parameters that can be used to display the entity</returns>
        public static ViewParameters CalculateViewParameters(Entity entity, Vector3 up, Vector3 front, CameraComponent cameraComponent)
        {
            var upAxis = up.Length() < MathUtil.ZeroTolerance ? Vector3.UnitY : Vector3.Normalize(up);

            // if we ensure that the whole object bounding box seen under the view vector in the frustum,
            // most of the time it results in object occupying only ~ 1/4 * 1/4 of the screen space.
            // So instead we decided to approximate the object with a bounding sphere (taking the risk that some of the objects are a little bit out of the screen)
            var boundingSphere = CalculateBoundingSpere(entity);

            // calculate the min distance from the object to see it entirely
            var minimunDistance = Math.Max(
                boundingSphere.Radius / (2f * (float)Math.Tan(cameraComponent.VerticalFieldOfView * cameraComponent.AspectRatio / 2f)),
                boundingSphere.Radius / (2f * (float)Math.Tan(cameraComponent.VerticalFieldOfView / 2f)));

            var distance = 1.2f * (minimunDistance + boundingSphere.Radius); // set the view distance such that the object can be seen entirely 
            var parameters = new ViewParameters(upAxis)
            {
                Target = boundingSphere.Center + entity.Transform.Position, // use of center of the bounding box as camera target
                Distance = distance,
                FarPlane = distance
            };

            return parameters;
        }
Пример #9
0
            public void Update(Entity entity, CameraComponent camera)
            {
                var frustumHeight = 2 * (float)Math.Tan(MathUtil.DegreesToRadians(camera.VerticalFieldOfView) / 2);

                // extract the world matrix of the UI entity
                var worldMatrix = entity.Get<TransformComponent>().WorldMatrix;

                // rotate the UI element perpendicular to the camera view vector, if billboard is activated
                var uiComponent = entity.Get<UIComponent>();

                if (!uiComponent.IsFullScreen)
                {
                    Matrix viewInverse;
                    Matrix.Invert(ref camera.ViewMatrix, out viewInverse);
                    var forwardVector = viewInverse.Forward;

                    if (uiComponent.IsBillboard)
                    {
                        // remove scale of the camera
                        viewInverse.Row1 /= viewInverse.Row1.XYZ().Length();
                        viewInverse.Row2 /= viewInverse.Row2.XYZ().Length();

                        // set the scale of the object
                        viewInverse.Row1 *= worldMatrix.Row1.XYZ().Length();
                        viewInverse.Row2 *= worldMatrix.Row2.XYZ().Length();

                        // set the adjusted world matrix
                        worldMatrix.Row1 = viewInverse.Row1;
                        worldMatrix.Row2 = viewInverse.Row2;
                        worldMatrix.Row3 = viewInverse.Row3;
                    }

                    if (uiComponent.IsFixedSize)
                    {
                        forwardVector.Normalize();
                        var distVec = (worldMatrix.TranslationVector - camera.Entity.Transform.Position);
                        float distScalar;
                        Vector3.Dot(ref forwardVector, ref distVec, out distScalar);
                        distScalar = Math.Abs(distScalar);

                        var worldScale = frustumHeight * distScalar * UIComponent.FixedSizeVerticalUnit; // FrustumHeight already is 2*Tan(FOV/2)

                        worldMatrix.Row1 *= worldScale;
                        worldMatrix.Row2 *= worldScale;
                        worldMatrix.Row3 *= worldScale;
                    }

                    // If the UI component is not drawn fullscreen it should be drawn as a quad with world sizes corresponding to its actual size
                    worldMatrix = Matrix.Scaling(uiComponent.Size / uiComponent.Resolution) * worldMatrix;
                }

                // Rotation of Pi along 0x to go from UI space to world space
                worldMatrix.Row2 = -worldMatrix.Row2;
                worldMatrix.Row3 = -worldMatrix.Row3;

                Matrix worldViewMatrix;
                Matrix.Multiply(ref worldMatrix, ref camera.ViewMatrix, out worldViewMatrix);
                Matrix.Multiply(ref worldViewMatrix, ref camera.ProjectionMatrix, out WorldViewProjectionMatrix);
            }
Пример #10
0
 protected override float ComputeScreenCoverage(CameraComponent camera, Vector3 position, Vector3 direction, float width, float height)
 {
     // As the directional light is covering the whole screen, we take the max of current width, height
     return Math.Max(width, height);
 }
Пример #11
0
            public void Update(Entity entity, CameraComponent camera)
            {
                AspectRatio = camera.AspectRatio;
                FrustumHeight = 2 * (float)Math.Tan(MathUtil.DegreesToRadians(camera.VerticalFieldOfView) / 2);

                // extract the world matrix of the UI entity
                var worldMatrix = entity.Get<TransformComponent>().WorldMatrix;

                // rotate the UI element perpendicular to the camera view vector, if billboard is activated
                var uiComponent = entity.Get<UIComponent>();
                if (!uiComponent.IsFullScreen && uiComponent.IsBillboard)
                {
                    Matrix viewInverse;
                    Matrix.Invert(ref camera.ViewMatrix, out viewInverse);

                    // remove scale of the camera
                    viewInverse.Row1 /= viewInverse.Row1.XYZ().Length();
                    viewInverse.Row2 /= viewInverse.Row2.XYZ().Length();

                    // set the scale of the object
                    viewInverse.Row1 *= worldMatrix.Row1.XYZ().Length();
                    viewInverse.Row2 *= worldMatrix.Row2.XYZ().Length();

                    // set the adjusted world matrix
                    worldMatrix.Row1 = viewInverse.Row1;
                    worldMatrix.Row2 = viewInverse.Row2;
                    worldMatrix.Row3 = viewInverse.Row3;
                }

                // Rotation of Pi along 0x to go from UI space to world space
                worldMatrix.Row2 = -worldMatrix.Row2; 
                worldMatrix.Row3 = -worldMatrix.Row3;

                ProjectionMatrix = camera.ProjectionMatrix;
                Matrix.Multiply(ref worldMatrix, ref camera.ViewMatrix, out ViewMatrix);
                Matrix.Invert(ref ViewMatrix, out ViewMatrixInverse);
                Matrix.Multiply(ref ViewMatrix, ref ProjectionMatrix, out ViewProjectionMatrix);
            }
        protected override void DrawCore(RenderContext context)
        {
            modelProcessor = SceneInstance.GetCurrent(context).GetProcessor<ModelProcessor>();
            lightProcessor = SceneInstance.GetCurrent(context).GetProcessor<LightProcessor>();

            // No light processors means no light in the scene, so we can early exit
            if (lightProcessor == null || modelProcessor == null)
            {
                return;
            }

            // Not in the context of a SceneCameraRenderer? just exit
            sceneCameraRenderer = context.Tags.Get(SceneCameraRenderer.Current);
            sceneCamera = context.Tags.Get(CameraComponentRenderer.Current);
            if (sceneCameraRenderer == null || sceneCamera == null)
            {
                return;
            }
            sceneCullingMask = sceneCameraRenderer.CullingMask;

            // Setup the callback on the ModelRenderer and shadow map LightGroupRenderer
            if (!isModelComponentRendererSetup)
            {
                // TODO: Check if we could discover declared renderers in a better way than just hacking the tags of a component
                var modelRenderer = ModelComponentRenderer.GetAttached(sceneCameraRenderer);
                if (modelRenderer == null)
                {
                    return;
                }

                modelRenderer.Callbacks.PreRenderModel += PrepareRenderModelForRendering;
                modelRenderer.Callbacks.PreRenderMesh += PreRenderMesh;

                // TODO: Make this pluggable
                // TODO: Shadows should work on mobile platforms
                if (context.GraphicsDevice.Features.Profile >= GraphicsProfile.Level_10_0
                    && (Platform.Type == PlatformType.Windows || Platform.Type == PlatformType.WindowsStore || Platform.Type == PlatformType.Windows10))
                {
                    shadowMapRenderer = new ShadowMapRenderer(modelRenderer.EffectName);
                    shadowMapRenderer.Renderers.Add(typeof(LightDirectional), new LightDirectionalShadowMapRenderer());
                    shadowMapRenderer.Renderers.Add(typeof(LightSpot), new LightSpotShadowMapRenderer());
                }

                isModelComponentRendererSetup = true;
            }

            // Collect all visible lights
            CollectVisibleLights();

            // Draw shadow maps
            if (shadowMapRenderer != null)
                shadowMapRenderer.Draw(context, visibleLightsWithShadows);

            // Prepare active renderers in an ordered list (by type and shadow on/off)
            CollectActiveLightRenderers(context);

            currentModelLightShadersPermutationEntry = null;
            currentModelShadersParameters = null;
            currentShadowReceiver = true;

            // Clear the cache of parameter entries
            lightParameterEntries.Clear();
            parameterCollectionEntryPool.Clear();

            // Clear association between model and lights
            modelToLights.Clear();

            // Clear all data generated by shader entries
            foreach (var shaderEntry in shaderEntries)
            {
                shaderEntry.Value.ResetGroupDatas();
            }
        }
Пример #13
0
 public override void Start()
 {
     camera = Entity.Get<CameraComponent>();
     simulation = this.GetSimulation();
 }
Пример #14
0
        protected override float ComputeScreenCoverage(CameraComponent camera, Vector3 position, Vector3 direction, float width, float height)
        {
            // http://stackoverflow.com/questions/21648630/radius-of-projected-sphere-in-screen-space
            // Use a sphere at target point to compute the screen coverage. This is a very rough approximation.
            // We compute the sphere at target point where the size of light is the largest
            // TODO: Check if we can improve this calculation with a better model
            var targetPosition = new Vector4(position + direction * Range, 1.0f);
            Vector4 projectedTarget;
            Vector4.Transform(ref targetPosition, ref camera.ViewProjectionMatrix, out projectedTarget);

            var d = Math.Abs(projectedTarget.W) + 0.00001f;
            var r = Range * Math.Sin(MathUtil.DegreesToRadians(AngleOuter/2.0f));
            var coTanFovBy2 = camera.ProjectionMatrix.M22;
            var pr = r * coTanFovBy2 / (Math.Sqrt(d * d - r * r) + 0.00001f);

            // Size on screen
            return (float)pr * Math.Max(width, height);
        }
Пример #15
0
        public override async Task Execute()
        {
            var config = AppConfig.GetConfiguration<Config>("CameraScript");
            flyingAround = config.FlyingAround;
            
            //uiControl = Context.RenderContext.UIControl;

            if (camera == null)
            {
                // Near plane and Far plane are swapped in order to increase float precision for far distance as near distance is already having 
                // lots of precisions by the 1/z perspective projection
                //camera = new Camera(new R32G32B32_Float(200, 0, 200), new R32G32B32_Float(0, 0, 200), 1.2f, 1280.0f / 720.0f, 4000000.0f, 10.0f);
                var zNear = 10.0f;
                var zFar = 4000000.0f;
                if (Context.RenderContext.IsZReverse)
                {
                    var temp = zNear;
                    zNear = zFar;
                    zFar = temp;
                }
                camera = new Camera(new Vector3(200, 0, 200), new Vector3(0, 0, 200), 1.2f, RenderContext.Width, RenderContext.Height, (float)RenderContext.Width / RenderContext.Height, zNear, zFar);
                camera.Mode = CameraMode.Free;
            }

            Speed = config.Speed;

            //useful when we need to debug something from a specific point of view (we can first get the WorldToCamera value using a breakpoint then set it below)
            /*Matrix mat = new Matrix();
            mat.M11 = 0.0267117824f;
            mat.M12 = -0.9257705f;
            mat.M13 = -0.377141267f;
            mat.M14 = 0.0f;
            mat.M21 = -0.9996432f;
            mat.M22 = -0.024737807f;
            mat.M23 = -0.0100777093f;
            mat.M24 = 0.0f;
            mat.M31 = 0.0f;
            mat.M32 = 0.377275884f;
            mat.M33 = -0.926100969f;
            mat.M34 = 0.0f;
            mat.M41 = 531.524963f;
            mat.M42 = 501.754761f;
            mat.M43 = 989.462646f;
            mat.M44 = 1.0f;
            camera.WorldToCamera = mat;*/

            //uiControl.MouseWheel += OnUiControlOnMouseWheel;
            var st = new Stopwatch();

            st.Start();

            var viewParameters = Context.RenderContext.RenderPassPlugins.OfType<MainPlugin>().FirstOrDefault().ViewParameters;

            Context.Scheduler.Add(() => AutoswitchCamera(Context));

            var lastTime = DateTime.UtcNow;
            var pauseTime = false;
            while (true)
            {
                await Scheduler.Current.NextFrame();

                var mousePosition = Context.InputManager.MousePosition;

                if (Context.InputManager.IsMouseButtonPressed(MouseButton.Right))
                {
                    camera.Mode = CameraMode.Free;
                    isModifyingPosition = true;

                    pitch = 0;
                    yaw = 0;
                    roll = 0;

                    if (camera.Mode == CameraMode.Free)
                    {
                        fixedFreeMatrix = camera.WorldToCamera;
                    }
                    else
                    {
                        fixedPosition = camera.Position;
                    }
                }
                if (Context.InputManager.IsMouseButtonDown(MouseButton.Right))
                {
                    var deltaX = mousePosition.X - previousX;
                    var deltaY = mousePosition.Y - previousY;
                    if (isModifyingPosition)
                    {

                        yaw += deltaX * Speed / 1000.0f;
                        pitch += deltaY * Speed / 1000.0f;

                        if (camera.Mode == CameraMode.Target)
                        {
                            camera.Position = (Vector3)Vector3.Transform(fixedPosition, Matrix.RotationX(pitch) * Matrix.RotationZ(yaw));
                            Console.WriteLine(camera.Position);
                        }
                        else
                        {
                            camera.WorldToCamera = Camera.YawPitchRoll(camera.Position, fixedFreeMatrix, yaw, -pitch, roll);
                        }

                        //uiControl.Text = "" + camera.Mode;

                        viewChanged = true;
                    }
                    else if (isModifyingFov)
                    {
                        camera.FieldOfView += deltaX / 128.0f;
                        camera.FieldOfView = Math.Max(Math.Min(camera.FieldOfView, (float)Math.PI * 0.9f), 0.01f);

                        viewChanged = true;
                    }
                }
                if (Context.InputManager.IsMouseButtonReleased(MouseButton.Right))
                {
                    isModifyingFov = false;
                    isModifyingPosition = false;

                    if (camera.Mode == CameraMode.Free && flyingAround)
                    {
                        camera.Mode = CameraMode.Target;
                    }
                }

                previousX = mousePosition.X;
                previousY = mousePosition.Y;

                if (Context.InputManager.IsKeyDown(Keys.LeftAlt) && Context.InputManager.IsKeyPressed(Keys.Enter))
                    Context.RenderContext.GraphicsDevice.IsFullScreen = !Context.RenderContext.GraphicsDevice.IsFullScreen;

                if (Context.InputManager.IsKeyPressed(Keys.F2))
                    pauseTime = !pauseTime;

                var currentTime = DateTime.UtcNow;
                if (!pauseTime)
                {
                    Context.CurrentTime += currentTime - lastTime;
                    viewParameters.Set(GlobalKeys.Time, (float)Context.CurrentTime.TotalSeconds);
                    var timeStep = (float)(currentTime - lastTime).TotalMilliseconds;
                    viewParameters.Set(GlobalKeys.TimeStep, timeStep);
                }

                // Set the pause variable for the rendering
                Context.RenderContext.IsPaused = pauseTime;
                lastTime = currentTime;
               
                if (Context.InputManager.IsKeyPressed(Keys.Space))
                {
                    // Fetch camera list
                    var cameras = Context.EntityManager.Entities
                        .Where(x => x.ContainsKey(CameraComponent.Key))
                        .Select(x => x.Get(CameraComponent.Key)).ToArray();

                    // Go to next camera
                    // If no camera or unset, index will be 0, so it will go to first one
                    int index = Array.IndexOf(cameras, TrackingCamera) + 1;
                    TrackingCamera = (index < cameras.Length) ? cameras[index] : null;
                    clock.Restart();

                    //flyingAround = !flyingAround;
                    //if (flyingAround)
                    //{
                    //    fixedPosition = camera.Position;
                    //    clock.Restart();
                    //}
                }

                if (TrackingCamera != null)
                {
                    Matrix projection, worldToCamera;

                    // Overwrite near/far plane with our camera, as they are not reliable
                    TrackingCamera.NearPlane = camera.NearClipPlane;
                    TrackingCamera.FarPlane = camera.FarClipPlane;

                    TrackingCamera.Calculate(out projection, out worldToCamera);

                    viewParameters.Set(TransformationKeys.View, worldToCamera);
                    viewParameters.Set(TransformationKeys.Projection, projection);

                    // TODO: tracking camera doesn't have proper near/far plane values. Use mouse camera near/far instead.
                    viewParameters.Set(CameraKeys.NearClipPlane, camera.NearClipPlane);
                    viewParameters.Set(CameraKeys.FarClipPlane, camera.FarClipPlane);
                    viewParameters.Set(CameraKeys.FieldOfView, TrackingCamera.VerticalFieldOfView);
                    // Console.WriteLine("FOV:{0}", trackingCamera.VerticalFieldOfView);
                    viewParameters.Set(CameraKeys.ViewSize, new Vector2(camera.Width, camera.Height));
                    viewParameters.Set(CameraKeys.Aspect, TrackingCamera.AspectRatio);
                    viewParameters.Set(CameraKeys.FocusDistance, TrackingCamera.FocusDistance);
                }
                else
                {
                    bool moved = false;

                    var localPosition = new Vector3(0, 0, 0);

                    if (Context.InputManager.IsKeyDown(Keys.Left) || Context.InputManager.IsKeyDown(Keys.A))
                    {
                        localPosition.X -= 1.0f;
                        moved = true;
                    }

                    if (Context.InputManager.IsKeyDown(Keys.Right) || Context.InputManager.IsKeyDown(Keys.D))
                    {
                        localPosition.X += 1.0f;
                        moved = true;
                    }

                    if (Context.InputManager.IsKeyDown(Keys.Up) || Context.InputManager.IsKeyDown(Keys.W))
                    {
                        localPosition.Y -= 1.0f;
                        moved = true;
                    }
                    if (Context.InputManager.IsKeyDown(Keys.Down) || Context.InputManager.IsKeyDown(Keys.S))
                    {
                        localPosition.Y += 1.0f;
                        moved = true;
                    }

                    if (Context.InputManager.IsKeyDown(Keys.R))
                    {
                        roll += 0.1f;
                    }

                    if (Context.InputManager.IsKeyDown(Keys.T))
                    {
                        roll -= 0.1f;
                    }

                    var moveSpeedFactor = Context.InputManager.IsKeyDown(Keys.LeftShift) || Context.InputManager.IsKeyDown(Keys.RightShift) ? 0.1f : 1.0f;

                    localPosition.Normalize();
                    localPosition *= (float)clock.ElapsedTicks * 1000.0f * MoveSpeed * moveSpeedFactor / Stopwatch.Frequency;

                    localVelocity = localVelocity * 0.9f + localPosition * 0.1f;

                    if (localVelocity.Length() > MoveSpeed * 0.001f)
                    {

                        if (camera.Mode == CameraMode.Target)
                            camera.Position = camera.Position + localVelocity;
                        else
                        {
                            var destVector = ((Vector3)camera.WorldToCamera.Column3);
                            var leftRightVector = Vector3.Cross(destVector, Vector3.UnitZ);
                            leftRightVector.Normalize();

                            var newPosition = camera.Position - destVector * localVelocity.Y;
                            newPosition = newPosition - leftRightVector * localVelocity.X;
                            camera.Position = newPosition;
                        }

                        viewChanged = true;
                    }

                    if (flyingAround)
                    {
                        camera.Position = (Vector3)Vector3.Transform(camera.Position, Matrix.RotationZ(clock.ElapsedMilliseconds * Speed / 10000.0f));
                        viewChanged = true;
                    }

                    if (Context.InputManager.IsKeyPressed(Keys.F))
                    {
                        camera.FieldOfView -= 0.1f;
                        viewChanged = true;
                    }

                    if (Context.InputManager.IsKeyPressed(Keys.G))
                    {
                        camera.FieldOfView += 0.1f;
                        viewChanged = true;
                    }

                    //if (viewChanged)
                    {
                        viewParameters.Set(TransformationKeys.View, camera.WorldToCamera);
                        viewParameters.Set(TransformationKeys.Projection, camera.Projection);
                        viewParameters.Set(CameraKeys.NearClipPlane, camera.NearClipPlane);
                        viewParameters.Set(CameraKeys.FarClipPlane, camera.FarClipPlane);
                        viewParameters.Set(CameraKeys.FieldOfView, camera.FieldOfView);
                        //Console.WriteLine("FOV:{0}", camera.FieldOfView);
                        viewParameters.Set(CameraKeys.ViewSize, new Vector2(camera.Width, camera.Height));
                        viewParameters.Set(CameraKeys.Aspect, camera.Aspect);
                        viewParameters.Set(CameraKeys.FocusDistance, 0.0f);
                        //Console.WriteLine("Camera: {0}", camera);

                    }

                    if (Context.InputManager.IsKeyPressed(Keys.I))
                    {
                        var worldToCamera = camera.WorldToCamera;
                        var target = (Vector3)worldToCamera.Column3;
                        Console.WriteLine("camera.Position = new R32G32B32_Float({0}f,{1}f,{2}f); camera.Target = camera.Position + new R32G32B32_Float({3}f, {4}f, {5}f);", camera.Position.X, camera.Position.Y, camera.Position.Z, target.X, target.Y, target.Z);
                    }

                    viewChanged = false;
                    clock.Restart();
                }
            }
        }
Пример #16
0
            public void Update(Entity entity, Vector3 virtualResolution)
            {
                var nearPlane = virtualResolution.Z / 2;
                var farPlane = nearPlane + virtualResolution.Z;
                var zOffset = nearPlane + virtualResolution.Z / 2;
                var aspectRatio = virtualResolution.X / virtualResolution.Y;
                var verticalFov = (float)Math.Atan2(virtualResolution.Y / 2, zOffset) * 2;

                var cameraComponent = new CameraComponent(nearPlane, farPlane)
                {
                    UseCustomAspectRatio = true,
                    AspectRatio = aspectRatio,
                    VerticalFieldOfView = MathUtil.RadiansToDegrees(verticalFov),
                    ViewMatrix = Matrix.LookAtRH(new Vector3(0, 0, zOffset), Vector3.Zero, Vector3.UnitY),
                    ProjectionMatrix = Matrix.PerspectiveFovRH(verticalFov, aspectRatio, nearPlane, farPlane),
                };

                Update(entity, cameraComponent);
            }
Пример #17
0
        public async Task AutoswitchCamera(EngineContext engineContext)
        {
            bool autoswitch = false;
            while (true)
            {
                // Fetch camera list
                var cameras = Context.EntityManager.Entities
                    .Where(x => x.ContainsKey(CameraComponent.Key))
                    .Select(x => x.Get(CameraComponent.Key)).ToArray();

                if (engineContext.InputManager.IsKeyPressed(Keys.F8))
                {
                    autoswitch = !autoswitch;
                }

                int index = Array.IndexOf(cameras, TrackingCamera);
                if (autoswitch)
                {
                    if (index == 1)
                        index = 2;
                    else
                        index = 1;
                    TrackingCamera = (index < cameras.Length) ? cameras[index] : null;
                }

                await TaskEx.Delay((index == 1) ? 50000 : 10000);
            }
        }
Пример #18
0
 protected abstract float ComputeScreenCoverage(CameraComponent camera, Vector3 position, Vector3 direction, float width, float height);
        private void UpdateFrustum(CameraComponent camera)
        {
            var projectionToView = camera.ProjectionMatrix;
            projectionToView.Invert();

            // Compute frustum-dependent variables (common for all shadow maps)
            var projectionToWorld = camera.ViewProjectionMatrix;
            projectionToWorld.Invert();

            // Transform Frustum corners in World Space (8 points) - algorithm is valid only if the view matrix does not do any kind of scale/shear transformation
            for (int i = 0; i < 8; ++i)
            {
                Vector3.TransformCoordinate(ref FrustumBasePoints[i], ref projectionToWorld, out frustumCornersWS[i]);
                Vector3.TransformCoordinate(ref FrustumBasePoints[i], ref projectionToView, out frustumCornersVS[i]);
            }
        }
Пример #20
0
        public static bool ScreenPositionToWorldPositionRaycast(Vector2 screenPos, CameraComponent camera, Simulation simulation, out ClickResult clickResult)
        {
            Matrix invViewProj = Matrix.Invert(camera.ViewProjectionMatrix);

            Vector3 sPos;
            sPos.X = screenPos.X * 2f - 1f;
            sPos.Y = 1f - screenPos.Y * 2f;

            sPos.Z = 0f;
            var vectorNear = Vector3.Transform(sPos, invViewProj);
            vectorNear /= vectorNear.W;

            sPos.Z = 1f;
            var vectorFar = Vector3.Transform(sPos, invViewProj);
            vectorFar /= vectorFar.W;

            clickResult.ClickedEntity = null;
            clickResult.WorldPosition = Vector3.Zero;
            clickResult.Type = ClickType.Empty;
            clickResult.HitResult = new HitResult();

            var minDistance = float.PositiveInfinity;

            var result = simulation.RaycastPenetrating(vectorNear.XYZ(), vectorFar.XYZ());
            foreach (var hitResult in result)
            {
                ClickType type = ClickType.Empty;
                
                var staticBody = hitResult.Collider as StaticColliderComponent;
                if (staticBody != null)
                {
                    if (staticBody.CollisionGroup == CollisionFilterGroups.CustomFilter1)
                        type = ClickType.Ground;

                    if (staticBody.CollisionGroup == CollisionFilterGroups.CustomFilter2)
                        type = ClickType.LootCrate;

                    if (type != ClickType.Empty)
                    {
                        var distance = (vectorNear.XYZ() - hitResult.Point).LengthSquared();
                        if (distance < minDistance)
                        {
                            minDistance = distance;
                            clickResult.Type = type;
                            clickResult.HitResult = hitResult;
                            clickResult.WorldPosition = hitResult.Point;
                            clickResult.ClickedEntity = hitResult.Collider.Entity;
                        }
                    }
                }
            }

            return (clickResult.Type != ClickType.Empty);
        }