Example #1
0
 // constructor
 public Sphere(Position3 position, double radius, bool useNormalMap, CreatePositionDelegate createPosition, CreateTerrainNodeVertexBufferDelegate createTerrainNodeVertexBuffer, bool isSphere)
 {
     this.position = position;
       this.Radius = radius;
       this.useNormalMap = useNormalMap;
       this.createPosition = createPosition;
       this.createTerrainNodeVertexBuffer = createTerrainNodeVertexBuffer;
       this.isSphere = isSphere;
       Initialize();
 }
 public static double CreatePositionSphere(ref Position3 spherePosition, ref Position3 cubePosition, ref Vector2 patchPosition,
                                       double radius, out Position3 outPosition)
 {
     // the input position is a point on the surface of a unit sphere
       // by default we just want to move it out to the sphere radius
       // descendant classes will do more interesting things, like add some perlin noise
       // to it for terrain
       outPosition = spherePosition * radius;
       return 0;
 }
        public static double CreatePositionPlanet(ref Position3 spherePosition, ref Position3 cubePosition, ref Vector2 patchPosition,
                                              double radius, out Position3 outPosition)
        {
            Position3 p = cubePosition * 1.2;

              double h0 = Math.Abs(Noise.fBm(p.X, p.Y, p.Z, 3)) / 10.0;
              double h1 = Noise.Turbulence(p.X, p.Y, p.Z, 3, 2.0, 0.5);
              double h2 = Noise.HybridMultiFractal(p.X, p.Y, p.Z, 14, 1.854143, h0, 0.60);
              double h = h1 * h2;

              h *= 60;

              outPosition = spherePosition * (radius + h);
              return h;
        }
Example #4
0
        /// <summary>
        /// Determine if the node needs to be split based on camera distance and field of view
        /// </summary>
        /// <param name="cameraPosition">Planet-space camera position </param>
        /// <param name="fieldOfView">Camera's field of view</param>
        /// <returns>True if the terrain node needs to be split</returns>
        private bool NeedsSplit(Position3 planetPosition, Position3 cameraPosition, float fieldOfView)
        {
            // limit splitting
              if (isSphere && level >= Constants.MaxAtmosphereNodeLevel) return false;
              if (!isSphere && level >= Constants.MaxTerrainNodeLevel) return false;

              // get distance between camera and terrain node center - both are already in planet space
              float viewDistance = GetViewDistance(planetPosition, cameraPosition);

              // TODO : splitting not working properly when zooming in/out - seems to be the opposite of what's needed

              // calculate screen space error
              float k = 1024.0f * 0.5f * (float)Math.Tan(fieldOfView * 0.5f);
              float screenSpaceError = (geometricError / viewDistance) * k;

              // return true if the screen space error is greater than the max
              return (screenSpaceError > maxScreenSpaceError);
        }
Example #5
0
        /// <summary>
        /// Get distance from camera
        /// </summary>
        /// <param name="planetPosition">Position of planet center</param>
        /// <param name="cameraPosition">Camera position in planet space</param>
        /// <returns></returns>
        private float GetViewDistance(Position3 planetPosition, Position3 cameraPosition)
        {
            //return (float)Position3.Distance(this.Position, cameraPosition);

              // need to get the camera position in patch-space to compare the distance
              Vector3 v = (cameraPosition - this.Position).AsVector3;

              // translate to object space by adding patch position to planet position then subtracting from the camera position
              //Vector3 v = (cameraPosition - (planetPosition + this.position)).AsVector3;

              float minDistance = 999999999999;
              closestPosition = new Position3(vertexBuffer.Vertices[MapVertexIndex(Constants.PatchWidth / 2, Constants.PatchHeight / 2)].Position);

              // center center
              CheckDistance(Constants.PatchWidth / 2, Constants.PatchHeight / 2, ref v, ref minDistance);

              // bottom left
              CheckDistance(0, 0, ref v, ref minDistance);

              // bottom center
              CheckDistance(Constants.PatchWidth / 2, 0, ref v, ref minDistance);

              // bottom right
              CheckDistance(Constants.PatchWidth - 1, 0, ref v, ref minDistance);

              // top left
              CheckDistance(0, Constants.PatchHeight - 1, ref v, ref minDistance);

              // top center
              CheckDistance(Constants.PatchWidth / 2, Constants.PatchHeight - 1, ref v, ref minDistance);

              // top right
              CheckDistance(Constants.PatchWidth - 1, Constants.PatchHeight - 1, ref v, ref minDistance);

              // left center
              CheckDistance(0, Constants.PatchHeight / 2, ref v, ref minDistance);

              // right center
              CheckDistance(Constants.PatchWidth - 1, Constants.PatchHeight / 2, ref v, ref minDistance);

              // transform to planet-space
              closestPosition += this.Position;

              // return closest distance
              return (float)Math.Sqrt(minDistance);
        }
