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); }
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; }
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; }
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); }
/// <summary> /// Initializes a new instance of the <see cref="SceneCameraSlot"/> class. /// </summary> /// <param name="camera">The camera.</param> public SceneCameraSlot(CameraComponent camera) { Camera = camera; }
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); }
/// <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; }
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); }
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); }
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(); } }
public override void Start() { camera = Entity.Get<CameraComponent>(); simulation = this.GetSimulation(); }
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); }
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(); } } }
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); }
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); } }
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]); } }
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); }