public QuadTreeNode(GraphicsDevice graphicsDevice, HeightProvider heightProvider, NodeType nodeType, QuadTreeNode parentNode, float edgeLengthFlat, Vector3Double originPositionFlat, Vector3 upDirectionFlat, Vector3 rightDirectionFlat, float radiusSphere) { _graphicsDevice = graphicsDevice; _heightProvider = heightProvider; _nodeType = nodeType; _parentNode = parentNode; _edgeLengthFlat = edgeLengthFlat; _halfEdgeLengthFlat = _edgeLengthFlat / 2; _quarterEdgeLengthFlat = _edgeLengthFlat / 4; _originPositionFlat = originPositionFlat; _upDirectionFlat = upDirectionFlat; _rightDirectionFlat = rightDirectionFlat; _radiusSphere = radiusSphere; Vector3 originPositionSphereNormal = Vector3Double.Normalize(_originPositionFlat); Vector3Double originPositionSpherePosition = new Vector3Double(_radiusSphere * originPositionSphereNormal); OriginPositionSphere = originPositionSpherePosition + _heightProvider.GetHeight(originPositionSpherePosition) * originPositionSphereNormal; IndexBuffer = _indexBuffers[IndexBufferSelection.Base]; }
private void CalculateContents() { float vertexSpacingFlat = _edgeLengthFlat / (VerticesPerEdge - 1); Vector3 min = new Vector3(float.MaxValue, float.MaxValue, float.MaxValue); Vector3 max = new Vector3(float.MinValue, float.MinValue, float.MinValue); // We're adding a border of 1 extra vertex for smooth normal calculations List <TerrainVertexInterstitial> interstitialVertices = new List <TerrainVertexInterstitial>(); for (int y = -1; y < VerticesPerEdge + 1; y++) { for (int x = -1; x < VerticesPerEdge + 1; x++) { Vector3Double positionWorldFlat = _originPositionFlat + (x * vertexSpacingFlat - _halfEdgeLengthFlat) * _rightDirectionFlat + (y * vertexSpacingFlat - _halfEdgeLengthFlat) * _upDirectionFlat; Vector3 positionWorldSphereNormal = Vector3Double.Normalize(positionWorldFlat); Vector3Double positionWorldSpherePosition = new Vector3Double(_radiusSphere * positionWorldSphereNormal); float positionWorldSphereHeight = _heightProvider.GetHeight(positionWorldSpherePosition); Vector3Double positionWorldSphere = positionWorldSpherePosition + positionWorldSphereHeight * positionWorldSphereNormal; Vector3 position = (positionWorldSphere - OriginPositionSphere).ToVector3(); bool includeInMesh = y > -1 && y <VerticesPerEdge && x> -1 && x < VerticesPerEdge; TerrainVertexInterstitial vertex = new TerrainVertexInterstitial(position, includeInMesh); if (includeInMesh) { float baseColourValue = Globals.CosineInterpolate(0.7f, 0.9f, (positionWorldSphereHeight - 50) / (500 - 50)); vertex.BaseColour = new Color(baseColourValue, baseColourValue, baseColourValue); min = Vector3.Min(min, vertex.Position); max = Vector3.Max(max, vertex.Position); } interstitialVertices.Add(vertex); } } BoundingBox = new BoundingBox(min, max); // Accumulate normals for (int i = 0; i < _normalCalculationIndices.Length; i += 3) { TerrainVertexInterstitial vertex1 = interstitialVertices.ElementAt(_normalCalculationIndices[i]); TerrainVertexInterstitial vertex2 = interstitialVertices.ElementAt(_normalCalculationIndices[i + 1]); TerrainVertexInterstitial vertex3 = interstitialVertices.ElementAt(_normalCalculationIndices[i + 2]); Vector3 side1 = vertex1.Position - vertex3.Position; Vector3 side2 = vertex1.Position - vertex2.Position; Vector3 normal = Vector3.Cross(side1, side2); vertex1.Normal += normal; vertex2.Normal += normal; vertex3.Normal += normal; } List <TerrainVertexInterstitial> interstitialVerticesForBuffer = interstitialVertices.Where(v => v.IncludeInBuffer).ToList(); // Normalise normals foreach (TerrainVertexInterstitial vertex in interstitialVerticesForBuffer) { vertex.Normal = Vector3.Normalize(vertex.Normal); } TerrainVertex[] resultVerticesData = interstitialVerticesForBuffer.Select(v => v.ToTerrainVertex()).ToArray(); VertexBuffer = new VertexBuffer(_graphicsDevice, TerrainVertex.VertexDeclaration, resultVerticesData.Length, BufferUsage.WriteOnly); VertexBuffer.SetData(resultVerticesData); }