Example #6
0
 public void Subtract(ref Position3 V1, ref Position3 V2)
 {
     X = V1.X - V2.X;
       Y = V1.Y - V2.Y;
       Z = V1.Z - V2.Z;
 }
Example #7
0
 public void Update(Position3 cameraPosition, float fieldOfView)
 {
     // update nodes, allowing them to split if required
       front.Update(position, cameraPosition, fieldOfView);
       back.Update(position, cameraPosition, fieldOfView);
       left.Update(position, cameraPosition, fieldOfView);
       right.Update(position, cameraPosition, fieldOfView);
       top.Update(position, cameraPosition, fieldOfView);
       bottom.Update(position, cameraPosition, fieldOfView);
 }
Example #8
0
        /// <summary>
        /// Calculate angle from camera to horizon
        /// </summary>
        /// <param name="cameraPosition">Planet space camera position</param>
        /// <returns>Horizon angle in radians</returns>
        public float CalculateHorizonAngle(Position3 cameraPosition)
        {
            double result = MathHelper.ToRadians(300);

              double h = cameraPosition.Length();
              if (h > radius)
              {
            result = Math.Acos(radius / h);
            result += MathHelper.ToRadians(5); // add 5 degrees to account for mountains on the horizon

            // if we're fairly far away from the planet we need to account
            // for the very large patch size of the 6 faces that make up the planet
            h = h - radius - 9;
            if (h > 1000)
              result += MathHelper.ToRadians(50);
              }

              return (float)result;
        }
Example #9
0
 public void Clone(Movement movement)
 {
     Orientation = movement.Orientation;
       fLocalPosition = movement.fLocalPosition;
       UpdateMovement(0);
 }
Example #10
0
 /// <summary>
 /// Split this node's children
 /// </summary>
 /// <param name="cameraPosition">Planet-space camera position</param>
 /// <param name="fieldOfView">Camera's field of view</param>
 private void SplitChildren(Position3 planetPosition, Position3 cameraPosition, float fieldOfView)
 {
     if (HasChildren)
       {
     children[0].Split(planetPosition, cameraPosition, fieldOfView);
     children[1].Split(planetPosition, cameraPosition, fieldOfView);
     children[2].Split(planetPosition, cameraPosition, fieldOfView);
     children[3].Split(planetPosition, cameraPosition, fieldOfView);
       }
 }
Example #11
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;
        }
