Ejemplo n.º 1
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();
              }
        }
Ejemplo n.º 2
0
    private void DrawSphereMask(Sphere sphere)
    {
      //GraphicsDevice.VertexDeclaration = positionNormalTextureHeight;

      GraphicsDevice.DepthStencilState = DepthStencilState.Default;
      GraphicsDevice.BlendState = BlendState.Opaque;
      GraphicsDevice.RasterizerState = currentRasterizerState;

      //CalculateProjection();

      Camera camera = cameraManager.ActiveCamera;


      // get frustum camera position in planet space
      Position3 cameraPosition = camera.Position - sphere.Position;

      // calculate horizon angle, using camera position in planet space
      float horizonAngle = sphere.CalculateHorizonAngle(cameraPosition);

      DrawTerrainNodeMask(sphere.Front, cameraPosition, horizonAngle, sphere, camera);
      DrawTerrainNodeMask(sphere.Back, cameraPosition, horizonAngle, sphere, camera);
      DrawTerrainNodeMask(sphere.Left, cameraPosition, horizonAngle, sphere, camera);
      DrawTerrainNodeMask(sphere.Right, cameraPosition, horizonAngle, sphere, camera);
      DrawTerrainNodeMask(sphere.Top, cameraPosition, horizonAngle, sphere, camera);
      DrawTerrainNodeMask(sphere.Bottom, cameraPosition, horizonAngle, sphere, camera);
    }
Ejemplo n.º 3
0
    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);
      }
    }
Ejemplo n.º 4
0
    private void DrawSphere(Sphere sphere)
    {
      // get frustum camera position in planet space
      Camera frustumCamera = cameraManager.ActiveFrustumCamera;
      Position3 frustumCameraPosition = frustumCamera.Position - sphere.Position;

      // update sphere, allowing it to split
      sphere.Update(frustumCameraPosition, MathHelper.ToRadians(frustumCamera.FieldOfView));


      //GraphicsDevice.VertexDeclaration = positionNormalTextureHeight;
      GraphicsDevice.DepthStencilState = DepthStencilState.Default;
      GraphicsDevice.BlendState = BlendState.Opaque;
      GraphicsDevice.RasterizerState = currentRasterizerState;

      CalculateProjection(sphere);


      Camera camera = mainCamera;


      // get frustum camera position in planet space
      Position3 cameraPosition = camera.Position - sphere.Position;

      // calculate horizon angle, using camera position in planet space
      float horizonAngle = sphere.CalculateHorizonAngle(cameraPosition);

      Globals.DrawLevel = 0;
      Globals.DrawCount = 0;
      Globals.HorizonCullCount = 0;
      Globals.FrustumCullCount = 0;

      DrawTerrainNode(sphere.Front, cameraPosition, horizonAngle, sphere, camera);
      DrawTerrainNode(sphere.Back, cameraPosition, horizonAngle, sphere, camera);
      DrawTerrainNode(sphere.Left, cameraPosition, horizonAngle, sphere, camera);
      DrawTerrainNode(sphere.Right, cameraPosition, horizonAngle, sphere, camera);
      DrawTerrainNode(sphere.Top, cameraPosition, horizonAngle, sphere, camera);
      DrawTerrainNode(sphere.Bottom, cameraPosition, horizonAngle, sphere, camera);
    }
Ejemplo n.º 5
0
    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);
      }
    }
Ejemplo n.º 6
0
    /// <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;
    }
Ejemplo n.º 7
0
    private void CalculateProjection(Sphere sphere)
    {
      Camera C = cameraManager.ActiveCamera;

      double H = (sphere.Position - C.Position).Length();
      double L = H; //  H - 9.0;

      if (L < sphere.Radius + 10.0)  // TODO : the distance here is important - might need to scale to planet size
      {
        C.NearClip = (float)(0.001 / sphere.Radius);
        C.FarClip = 20000.0f;
        C.UpdateProjectionMatrix();
      }
      else if (L < sphere.Radius + 20.0)  // TODO : the distance here is important - might need to scale to planet size
      {
        C.NearClip = (float)(0.01 / sphere.Radius);
        C.FarClip = 20000.0f;
        C.UpdateProjectionMatrix();
      }
      else if (L < sphere.Radius + 50.0)  // TODO : the distance here is important - might need to scale to planet size
      {
        C.NearClip = (float)(0.1 / sphere.Radius);
        C.FarClip = 20000.0f;
        C.UpdateProjectionMatrix();
      }
      else if (L < sphere.Radius + 6000.0)
      {
        C.NearClip = 0.001f; //  0.000001f; //  (float)(1.0 /* 30.0 */ / sphere.Radius);
        C.FarClip = 20000.0f;
        C.UpdateProjectionMatrix();
      }
      else
      {
        C.NearClip = 0.001f; //  (float)(0.1 /* 150.0 */ / sphere.Radius);
        C.FarClip = 20000.0f;
        C.UpdateProjectionMatrix();
      }
    }
