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;
        }
Exemple #2
0
        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();
    }
Exemple #8
0
 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);
 }