Example #12
0
        /// <summary>
        /// Generate terrain mesh for this node
        /// </summary>
        public void GenerateMesh(TerrainNodeSplitItem item)
        {
            // the minus one here is correct: e.g. 3x3 vertices labeled 0, 1, 2: v0.x = 0, v1.x = 0.5, v2.x = 1.  The increment = 1 / (3 - 1) = 0.5
              double horizontalStep = bounds.Width / (Constants.PatchWidth - 1);
              double verticalStep = bounds.Height / (Constants.PatchHeight - 1);
              float horizontalTextureStep = 1.0f / (Constants.PatchWidth - 1);
              float verticalTextureStep = 1.0f / (Constants.PatchHeight - 1);

              float MinX, MinY, MinZ;
              float MaxX, MaxY, MaxZ;

              // initialize min and max vertex tracking
              MinX = MinY = MinZ = 999999;
              MaxX = MaxY = MaxZ = -999999;

              // get matrix used to transform vertices to the proper cube face
              Matrix faceMatrix = CubeFaces.GetFace(bounds.Face).FaceMatrix;

              // create vertex storage using user supplied delegate
              vertexBuffer = createTerrainNodeVertexBuffer(item.HeightData.Length);

              //int cubeVertexIndex = 0;
              //CubeVertices = new Vector2[item.HeightData.Length];

              hasMeshBorder = false;
              int vertexIndex = 0;
              int Rows = Constants.PatchHeight;
              int Columns = Constants.PatchWidth;

              if (item.HeightData.Length > Constants.PatchWidth * Constants.PatchHeight)
              {
            hasMeshBorder = true;
            Rows += 2;
            Columns += 2;
              }

              patchRows = Rows;
              patchColumns = Columns;

              float v = 0;
              double y = bounds.Bottom;

              if (hasMeshBorder)
              {
            v -= verticalTextureStep;
            y -= verticalStep;
              }

              for (int hy = 0; hy < Rows; hy++)
              {
            float u = 0;
            double x = bounds.Left;

            if (hasMeshBorder)
            {
              u -= horizontalTextureStep;
              x -= horizontalStep;
            }

            for (int hx = 0; hx < Columns; hx++)
            {
              // create the vertex position and rotate it to the appropriate face
              Position3 cubePosition = new Position3(x, y, 1);

              Position3 spherePosition = Tools.CubeToSphereMapping(x, y, 1);
              spherePosition.Transform(ref faceMatrix);
              cubePosition.Transform(ref faceMatrix);

              // transform the vertex based on the user defined delegate
              double height;
              Position3 finalPosition;
              Vector2 patchPosition = new Vector2(hx, hy);

              if (item == null)
            CreatePosition(ref spherePosition, ref cubePosition, ref patchPosition, out finalPosition, out height);
              else
              {
            height = item.HeightData[hy * Columns + hx];
            if (height < 0) height = 0;
            finalPosition = spherePosition * (radius + height);
            TranslateToPatchSpace(ref finalPosition);
              }

              VertexPositionNormalTextureHeight vertex = new VertexPositionNormalTextureHeight();

              vertex.Position = (Vector3)finalPosition;
              vertex.Height = (float)height;
              vertex.Normal = (Vector3)spherePosition;
              vertex.TextureCoordinate = new Vector2(u, v);
              vertex.Tangent = Vector4.Zero;
              vertexBuffer.Vertices[vertexIndex++] = vertex;

              // track min and max coordinates, but only  for the vertices that will be in the final mesh
              if (hx >= 1 && hx < Columns - 1 && hy >= 1 && hy < Rows - 1)
              {
            if (vertex.Position.X < MinX) MinX = vertex.Position.X;
            if (vertex.Position.Y < MinY) MinY = vertex.Position.Y;
            if (vertex.Position.Z < MinZ) MinZ = vertex.Position.Z;

            if (vertex.Position.X > MaxX) MaxX = vertex.Position.X;
            if (vertex.Position.Y > MaxY) MaxY = vertex.Position.Y;
            if (vertex.Position.Z > MaxZ) MaxZ = vertex.Position.Z;
              }

              x += horizontalStep;
              u += horizontalTextureStep;
            }

            y += verticalStep;
            v += verticalTextureStep;
              }

              // create min and max bounding vertices, in patch-space
              minVertex = new Vector3(MinX, MinY, MinZ);
              maxVertex = new Vector3(MaxX, MaxY, MaxZ);

              // calculate normals and tangents
              CalculateNormals();
              CalculateTangents();

              // save vertex buffer changes - this effectively copies the raw data to a vertex buffer on the device
              vertexBuffer.CommitChanges(Constants.PatchWidth, Constants.PatchHeight);
        }
Example #13
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.");
        }
Example #14
0
 public Position3(Position3 V)
 {
     X = V.X;
       Y = V.Y;
       Z = V.Z;
 }
Example #15
0
        public void SubtractNormalize(ref Position3 V1, ref Vector3 V2)
        {
            X = V1.X - V2.X;
              Y = V1.Y - V2.Y;
              Z = V1.Z - V2.Z;

              double L = 1 / Math.Sqrt(X * X + Y * Y + Z * Z);
              X *= L;
              Y *= L;
              Z *= L;
        }
Example #16
0
 public void SubtractFrom(ref Position3 V1)
 {
     X = V1.X - X;
       Y = V1.Y - Y;
       Z = V1.Z - Z;
 }
Example #17
0
 public void Subtract(ref Position3 V1)
 {
     X -= V1.X;
       Y -= V1.Y;
       Z -= V1.Z;
 }