Ejemplo n.º 8
0
    protected override void LoadContent()
    {
      WireFrame = new RasterizerState {
        CullMode = CullMode.CullCounterClockwiseFace,
        FillMode = FillMode.WireFrame,
        MultiSampleAntiAlias = true
      };


      DepthNoWrite = new DepthStencilState
      {
        DepthBufferEnable = true,
        DepthBufferWriteEnable = false
      };


      CullClockwiseSolid = new RasterizerState
      {
        CullMode = CullMode.CullClockwiseFace,
        FillMode = FillMode.Solid,
        MultiSampleAntiAlias = true
      };


      CullClockwiseWireFrame = new RasterizerState
      {
        CullMode = CullMode.CullClockwiseFace,
        FillMode = FillMode.WireFrame,
        MultiSampleAntiAlias = true
      };



      currentRasterizerState = RasterizerState.CullCounterClockwise;

      TerrainNodeDelegates.InitializeTerrainNodeDelegates(GraphicsDevice);
      TerrainNodeSplitManager.Initialize(this);

      spriteBatch = new SpriteBatch(GraphicsDevice);
      positionNormalTextureHeight = VertexPositionNormalTextureHeight.VertexDeclaration; // new VertexDeclaration(GraphicsDevice, VertexPositionNormalTextureHeight.VertexElements);
      positionColor = VertexPositionColor.VertexDeclaration; // new VertexDeclaration(GraphicsDevice, VertexPositionColor.VertexElements);

      dirtTexture = Content.Load<Texture2D>(@"Textures\dirt_01");
      grassTexture = Content.Load<Texture2D>(@"Textures\grass_01");
      sunGlowTexture = Content.Load<Texture2D>(@"textures\sun_glow");
      planetEffectMask = Content.Load<Effect>(@"Effects\PlanetMask");
      planetEffectBasic = Content.Load<Effect>(@"Effects\PlanetBasic");
      planetEffectTexture = Content.Load<Effect>(@"Effects\PlanetBasicTexture");
      planetEffectBump = Content.Load<Effect>(@"Effects\PlanetBump");
      planetEffectBumpSpace = Content.Load<Effect>(@"Effects\PlanetBumpFromSpace");
      planetEffectBumpAtmosphere = Content.Load<Effect>(@"Effects\PlanetBumpFromAtmosphere");
      planetEffectBumpMaps = Content.Load<Effect>(@"Effects\PlanetBumpMaps");

      planetEffectAtmosphereSpace = Content.Load<Effect>(@"Effects\AtmosphereBasicSpace");
      planetEffectAtmosphereAtmosphere = Content.Load<Effect>(@"Effects\AtmosphereBasicAtmosphere");

      // select initial render effect
      planetEffect = null;
      SelectNextRenderMode();


#if sun
      sunBasicEffect = Content.Load<Effect>(@"Effects\SunBasic");
#endif

      debugTextFont = Content.Load<SpriteFont>(@"Fonts\DebugTextFont");


      // initialize terrain node index buffer
      TerrainNodeIndexBuffer.CreateIndices(GraphicsDevice, Constants.PatchWidth, Constants.PatchHeight);


      // create test sphere
      Position3 p = new Position3(1, 1, 1);
      p.Normalize();
      p *= 149597870.691;     // earth -> sun distance

#if planet
      sphere = new Sphere(p, Constants.EarthRadius, true, TerrainNodeDelegates.CreatePositionPlanet, TerrainNodeDelegates.CreateTerrainNodeVertexBuffer, false);
#endif

#if atmosphere
      // create test atmosphere
      atmosphere = new Sphere(p, Constants.EarthAtmosphereRadius, true, TerrainNodeDelegates.CreatePositionSphere, TerrainNodeDelegates.CreateTerrainNodeVertexBuffer, true);

      // create atmosphere shaders
      groundFromSpace = new AtmosphereShader();
#endif

#if sun
      // create sun
      sun = new Sphere(Position3.Zero, Constants.SunRadius, false, TerrainNodeDelegates.CreatePositionSphere, TerrainNodeDelegates.CreateTerrainNodeVertexBuffer, true);
#endif


      testEffect = new BasicEffect(GraphicsDevice);
      testSquare = GenerateSquare(25, 0, Color.LawnGreen);

      mainCamera.AttachedPosition = p;  // camera is attached to the sphere
      mainCamera.UpdateCamera(0);
      mainCamera.LookAt(Position3.Zero);

      if (frustumCamera != null)
      {
        frustumCamera.AttachedPosition = p;  // camera is attached to the sphere
        frustumCamera.UpdateCamera(0);
        frustumCamera.LookAt(Position3.Zero);
      }

      // space dome
      spaceDome = new SpaceDome(Constants.EarthRadius * 3.0, Constants.EarthRadius * 100.0);
      spaceDome.LoadContent(this);

      tank = new Tank();
      tank.LoadContent(this);
      tank.Movement.AttachedPosition = p;
      tank.Movement.UpdateMovement(0);


      sunGlowEffect = Content.Load<Effect>(@"effects\billboard");
      billboardVertexDeclaration = VertexPositionTexture.VertexDeclaration; // new VertexDeclaration(this.GraphicsDevice, VertexPositionTexture.VertexElements);
      GenerateSunVertices();


#if lensflare
      // lens flare
      lensFlare = new LensFlareComponent();
      lensFlare.LoadContent(this);
      lensFlare.LightPosition = Position3.Zero;
      lensFlare.MaskMode = true;
#endif


    }
