예제 #1
0
        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];
        }
예제 #2
0
        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);
        }