Example #18
0
        /// <summary>
        /// Split or unsplit nodes and child nodes as required
        /// </summary>
        /// <param name="cameraPosition">Planet-space camera position</param>
        /// <param name="fieldOfView">Camera's field of view</param>
        private void Split(Position3 planetPosition, Position3 cameraPosition, float fieldOfView)
        {
            // if we're already splitting then we don't want to do any other split processing until the thread is complete
              // this node will continue to be the leaf node in this branch so it will continue to draw until the
              // splitting is completed
              if (Splitting)
              {
            // if we no longer need to split, but we're still queued up for splitting then cancel it - the thread
            // will see this when it gets to the the node in the queue and won't do anything
            if (!NeedsSplit(planetPosition, cameraPosition, fieldOfView))
              CancelSplitting = true;

            return;
              }

              // if this node needs to be split then check its children or queue up a split
              if (NeedsSplit(planetPosition, cameraPosition, fieldOfView))
              {
            // if it already has children then we've already split, so recurse through the children
            if (HasChildren)
            {
              SplitChildren(planetPosition, cameraPosition, fieldOfView);
            }

            // otherwise we need to be split and have no children, so queue up the child node to the node splitter queue thread
            else
            {
              // setting this will cause drawing code to pretend this is a leaf node until the split is complete
              // it will also become non-splittable during this time
              CancelSplitting = false;
              Splitting = true;

              QueueNodeGeneration();
            }
              }

              // if we don't need to be split then we can remove child nodes
              else
              {
            // if our children are all leaf nodes then we no longer need them, so get rid of them and this node is now a leaf node
            if (ChildrenAreLeafNodes())
              ClearChildren();

            // if we do have non-leaf children then recurse down until we find a node whose children are leaves, and remove those children
            // the lower level children will continue to be drawn until they've been cleared out, at only 1 level per frame
            if (HasChildren)
              SplitChildren(planetPosition, cameraPosition, fieldOfView);
              }
        }
Example #19
0
 /// <summary>
 /// Split all the way down to leaf nodes before generating the actual terrain.
 /// The deepest node with data will still be displayed until all the leaf nodes
 /// are ready.
 /// </summary>
 /// <param name="planetPosition"></param>
 /// <param name="cameraPosition"></param>
 /// <param name="fieldOfView"></param>
 private void Split2(Position3 planetPosition, Position3 cameraPosition, float fieldOfView)
 {
 }
Example #20
0
 /// <summary>
 /// Translate sphere-space position to patch-space
 /// </summary>
 /// <param name="position">Sphere-space position</param>
 public void TranslateToPatchSpace(ref Position3 position)
 {
     position.Subtract(ref this.position);
 }
Example #21
0
        public void UpdateMovement(float elapsed)
        {
            fRotationalVelocity += (fRotationalAcceleration * elapsed);

              fRotationTime += elapsed;
              while (fRotationTime >= (1.0f / 60.0f))
              {
            fRotationalVelocity *= fRotationalDrag;
            fRotationTime -= (1.0f / 60.0f);
            fRotationalAcceleration = Vector3.Zero;
              }

              float Yaw = MathHelper.ToRadians(fRotationalVelocity.Y * elapsed);
              float Pitch = MathHelper.ToRadians(fRotationalVelocity.X * elapsed);
              float Roll = MathHelper.ToRadians(fRotationalVelocity.Z * elapsed);

              // create a rotation quaternion based on orientation changes - this is the amount to rotate
              Quaternion Rotation = Quaternion.CreateFromYawPitchRoll(Yaw, Pitch, Roll);

              // add the rotation to the current rotation quaternion
              fOrientation *= Rotation;

              UpdateOrientation();

              // apply linear acceleration to velocity
              fLinearVelocity += fLinearAcceleration * elapsed;

              fLinearTime += elapsed;
              while (fLinearTime >= (1.0f / 60.0f))
              {
            fLinearVelocity *= fLinearDrag;
            fLinearTime -= (1.0f / 60.0f);
            fLinearAcceleration = Vector3.Zero;
              }

              fLocalPosition.Add(fLinearVelocity);
              Position = fLocalPosition + AttachedPosition;

              // update matrices
              UpdateWorldMatrix();
        }
Example #22
0
 public void Update(Position3 planetPosition, Position3 cameraPosition, float fieldOfView)
 {
     Split(planetPosition, cameraPosition, fieldOfView);
 }
