public TerrainNodeSplitItem(TerrainNode parentNode, int childIndex, TerrainNodeBounds bounds, bool isSphere)
 {
     ParentNode = parentNode;
       ChildIndex = childIndex;
       Bounds = bounds;
       IsSphere = isSphere;
 }
Esempio n. 2
0
 public void Initialize()
 {
     front = CreateRootTerrainNode(Face.Front);
       back = CreateRootTerrainNode(Face.Back);
       left = CreateRootTerrainNode(Face.Left);
       right = CreateRootTerrainNode(Face.Right);
       top = CreateRootTerrainNode(Face.Top);
       bottom = CreateRootTerrainNode(Face.Bottom);
 }
Esempio 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);
      }
    }
Esempio n. 4
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);
      }
    }
Esempio n. 5
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;
    }
Esempio n. 6
0
    private void CountTerrainNodes(TerrainNode node)
    {
      Globals.NodeCount++;

      if (node.HasChildren)
      {
        if (node.Children[0] != null) CountTerrainNodes(node.Children[0]);
        if (node.Children[1] != null) CountTerrainNodes(node.Children[1]);
        if (node.Children[2] != null) CountTerrainNodes(node.Children[2]);
        if (node.Children[3] != null) CountTerrainNodes(node.Children[3]);
      }
    }
Esempio n. 7
0
    private void DrawNodeFrustum(TerrainNode node)
    {

      // calculate the width of the patch; first we need a vertex on both sides of the patch, in planet space
      Vector3 p1 = node.Position.AsVector3 + node.VertexBuffer.Vertices[1 * 33 + 1].Position;
      Vector3 p2 = node.Position.AsVector3 + node.VertexBuffer.Vertices[1 * 33 + 33].Position;

      // need to move them to the sphere radius
      p1.Normalize();
      p1 *= (float)sphere.Radius;

      p2.Normalize();
      p2 *= (float)sphere.Radius;

      // now we can calculate the opposite and hypotenuse lengths
      float opposite = Vector3.Distance(p1, p2) * 0.5f;    // width is distance between p1 and p2, and we need just half of it
      float hypotenuse = (float)sphere.Radius;

      // once we have the width we can calculate the field of view
      float fieldOfView = (float)(2.0 * Math.Asin(opposite / hypotenuse));

      // now we can create the view and projection matrixes
      Matrix view = Matrix.CreateLookAt(Vector3.Zero, node.Position.AsVector3, Vector3.Up);
      Matrix projection = Matrix.CreatePerspectiveFieldOfView(fieldOfView, 1.0f, 1.0f, 9000.0f);

      // which then lets us create the bounding frustum
      BoundingFrustum frustum = new BoundingFrustum(view * projection);

      Vector3[] corners = frustum.GetCorners();

      // draw lines between corners

      VertexPositionColor[] vertices = new VertexPositionColor[24];

      Position3 p = Position3.Zero;

      Position3 p0 = node.Position;
      p0.Normalize();
      p0 *= 9000.0f;


      // line 1
      vertices[0] = new VertexPositionColor(corners[0], Color.White);
      vertices[1] = new VertexPositionColor(corners[1], Color.White);

      // line 2
      vertices[2] = new VertexPositionColor(corners[1], Color.White);
      vertices[3] = new VertexPositionColor(corners[2], Color.White);

      // line 3
      vertices[4] = new VertexPositionColor(corners[2], Color.White);
      vertices[5] = new VertexPositionColor(corners[3], Color.White);

      // line 4
      vertices[6] = new VertexPositionColor(corners[3], Color.White);
      vertices[7] = new VertexPositionColor(corners[0], Color.White);


      // line 5
      vertices[8] = new VertexPositionColor(corners[4], Color.White);
      vertices[9] = new VertexPositionColor(corners[5], Color.White);

      // line 6
      vertices[10] = new VertexPositionColor(corners[5], Color.White);
      vertices[11] = new VertexPositionColor(corners[6], Color.White);

      // line 7
      vertices[12] = new VertexPositionColor(corners[6], Color.White);
      vertices[13] = new VertexPositionColor(corners[7], Color.White);

      // line 8
      vertices[14] = new VertexPositionColor(corners[7], Color.White);
      vertices[15] = new VertexPositionColor(corners[4], Color.White);


      // line 9
      vertices[16] = new VertexPositionColor(corners[0], Color.White);
      vertices[17] = new VertexPositionColor(corners[4], Color.White);

      // line 10
      vertices[18] = new VertexPositionColor(corners[1], Color.White);
      vertices[19] = new VertexPositionColor(corners[5], Color.White);

      // line 11
      vertices[20] = new VertexPositionColor(corners[2], Color.White);
      vertices[21] = new VertexPositionColor(corners[6], Color.White);

      // line 12
      vertices[22] = new VertexPositionColor(corners[3], Color.White);
      vertices[23] = new VertexPositionColor(corners[7], Color.White);



      GraphicsDevice device = graphics.GraphicsDevice;
      // TODO : device.RenderState.CullMode = CullMode.None;


      // get world space position for drawing the frustum
      Position3 worldSpacePosition = sphere.Position;

      // translate to camera space by subtracting the camera position, scale by planet scale
      Position3 cameraSpacePosition = (worldSpacePosition - mainCamera.Position) * sphere.Scale;

      // create world matrix
      Matrix cameraSpaceMatrix = sphere.ScaleMatrix * Matrix.CreateTranslation(cameraSpacePosition.AsVector3);


      testEffect.Projection = mainCamera.ProjectionMatrix;
      testEffect.World = cameraSpaceMatrix;
      testEffect.View = mainCamera.ViewMatrix;
      //testEffect.EnableDefaultLighting();
      testEffect.VertexColorEnabled = true;


      testEffect.CurrentTechnique.Passes[0].Apply();
      GraphicsDevice.DrawUserPrimitives(PrimitiveType.LineList, vertices, 0, 12);
    }
