コード例 #1
0
        // face space method, using ray intersection in planet space
        public TerrainNode FindNodeUnderPosition(Position3 position, out Vector3[] triangle, out double height, out Vector3 normal)
        {
            triangle = null;
              height = 0;
              normal = Vector3.Zero;

              Position3 originalPosition = position;

              // normalize the position so it points out from the planet center towards the actual position
              position.Normalize();

              // get the direction vector
              Vector3 direction = position.AsVector3;

              // get a position 1km under the planet surface
              position *= radius - 1;

              // get ray from position to planet center, translate to patch space
              Ray ray = new Ray((position - this.Position).AsVector3, direction);

              Vector3 p1 = MinVertex;
              Vector3 p2 = MaxVertex;

              // first do a bounding box/ray intersection test
              BoundingBox box = new BoundingBox(MinVertex, MaxVertex);

              // if the ray doesn't intersect the bounding box then it can't intersect terrain node
              if (ray.Intersects(box) == null) return null;

              // we have a potential match - do mesh collision to be sure
              Vector3[] t = this.GetHeightAndNormal(originalPosition, out height, out normal);

              // if no mesh collision then we're done
              if (t == null) return null;

              // if the position is over this node and this is a leaf node then we have what we want
              if (!HasChildren)
              {
            triangle = t;
            return this;
              }

              // otherwise we want to recurse into the children to find the leaf node
              for (int i = 0; i < children.Length; i++)
              {
            TerrainNode node = children[i].FindNodeUnderPosition(position, out triangle, out height, out normal);
            if (node != null) return node;
              }

              // if we get here then we have a problem - the position is allegedly above this node, which means
              // it should also be above one of this node's children, but we didn't find a child
              // return this;

              if (Globals.Game.Graphics.IsFullScreen)
            Globals.Game.Graphics.ToggleFullScreen();
              throw new Exception("Unable to find leaf node.");
        }