Example #23
0
 public void LookAt(Position3 Target)
 {
     Target -= Position;
       SetWorldMatrix(Matrix.CreateLookAt(Vector3.Zero, (Vector3)Target, (Vector3)fUp));
 }
Example #24
0
        /// <summary>
        /// Calculate the sphere-space position of the patch by determining where the center vertex lies on the sphere
        /// </summary>
        private void CalculatePatchPosition(TerrainNodeSplitItem item)
        {
            // find the cube position of the center vertex
              double x = bounds.Left + bounds.Width / 2;
              double y = bounds.Bottom + bounds.Height / 2;

              // get the matrix used to rotate the a position to the appropriate cube face
              Matrix faceMatrix = CubeFaces.GetFace(bounds.Face).FaceMatrix;

              // create the vertex position in cube-space and rotate it to the appropriate face
              Position3 cubePosition = new Position3(x, y, 1);
              cubePosition.Transform(ref faceMatrix);

              // get the vertex position on the unit sphere and rotate it to the appropriate face
              Position3 spherePosition = Tools.CubeToSphereMapping(x, y, 1);
              spherePosition.Transform(ref faceMatrix);
              spherePosition.Normalize();

              Vector2 patchPosition = new Vector2(Constants.PatchWidth / 2, Constants.PatchHeight / 2);

              if (item == null)
              {
            // transform the vertex based on the user defined delegate - this returns the height value of the point on the sphere
            createPosition(ref spherePosition, ref cubePosition, ref patchPosition, radius, out position);
              }
              else
              {
            double h = item.HeightData[(int)((patchPosition.Y + 1) * (Constants.PatchWidth + 2) + (patchPosition.X + 1))];
            if (h < 0) h = 0;
            position = spherePosition * (radius + h);
              }
        }
Example #25
0
        public TerrainNode FindNodeUnderPosition(Position3 position, out Vector3[] triangle, out double height, out Vector3 normal)
        {
            TerrainNode result = null;

              result = front.FindNodeUnderPosition(position, out triangle, out height, out normal);

              if (result == null)
            result = back.FindNodeUnderPosition(position, out triangle, out height, out normal);

              if (result == null)
            result = left.FindNodeUnderPosition(position, out triangle, out height, out normal);

              if (result == null)
            result = right.FindNodeUnderPosition(position, out triangle, out height, out normal);

              if (result == null)
            result = top.FindNodeUnderPosition(position, out triangle, out height, out normal);

              if (result == null)
            result = bottom.FindNodeUnderPosition(position, out triangle, out height, out normal);

              return result;
        }
Example #26
0
        public void AddNormalize(ref Position3 V1, ref Vector3 V2)
        {
            X = V1.X + V2.X;
              Y = V1.Y + V2.Y;
              Z = V1.Z + V2.Z;

              double L = 1 / Math.Sqrt(X * X + Y * Y + Z * Z);
              X *= L;
              Y *= L;
              Z *= L;
        }
Example #27
0
        private void CheckDistance(int x, int y, ref Vector3 v, ref float minDistance)
        {
            VertexPositionNormalTextureHeight p = vertexBuffer.Vertices[y * patchColumns + x]; // MapVertexIndex(x, y)];

              float d = Vector3.DistanceSquared(p.Position, v);

              if (d < minDistance)
              {
            minDistance = d;
            closestPosition = new Position3(p.Position);
              }
        }
Example #28
0
        public bool Equals(Position3 P)
        {
            // if (P == null) return false;

              return (X == P.X &&
              Y == P.Y &&
              Z == P.Z);
        }
Example #29
0
 /// <summary>
 /// Create a patch-space position by using the user supplied delegate.
 /// </summary>
 /// <param name="inPosition">Input position, located on the surface of a unit sphere</param>
 /// <param name="outPosition">Output position, moved out to the sphere surface, or altered with noise, as determined by the user supplied delegate</param>
 private void CreatePosition(ref Position3 spherePosition, ref Position3 cubePosition, ref Vector2 patchPosition, out Position3 outPosition, out double height)
 {
     height = createPosition(ref spherePosition, ref cubePosition, ref patchPosition, radius, out outPosition);
       TranslateToPatchSpace(ref outPosition);
 }
Example #30
0
 public void Add(ref Position3 V1, ref Position3 V2)
 {
     X = V1.X + V2.X;
       Y = V1.Y + V2.Y;
       Z = V1.Z + V2.Z;
 }