Esempio n. 8
0
    private void DrawNodeBoundingBox(TerrainNode node)
    {
      // calculate the width of the patch; first we need a vertex on both sides of the patch, in planet space
      Vector3 p1 = node.Position.AsVector3 + node.MinVertex;
      Vector3 p2 = node.Position.AsVector3 + node.MaxVertex;


      // which then lets us create the bounding frustum
      BoundingBox box = new BoundingBox(p1, p2);

      Vector3[] corners = box.GetCorners();

      // draw lines between corners
      VertexPositionColor[] vertices = new VertexPositionColor[24];


      // line 1
      vertices[0] = new VertexPositionColor(corners[0], Color.White);
      vertices[1] = new VertexPositionColor(corners[1], Color.White);

      // line 2
      vertices[2] = new VertexPositionColor(corners[1], Color.White);
      vertices[3] = new VertexPositionColor(corners[2], Color.White);

      // line 3
      vertices[4] = new VertexPositionColor(corners[2], Color.White);
      vertices[5] = new VertexPositionColor(corners[3], Color.White);

      // line 4
      vertices[6] = new VertexPositionColor(corners[3], Color.White);
      vertices[7] = new VertexPositionColor(corners[0], Color.White);


      // line 5
      vertices[8] = new VertexPositionColor(corners[4], Color.White);
      vertices[9] = new VertexPositionColor(corners[5], Color.White);

      // line 6
      vertices[10] = new VertexPositionColor(corners[5], Color.White);
      vertices[11] = new VertexPositionColor(corners[6], Color.White);

      // line 7
      vertices[12] = new VertexPositionColor(corners[6], Color.White);
      vertices[13] = new VertexPositionColor(corners[7], Color.White);

      // line 8
      vertices[14] = new VertexPositionColor(corners[7], Color.White);
      vertices[15] = new VertexPositionColor(corners[4], Color.White);


      // line 9
      vertices[16] = new VertexPositionColor(corners[0], Color.White);
      vertices[17] = new VertexPositionColor(corners[4], Color.White);

      // line 10
      vertices[18] = new VertexPositionColor(corners[1], Color.White);
      vertices[19] = new VertexPositionColor(corners[5], Color.White);

      // line 11
      vertices[20] = new VertexPositionColor(corners[2], Color.White);
      vertices[21] = new VertexPositionColor(corners[6], Color.White);

      // line 12
      vertices[22] = new VertexPositionColor(corners[3], Color.White);
      vertices[23] = new VertexPositionColor(corners[7], Color.White);



      GraphicsDevice device = graphics.GraphicsDevice;
      device.RasterizerState = RasterizerState.CullNone;

      //device.VertexDeclaration = positionColor;


      // get world space position for drawing the frustum
      Position3 worldSpacePosition = sphere.Position;

      // translate to camera space by subtracting the camera position, scale by planet scale
      Position3 cameraSpacePosition = (worldSpacePosition - mainCamera.Position) * sphere.Scale;

      // create world matrix
      Matrix cameraSpaceMatrix = sphere.ScaleMatrix * Matrix.CreateTranslation(cameraSpacePosition.AsVector3);


      testEffect.Projection = mainCamera.ProjectionMatrix;
      testEffect.World = cameraSpaceMatrix;
      testEffect.View = mainCamera.ViewMatrix;
      //testEffect.EnableDefaultLighting();
      testEffect.VertexColorEnabled = true;

      testEffect.CurrentTechnique.Passes[0].Apply();
      GraphicsDevice.DrawUserPrimitives(PrimitiveType.LineList, vertices, 0, 12);

    }
Esempio n. 9
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);
        }
 public static void QueueNodeSplit(TerrainNode parentNode, int childIndex, TerrainNodeBounds bounds, bool isSphere)
 {
     QueueNodeSplit(new TerrainNodeSplitItem(parentNode, childIndex, bounds, isSphere));
 }