コード例 #2
0
        public Vector3[] GetHeightAndNormal(Position3 position, out double height, out Vector3 normal)
        {
            // we know position is over this node, now we need to find which triangle within the node

              // normalize the position so it points out from the planet center towards the actual position
              position.Normalize();

              // get the direction vector
              Position3 direction3 = position;
              Vector3 direction = position.AsVector3;

              // get a position 1km under the planet surface, in planet space
              position *= radius - 1;

              // translate to patch space
              position -= this.Position;

              // get ray from position to planet center, translate to patch space
              Ray ray = new Ray(position.AsVector3, direction);
              float? intersection = null;
              float u = 0;
              float v = 0;

              Vector3 v0 = Vector3.Zero;
              Vector3 v1 = Vector3.Zero;
              Vector3 v2 = Vector3.Zero;
              Vector3 v4 = Vector3.Zero;

              Vector3 n0 = Vector3.Zero;
              Vector3 n1 = Vector3.Zero;
              Vector3 n2 = Vector3.Zero;
              Vector3 n4 = Vector3.Zero;

              int triangleIndex = 0;
              int quadIndex = 0;
              int index;
              int y;
              int x;

              // now we need to loop through each triangle and see if the ray intersects
              for (int i = 0; i < TerrainNodeIndexBuffer.IndexCount; i += 3)
              {
            index = TerrainNodeIndexBuffer.IndexData[i];
            y = index / Constants.PatchHeight;
            x = index % Constants.PatchWidth;
            index = (y + 1) * patchColumns + (x + 1);
            v0 = vertexBuffer.Vertices[index].Position;
            n0 = vertexBuffer.Vertices[index].Normal;

            index = TerrainNodeIndexBuffer.IndexData[i + 1];
            y = index / Constants.PatchHeight;
            x = index % Constants.PatchWidth;
            index = (y + 1) * patchColumns + (x + 1);
            v1 = vertexBuffer.Vertices[index].Position;
            n1 = vertexBuffer.Vertices[index].Normal;

            index = TerrainNodeIndexBuffer.IndexData[i + 2];
            y = index / Constants.PatchHeight;
            x = index % Constants.PatchWidth;
            index = (y + 1) * patchColumns + (x + 1);
            v2 = vertexBuffer.Vertices[index].Position;
            n2 = vertexBuffer.Vertices[index].Normal;

            Tools.RayIntersectsTriangle(ref ray, ref v0, ref v1, ref v2, out intersection, out u, out v);

            if (intersection != null)
            {
              triangleIndex = i;
              quadIndex = i;
              if (quadIndex % 6 != 0)
            quadIndex -= 3;
              break;
            }
              }

              Globals.TriangleIndex = triangleIndex;

              if (intersection == null)
              {
            height = radius;
            normal = direction;
            return null;
              }

              // Now that we've calculated the indices of the corners of our cell, and
              // where we are in that cell, we'll use bilinear interpolation to calculuate
              // our height. This process is best explained with a diagram, so please see
              // the accompanying doc for more information.
              // First, calculate the heights on the bottom and top edge of our cell by
              // interpolating from the left and right sides.

              // get the vertices for the quad containing this triangle

              index = TerrainNodeIndexBuffer.IndexData[quadIndex + 0];
              y = index / Constants.PatchHeight;
              x = index % Constants.PatchWidth;
              index = (y + 1) * patchColumns + (x + 1);
              v0 = vertexBuffer.Vertices[index].Position;
              n0 = vertexBuffer.Vertices[index].Normal;

              index = TerrainNodeIndexBuffer.IndexData[quadIndex + 1];
              y = index / Constants.PatchHeight;
              x = index % Constants.PatchWidth;
              index = (y + 1) * patchColumns + (x + 1);
              v1 = vertexBuffer.Vertices[index].Position;
              n1 = vertexBuffer.Vertices[index].Normal;

              index = TerrainNodeIndexBuffer.IndexData[quadIndex + 2];
              y = index / Constants.PatchHeight;
              x = index % Constants.PatchWidth;
              index = (y + 1) * patchColumns + (x + 1);
              v2 = vertexBuffer.Vertices[index].Position;
              n2 = vertexBuffer.Vertices[index].Normal;

              index = TerrainNodeIndexBuffer.IndexData[quadIndex + 4];
              y = index / Constants.PatchHeight;
              x = index % Constants.PatchWidth;
              index = (y + 1) * patchColumns + (x + 1);
              v4 = vertexBuffer.Vertices[index].Position;
              n4 = vertexBuffer.Vertices[index].Normal;

              /*
              Vector3 top, bottom, p, topNormal, bottomNormal, n;

              if (triangleIndex % 6 == 0)
              {
            // we're in triangle A - the top left triangle
            top = Vector3.Lerp(v0, v1, u);
            bottom = Vector3.Lerp(v2, v4, u);
            p = Vector3.Lerp(top, bottom, v);
            topNormal = Vector3.Lerp(n0, n1, u);
            bottomNormal = Vector3.Lerp(n2, n4, u);
            n = Vector3.Lerp(topNormal, bottomNormal, v);
            n.Normalize();
              }
              else
              {
            // we're in triangle B - the bottom right triangle
            // this means u and v are positions within *that* triangle, so we need to do our lerping differently
            // we're in triangle A - the top left triangle

            // TODO : except u and v are acting very odd!  they don't seem to be correct
            // let's try getting the quad all at once, then doing the Ray check on each triangle in the quad

            top = Vector3.Lerp(v0, v1, u);
            bottom = Vector3.Lerp(v2, v4, u);
            p = Vector3.Lerp(top, bottom, v);
            topNormal = Vector3.Lerp(n0, n1, u);
            bottomNormal = Vector3.Lerp(n2, n4, u);
            n = Vector3.Lerp(topNormal, bottomNormal, v);
            n.Normalize();
              }

              */

              // intersection gives us the length on the ray of the exact intersection position,
              // which gives us the exact height value to use
              Position3 vp = this.Position + (position + (direction3 * (double)intersection));
              height = vp.Length();

              // but now, how do we get the normal from that?  let's start with just averaging the normals
              normal = (n0 + n1 + n2 + n4) * 0.25f;

              Vector3[] result = new Vector3[5];
              result[0] = v0;
              result[1] = v1;
              result[2] = v2;
              result[3] = v4;
              result[4] = (vp - this.Position).AsVector3;

              return result;
        }
コード例 #3
0
ファイル: PlanetGame.cs プロジェクト: TrinityGaming/Planet_40
    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


    }