Ejemplo n.º 9
0
    private void DrawAtmosphere(Sphere sphere)
    {
      // get frustum camera position in planet space
      Camera frustumCamera = cameraManager.ActiveFrustumCamera;
      Position3 frustumCameraPosition = frustumCamera.Position - sphere.Position;

      // update sphere, allowing it to split
      sphere.Update(frustumCameraPosition, MathHelper.ToRadians(frustumCamera.FieldOfView));

      if (fillMode == FillMode.Solid)
        GraphicsDevice.RasterizerState = CullClockwiseSolid;
      else
        GraphicsDevice.RasterizerState = CullClockwiseWireFrame;

      GraphicsDevice.DepthStencilState = DepthNoWrite;
      GraphicsDevice.BlendState = BlendState.NonPremultiplied;

      //CalculateProjection(sphere);


      Camera camera = mainCamera;


      // get frustum camera position in planet space
      Position3 cameraPosition = camera.Position - sphere.Position;

      // calculate horizon angle, using camera position in planet space
      float horizonAngle = sphere.CalculateHorizonAngle(cameraPosition);

      Globals.DrawLevel = 0;
      Globals.DrawCount = 0;
      Globals.HorizonCullCount = 0;
      Globals.FrustumCullCount = 0;

      DrawAtmosphereNode(sphere.Front, cameraPosition, horizonAngle, sphere, camera);
      DrawAtmosphereNode(sphere.Back, cameraPosition, horizonAngle, sphere, camera);
      DrawAtmosphereNode(sphere.Left, cameraPosition, horizonAngle, sphere, camera);
      DrawAtmosphereNode(sphere.Right, cameraPosition, horizonAngle, sphere, camera);
      DrawAtmosphereNode(sphere.Top, cameraPosition, horizonAngle, sphere, camera);
      DrawAtmosphereNode(sphere.Bottom, cameraPosition, horizonAngle, sphere, camera);
    }
Ejemplo n.º 10
0
        public void HandleInput(GameTime gameTime, Sphere planet, IInputManager inputManager)
        {
            double height;
              Vector3 normal;

              Triangle = null;

              Position3 oldPosition = movement.fLocalPosition;
              movement.Update(gameTime);

              NodeUnderTank = planet.FindNodeUnderPosition(movement.Position - planet.Position, out Triangle, out height, out normal);

              if (NodeUnderTank == null)
              {
            if (Globals.Game.Graphics.IsFullScreen)
              Globals.Game.Graphics.ToggleFullScreen();
            throw new Exception("Unable to find node under tank.");
              }
              else
              {
            Position3 p = movement.Position - planet.Position;
            p.Normalize();
            movement.Position = planet.Position + (p * height);
              }

               movement.OrientUp(normal);

              // now we need to roll the tank's wheels "forward." to do this, we'll
              // calculate how far they have rolled, and from there calculate how much
              // they must have rotated.
              float distanceMoved = (float)Position3.Distance(oldPosition, movement.fLocalPosition);
              float theta = distanceMoved / TankWheelRadius * 1000.0f;
              int rollDirection = 0;

              Vector3 n0 = movement.fLinearVelocity;
              n0.Normalize();

              Vector3 n1 = movement.fForward;

               if (Vector3.Dot(n0, n1) < 0)
             rollDirection = 1;
               else
             rollDirection = -1;

               wheelRollMatrix *= Matrix.CreateRotationX(theta * rollDirection);
        }