public CameraManager(Game game) : base(game) { game.Services.AddService(typeof(ICameraManager), this); fGraphics = (GraphicsDeviceManager)game.Services.GetService(typeof(IGraphicsDeviceManager)); fCameras = new Dictionary<String, Camera>(); fActiveCamera = null; fActiveFrustumCamera = null; }
public void Draw(Sphere planet, Camera camera) { // Apply matrices to the relevant bones, as discussed in the Simple // Animation Sample. leftBackWheelBone.Transform = wheelRollMatrix * leftBackWheelTransform; rightBackWheelBone.Transform = wheelRollMatrix * rightBackWheelTransform; leftFrontWheelBone.Transform = wheelRollMatrix * leftFrontWheelTransform; rightFrontWheelBone.Transform = wheelRollMatrix * rightFrontWheelTransform; // now that we've updated the wheels' transforms, we can create an array // of absolute transforms for all of the bones, and then use it to draw. Matrix[] boneTransforms = new Matrix[model.Bones.Count]; model.CopyAbsoluteBoneTransformsTo(boneTransforms); // get world space position by adding terrain node position to planet position Position3 worldSpacePosition = movement.Position; // translate to camera space by subtracting the camera position, scale by planet scale Position3 cameraSpacePosition = (worldSpacePosition - camera.Position) * planet.Scale; Matrix cameraSpaceMatrix = planet.ScaleMatrix * movement.WorldMatrix * Matrix.CreateTranslation(cameraSpacePosition.AsVector3); Vector3 lightDirection = (planet.Position - Position3.Zero).AsVector3; lightDirection.Normalize(); foreach (ModelMesh mesh in model.Meshes) { foreach (BasicEffect effect in mesh.Effects) { effect.World = boneTransforms[mesh.ParentBone.Index] * cameraSpaceMatrix; effect.View = camera.ViewMatrix; effect.Projection = camera.ProjectionMatrix; effect.DirectionalLight0.Direction = -lightDirection; effect.EnableDefaultLighting(); effect.VertexColorEnabled = false; effect.PreferPerPixelLighting = true; } mesh.Draw(); } }
/// <summary> /// Loads the content used by the lensflare component. /// </summary> public void LoadContent(Game game) { this.game = game; fCameraManager = (ICameraManager)game.Services.GetService(typeof(ICameraManager)); // Create a SpriteBatch for drawing the glow and flare sprites. spriteBatch = new SpriteBatch(game.GraphicsDevice); // Load the glow and flare textures. glowSprite = game.Content.Load<Texture2D>(@"textures\glow"); foreach (Flare flare in flares) { flare.Texture = game.Content.Load<Texture2D>(@"textures\" + flare.TextureName); } // Effect and vertex declaration for drawing occlusion query polygons. basicEffect = new BasicEffect(game.GraphicsDevice); basicEffect.View = Matrix.Identity; basicEffect.VertexColorEnabled = true; fMaskCombine = game.Content.Load<Effect>(@"effects\maskcombine"); vertexDeclaration = VertexPositionColor.VertexDeclaration; // new VertexDeclaration(game.GraphicsDevice, VertexPositionColor.VertexElements); // Create vertex data for the occlusion query polygons. queryVertices = new VertexPositionColor[4]; queryVertices[0].Position = new Vector3(-querySize / 2, -querySize / 2, -1); queryVertices[1].Position = new Vector3( querySize / 2, -querySize / 2, -1); queryVertices[2].Position = new Vector3( querySize / 2, querySize / 2, -1); queryVertices[3].Position = new Vector3(-querySize / 2, querySize / 2, -1); // Create the occlusion query object. occlusionQuery = new OcclusionQuery(game.GraphicsDevice); fSunCamera = fCameraManager.GetCamera("SunCam"); PresentationParameters pp = game.GraphicsDevice.PresentationParameters; fSunView = new RenderTarget2D(game.GraphicsDevice, MaskSize, MaskSize, false, pp.BackBufferFormat, pp.DepthStencilFormat, pp.MultiSampleCount, RenderTargetUsage.DiscardContents); fIntensityMap = new RenderTarget2D(game.GraphicsDevice, 1, 1, false, SurfaceFormat.Single, pp.DepthStencilFormat, pp.MultiSampleCount, RenderTargetUsage.DiscardContents); fIntensityEffect = game.Content.Load<Effect>(@"effects\intensity"); fIntensityMaskVertexDeclaration = VertexPositionTexture.VertexDeclaration; // new VertexDeclaration(game.GraphicsDevice, VertexPositionTexture.VertexElements); fOcclusionPoints = GenerateOcclusionPoints(); }
private void DrawTerrainNodeMask(TerrainNode terrainNode, Position3 cameraPosition, float horizonAngle, Sphere sphere, Camera camera) { // this can happen if a node was partially split if (terrainNode == null) return; // no need to draw or recurse any deeper if the node isn't visible if (CullTerrainNode(terrainNode, cameraPosition, horizonAngle, sphere, cameraManager.ActiveFrustumCamera)) { // if the node is being split then we can cancel the split if it's not visible terrainNode.CancelSplitting = true; return; } // we only draw leaf nodes, so recurse down until we find them, then draw them // a node that's splitting is considered a leaf node if (!terrainNode.Splitting && terrainNode.HasChildren) { DrawTerrainNodeMask(terrainNode.Children[0], cameraPosition, horizonAngle, sphere, camera); DrawTerrainNodeMask(terrainNode.Children[1], cameraPosition, horizonAngle, sphere, camera); DrawTerrainNodeMask(terrainNode.Children[2], cameraPosition, horizonAngle, sphere, camera); DrawTerrainNodeMask(terrainNode.Children[3], cameraPosition, horizonAngle, sphere, camera); } else { // get world space position by adding terrain node position to planet position Position3 worldSpacePosition = sphere.Position + terrainNode.Position; // translate to camera space by subtracting the camera position, scale by planet scale Position3 cameraSpacePosition = (worldSpacePosition - camera.Position) * sphere.Scale; Matrix cameraSpaceMatrix = sphere.ScaleMatrix * Matrix.CreateTranslation(cameraSpacePosition.AsVector3); Matrix worldViewProjectionMatrix = cameraSpaceMatrix * camera.ViewProjectionMatrix; // we're drawing in black, so we don't need to much information planetEffectMask.Parameters["WorldViewProj"].SetValue(worldViewProjectionMatrix); planetEffectMask.CurrentTechnique.Passes[0].Apply(); GraphicsDevice.SetVertexBuffer(terrainNode.VertexBuffer.VertexBuffer); GraphicsDevice.Indices = TerrainNodeIndexBuffer.Indices; GraphicsDevice.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, terrainNode.VertexBuffer.VertexCount, 0, TerrainNodeIndexBuffer.IndexCount / 3); } }
private void DrawTerrainNode(TerrainNode terrainNode, Position3 cameraPosition, float horizonAngle, Sphere sphere, Camera camera) { // this can happen if a node was partially split if (terrainNode == null) return; // no need to draw or recurse any deeper if the node isn't visible if (CullTerrainNode(terrainNode, cameraPosition, horizonAngle, sphere, cameraManager.ActiveFrustumCamera)) { // if the node is being split then we can cancel the split if it's not visible terrainNode.CancelSplitting = true; return; } // we only draw leaf nodes, so recurse down until we find them, then draw them // a node that's splitting is considered a leaf node if (!terrainNode.Splitting && terrainNode.HasChildren) { DrawTerrainNode(terrainNode.Children[0], cameraPosition, horizonAngle, sphere, camera); DrawTerrainNode(terrainNode.Children[1], cameraPosition, horizonAngle, sphere, camera); DrawTerrainNode(terrainNode.Children[2], cameraPosition, horizonAngle, sphere, camera); DrawTerrainNode(terrainNode.Children[3], cameraPosition, horizonAngle, sphere, camera); } else { Globals.DrawCount++; // track max draw level if (terrainNode.Level > Globals.DrawLevel) Globals.DrawLevel = terrainNode.Level; // get world space position by adding terrain node position to planet position Position3 worldSpacePosition = sphere.Position + terrainNode.Position; // translate to camera space by subtracting the camera position, scale by planet scale Position3 cameraSpacePosition = (worldSpacePosition - camera.Position) * sphere.Scale; Matrix cameraSpaceMatrix = sphere.ScaleMatrix * Matrix.CreateTranslation(cameraSpacePosition.AsVector3); Matrix worldViewProjectionMatrix = cameraSpaceMatrix * camera.ViewProjectionMatrix; // get light position, translated to camera space, TODO : light position is currently in the solar system center Vector3 lightPosition = (Vector3)(camera.Position - new Position3(0, 0, 0)); // get light direction - "space" doesn't matter here since it's just a direction Vector3 lightDirection = (Vector3)(worldSpacePosition - new Position3(0, 0, 0)); lightDirection.Normalize(); // determine which shader to use double altitude = mainCamera.fLocalPosition.Length(); Effect effect; #if atmosphere if (altitude <= Constants.EarthAtmosphereRadius) effect = planetEffectBumpAtmosphere; else effect = planetEffectBumpSpace; #else effect = planetEffect; #endif effect.Parameters["WorldViewProj"].SetValue(worldViewProjectionMatrix); effect.Parameters["LightDirection"].SetValue(-lightDirection); if (effect == planetEffectTexture) { //effect.Parameters["Tint"].SetValue(new Vector4(1, 1, 1, 1)); effect.Parameters["DiffuseTexture"].SetValue(terrainNode.DiffuseTexture); } else if (effect != planetEffectBasic) { effect.Parameters["WorldMatrix"].SetValue(cameraSpaceMatrix); effect.Parameters["DiffuseTexture"].SetValue(terrainNode.DiffuseTexture); effect.Parameters["NormalTexture"].SetValue(terrainNode.NormalTexture); } /* if (terrainNode == tank.NodeUnderTank) effect.Parameters["Tint"].SetValue(new Vector4(1.0f, 0.5f, 0.5f, 1f)); else*/ effect.Parameters["Tint"].SetValue(new Vector4(1f, 1f, 1f, 1f)); // set up atmosphere parameters #if atmosphere groundFromSpace.ResolveParameters(effect); float cameraHeight = (float)(camera.Position - sphere.Position).Length(); Vector3 cameraPositionNode = (camera.Position - sphere.Position).AsVector3; Vector3 vLightDirection = (Vector3)(Position3.Zero - camera.Position); vLightDirection.Normalize(); effect.Parameters["PatchPosition"].SetValue(terrainNode.Position.AsVector3); effect.Parameters["v3CameraPos"].SetValue(cameraPositionNode); effect.Parameters["v3LightPos"].SetValue(vLightDirection); effect.Parameters["fCameraHeight"].SetValue(cameraHeight); effect.Parameters["fCameraHeight2"].SetValue(cameraHeight * cameraHeight); #endif effect.CurrentTechnique.Passes[0].Apply(); GraphicsDevice.SetVertexBuffer(terrainNode.VertexBuffer.VertexBuffer); GraphicsDevice.Indices = TerrainNodeIndexBuffer.Indices; GraphicsDevice.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, terrainNode.VertexBuffer.VertexCount, 0, TerrainNodeIndexBuffer.IndexCount / 3); //DrawNodeFrustum(terrainNode); } }
/// <summary> /// Determine if this node should be culled, either horizon or view frustum /// </summary> /// <param name="cameraPosition">Camera position in planet space</param> /// <param name="horizonAngle">Horizon angle in radians</param> /// <returns>Boolean indicating whether or not the node should be culled</returns> private bool CullTerrainNode(TerrainNode terrainNode, Position3 cameraPosition, float horizonAngle, Sphere sphere, Camera camera) { // don't cull away top level nodes if they're splitting if (terrainNode.Splitting && terrainNode.Level <= 2) return false; Position3 nodePosition; ///// horizon culling ///// if (!Constants.DisableHorizonCulling && horizonAngle != 0) { if (terrainNode.Level >= 2) { // get the camera position on the unit sphere Position3 unitCameraPosition = cameraPosition; unitCameraPosition.Normalize(); // get the planet node position on the unit sphere nodePosition = terrainNode.ClosestPosition; nodePosition.Normalize(); // get the node's angle relative to the camera float angle = (float)Math.Acos(Position3.Dot(unitCameraPosition, nodePosition)); // if it's over the horizon then cull the node if (angle > horizonAngle) { Globals.HorizonCullCount++; return true; } } } ///// view frustum culling ///// if (!Constants.DisableFrustumCulling) { // get node's camera space position nodePosition = (sphere.Position + terrainNode.Position) - camera.Position; // create a matrix for frustum culling Matrix M = sphere.ScaleMatrix * Matrix.CreateTranslation(nodePosition.AsVector3 * (float)sphere.Scale); // create bounding box transformed to camera space Vector3 MinV; Vector3 MaxV; MinV = Vector3.Transform(terrainNode.MinVertex, M); MaxV = Vector3.Transform(terrainNode.MaxVertex, M); BoundingBox B = new BoundingBox(MinV, MaxV); ContainmentType CT; // if it's not contained within the view frustum then cull the node camera.Frustum.Contains(ref B, out CT); if (CT == ContainmentType.Disjoint) { Globals.FrustumCullCount++; return true; } } // otherwise it's visible return false; }
//#if perfhud // private void PreparingDeviceSettings(object sender, PreparingDeviceSettingsEventArgs e) // { // foreach (GraphicsAdapter adapter in GraphicsAdapter.Adapters) // { // if (adapter.Description.Contains("PerfHUD")) // { // e.GraphicsDeviceInformation.Adapter = adapter; // //e.GraphicsDeviceInformation.DeviceType = DeviceType.Reference; // break; // } // } // return; // } //#endif protected override void Initialize() { // main camera mainCamera = cameraManager.CreateCamera("Main"); mainCamera.fViewport = GraphicsDevice.Viewport; mainCamera.fLocalPosition = new Position3(0, 0, 10000); mainCamera.AcceptInput = true; // frustum camera if (Constants.UseFrustumCamera) { frustumCamera = cameraManager.CreateCamera("Frustum"); frustumCamera.fViewport = GraphicsDevice.Viewport; frustumCamera.fLocalPosition = new Position3(0, 0, 10000); frustumCamera.AcceptInput = false; //cameraManager.ActivateFrustumCamera("Frustum"); } // sun camera sunCamera = cameraManager.CreateCamera("SunCam"); sunCamera.fViewport = new Viewport(); sunCamera.fViewport.Width = 32; sunCamera.fViewport.Height = 32; // frame rate calculation frameRate = new FrameRate(this); frameRate.UpdateOrder = 1; Components.Add(frameRate); Mouse.SetPosition(Window.ClientBounds.Width / 2, Window.ClientBounds.Height / 2); base.Initialize(); ResetCameraPosition(); }
public void Clone(Camera camera) { Orientation = camera.Orientation; fLocalPosition = camera.fLocalPosition; UpdateCamera(0); }
public void ActivateCamera(string Name) { //if (fActiveCamera != null) // fActiveCamera.AcceptInput = false; fActiveCamera = GetCamera(Name); if (fActiveFrustumCamera == null) fActiveFrustumCamera = fActiveCamera; //if (fActiveCamera != null) // fActiveCamera.AcceptInput = true; }
public void RemoveCamera(string Name) { Camera C = GetCamera(Name); if (fActiveCamera == C) { fActiveCamera = null; if (fActiveFrustumCamera == C) fActiveFrustumCamera = null; } fCameras.Remove(Name); }
public Camera CreateCamera(string Name) { Camera Result = new Camera(Game); AddCamera(Name, Result); return Result; }
public void AddCamera(string Name, Camera C) { fCameras.Add(Name, C); // active this camera if it's the first one added if (fActiveCamera == null && fCameras.Count == 1) { fActiveCamera = C; fActiveCamera.AcceptInput = true; if (fActiveFrustumCamera == null) fActiveFrustumCamera = fActiveCamera; } }
public void ActivateFrustumCamera(string Name) { fActiveFrustumCamera = GetCamera(Name); }