private void CalculateTextureWeights() { lowMark = 15 * scale.Y; highMark = 180 * scale.Y; for (int i = 0; i < vertices.Length; i++) { float height = vertices[i].Position.Y; double normalAngle = GMath.AngleOfIncline(vertices[i].Normal); Vector4 weights = Vector4.Zero; // start all weights at 0 if (height < lowMark) // height is in the lower third { weights.Y = height / lowMark; // percent weight 2 weights.X = 1 - weights.Y; // percent weight 1 } else if (height < highMark) // height is in the middle third { weights.Z = (height - lowMark) / (highMark - lowMark); // percent weight 3 weights.Y = 1 - weights.Z; // percent weight 2 } else // height is in the top third { weights.W = (height - highMark) / (255 - highMark) * (float)(90 - normalAngle) / 90.0f; // percent weight 4 weights.Z = 1 - weights.W; // percent weight 3 } // surfaces which have steep surfaces should be rocky if (normalAngle < 50) { float rockyness = MathHelper.Clamp((float)(90 - normalAngle) / 90.0f, 0, 1); weights *= 1 - rockyness; weights.W += rockyness; } // surfaces which have shallow angles mix in some of the third texture if (normalAngle > 75 && vertices[i].Position.Y > lowMark) { weights *= 0.4f; weights.Z += 0.6f; } vertices[i].TextureWeights = weights; } }
/// <summary> /// Creates and connects all nodes in the grid /// </summary> private void BuildGrid(Sim.Environment.Terrain terrain) { // create the nodes at their proper locations nodes = new Node[width * length]; for (int z = 0; z < length; z++) { for (int x = 0; x < width; x++) { int i = x + z * width; float y = terrain.CalculateHeight(x * spacing, z * spacing); nodes[i] = new Node(new Vector3(x * spacing, y, z * spacing)); if (y < 5) // underwater { nodes[i].State = NodeState.Invalid; } else if (GMath.AngleOfIncline(terrain.CalculateSurfaceNormal(x * spacing, z * spacing)) < 50) { nodes[i].State = NodeState.Invalid; } } } // connect adjacent nodes for (int z = 0; z < length; z++) { for (int x = 0; x < width; x++) { Node n = nodes[x + z * width]; // adjacent nodes exist in all 8 directions if the current node is part of the // interior of the grid; if the node is on an edge, certain spots are empty bool addN = z > 0; bool addS = z < length - 1; bool addW = x > 0; bool addE = x < width - 1; if (addN) { n.AdjacentNodes.Add(nodes[x + (z - 1) * width]); // N if (addE) { n.AdjacentNodes.Add(nodes[(x + 1) + (z - 1) * width]); // NE } if (addW) { n.AdjacentNodes.Add(nodes[(x - 1) + (z - 1) * width]); // NW } } if (addS) { n.AdjacentNodes.Add(nodes[x + (z + 1) * width]); // S if (addE) { n.AdjacentNodes.Add(nodes[(x + 1) + (z + 1) * width]); // SE } if (addW) { n.AdjacentNodes.Add(nodes[(x - 1) + (z + 1) * width]); // SW } } if (addE) { n.AdjacentNodes.Add(nodes[(x + 1) + z * width]); // E } if (addW) { n.AdjacentNodes.Add(nodes[(x - 1) + z * width]); // W } } } }