Example #1
0
        private void InitializePlates()
        {
            // Initialize vertexToPlate array to a value that isn't a valid plate index
            VertexToPlates = new int[geometry.Mesh.Length];
            for (int i = 0; i < geometry.Mesh.Length; ++i)
            {
                VertexToPlates[i] = -1;
            }
            borders.Clear();

            for (int plateIndex = 0; plateIndex < GetPlates().Length; ++plateIndex)
            {
                int plate = -1;
                do
                {
                    int vertexIndex = rand.Next(geometry.Mesh.Length);
                    // prevent 2 plates spawning at the same vertex.
                    plate = VertexToPlates[vertexIndex];
                    if (plate == -1)
                    {
                        var traits = new PlatePhysicsTraits();
                        traits.Pivot = new Vector3(rand.Next(100) - 50, rand.Next(100) - 50, rand.Next(100) - 50);
                        traits.Pivot.Normalize();
                        traits.Center = geometry.Mesh.GetPosition(vertexIndex);
                        if (Vector3.Dot(traits.Center, traits.Pivot) < 0)
                        {
                            traits.Pivot *= -1.0f;                                                 // Ensure pivot is at least in the same hemisphere as the plate center.
                        }
                        traits.CenterRotation = (rand.Next(200) - 100) * (float)Math.PI / 6000.0f; // -3 -> 3 degrees
                        traits.PivotRotation  = (rand.Next(200) - 100) * (float)Math.PI / 6000.0f;
                        traits.Elevation      = 0.0f;

                        GetPlates()[plateIndex] = new Plate(VertexToPlates, geometry, traits, plateIndex, vertexIndex, ref rand);
                        break;
                    }
                } while (plate != -1);
            }
        }
Example #2
0
        public void CalculateBorderTileHeights()
        {
            //     if perpendicular motion is +ve, it's a collision.
            //                                -ve, it's a rift (which would form basaltic volcanoes)
            //     If collision, then
            //        if heights sufficiently close & same sign, treat as height increase
            //           mountain formation; folding;
            //        if heights opposite sign; subduct the lower under the higher.
            //           tilt upper plate (calc for all boundaries)
            foreach (int borderCornerKey in borderCorners.Keys)
            {
                List <Int64> borderIndices = borderCorners[borderCornerKey].borderIndices;
                if (borderIndices.Count == 3)
                {
                    // At 3 plate boundaries, just take some maxima / averages:
                    Plate  plate0 = GetPlates()[VertexToPlates[geometry.Topology.Centroids[borderCornerKey].Faces[0]]];
                    Plate  plate1 = GetPlates()[VertexToPlates[geometry.Topology.Centroids[borderCornerKey].Faces[1]]];
                    Plate  plate2 = GetPlates()[VertexToPlates[geometry.Topology.Centroids[borderCornerKey].Faces[2]]];
                    Stress stress = borderCorners[borderCornerKey].stress;
                    if (stress.pressure > 0.3)
                    {
                        borderCorners[borderCornerKey].elevation = Math.Max(plate0.Traits.Elevation, Math.Max(plate1.Traits.Elevation, plate2.Traits.Elevation)) + stress.pressure;
                    }
                    else if (stress.pressure < -0.3)
                    {
                        borderCorners[borderCornerKey].elevation = Math.Max(plate0.Traits.Elevation, Math.Max(plate1.Traits.Elevation, plate2.Traits.Elevation)) + stress.pressure / 4;
                    }
                    else if (stress.shear > 0.3)
                    {
                        borderCorners[borderCornerKey].elevation = Math.Max(plate0.Traits.Elevation, Math.Max(plate1.Traits.Elevation, plate2.Traits.Elevation)) + stress.shear / 8;
                    }
                    else
                    {
                        borderCorners[borderCornerKey].elevation = (plate0.Traits.Elevation + plate1.Traits.Elevation + plate2.Traits.Elevation) / 3.0f;
                    }
                }
                else
                {
                    Border border0     = borders[borderIndices[0]];
                    Border border1     = borders[borderIndices[1]];
                    int    plateIndex0 = border0.plate0;
                    int    plateIndex1 = border1.plate0 == plateIndex0 ? border1.plate1 : border0.plate1;
                    Plate  plate0      = GetPlates()[plateIndex0];
                    Plate  plate1      = GetPlates()[plateIndex1];

                    ElevationCalculation elevationCalculation = ElevationCalculation.DORMANT;
                    Stress stress = borderCorners[borderCornerKey].stress;
                    if (stress.pressure > 0.3)
                    {
                        borderCorners[borderCornerKey].elevation = Math.Max(plate0.Traits.Elevation, plate1.Traits.Elevation) + stress.pressure;

                        if (plate0.Traits.Elevation < 0 && plate0.Traits.Elevation < 0)
                        {
                            elevationCalculation = ElevationCalculation.COLLIDING;
                        }
                        else if (plate0.Traits.Elevation < 0)
                        {
                            elevationCalculation = ElevationCalculation.SUBDUCTING;
                        }
                        else if (plate1.Traits.Elevation < 0)
                        {
                            elevationCalculation = ElevationCalculation.SUPERDUCTING;
                        }
                        else
                        {
                            elevationCalculation = ElevationCalculation.COLLIDING;
                        }
                    }
                    else if (stress.pressure < -0.3)
                    {
                        borderCorners[borderCornerKey].elevation = Math.Max(plate0.Traits.Elevation, plate1.Traits.Elevation) + stress.pressure / 4;
                        elevationCalculation = ElevationCalculation.DIVERGING;
                    }
                    else if (stress.shear > 0.3)
                    {
                        borderCorners[borderCornerKey].elevation = Math.Max(plate0.Traits.Elevation, plate1.Traits.Elevation) + stress.shear / 8;
                        elevationCalculation = ElevationCalculation.SHEARING;
                    }
                    else
                    {
                        borderCorners[borderCornerKey].elevation = (plate0.Traits.Elevation + plate1.Traits.Elevation) / 2.0f;
                        elevationCalculation = ElevationCalculation.DORMANT;
                    }

                    // Queue up:
                    //   next corner: Inner corner: the corner that isn't the opposite corner of border0 and border1
                    //     (i.e. remove the opposite corners from Centroid neighbours, and it's the remaining one).
                    //   origin: { this corner, stress, plate, elevationType }
                    //   border: inner border
                    //   corner: this corner
                    //   distanceToPlateBoundary: inner border length, i.e. of next corner.
                }
            }
        }
Example #3
0
        public void CalculateStresses()
        {
            // for each vertex in plate boundaries,
            //   calculate relative motion between tiles
            //     both parallel to (shear) and perpendicular to (pressure) edge.

            foreach (int borderCornerKey in borderCorners.Keys)
            {
                List <Int64> borderIndices = borderCorners[borderCornerKey].borderIndices;
                var          centroid      = geometry.Topology.Centroids[borderCornerKey];
                var          pos           = centroid.position;

                Dictionary <int, Vector3> plateMovement = new Dictionary <int, Vector3>();
                foreach (Int64 borderKey in borderIndices)
                {
                    Border border = borders[borderKey];

                    // Calculate movement only once for each plate
                    for (int i = 0; i < 2; ++i)
                    {
                        int     plateIndex = (i == 0) ? border.plate0 : border.plate1;
                        Vector3 movement;
                        if (!plateMovement.TryGetValue(plateIndex, out movement))
                        {
                            Plate plate = GetPlates()[plateIndex];
                            movement = plate.CalculateSpin(pos) + plate.CalculateDrift(pos);
                            plateMovement[plateIndex] = movement;
                        }
                    }
                }

                if (borderIndices.Count == 3)
                {
                    // 3 separate plates. Find movement from each plate at this corner and average it
                    Stress[] stresses  = new Stress[3];
                    int      stressIdx = 0;
                    foreach (Int64 borderKey in borderIndices)
                    {
                        Border  border = borders[borderKey];
                        int     oppositeCornerIndex    = border.OppositeCorner(borderCornerKey);
                        var     oppositeCornerPosition = geometry.Topology.Centroids[oppositeCornerIndex].position;
                        Vector3 boundary       = oppositeCornerPosition - pos;
                        Vector3 boundaryNormal = Vector3.Cross(boundary, pos);
                        stresses[stressIdx++] = calculateStress(plateMovement[border.plate0], plateMovement[border.plate1], boundary, boundaryNormal);
                    }
                    borderCorners[borderCornerKey].stress.pressure = (stresses[0].pressure + stresses[1].pressure + stresses[2].pressure) / 3.0f;
                    borderCorners[borderCornerKey].stress.shear    = (stresses[0].shear + stresses[1].shear + stresses[2].shear) / 3.0f;
                }
                else // Border between only 2 plates.
                {
                    // generate average vector, calculate stress once.
                    Border  border0 = borders[borderIndices[0]];
                    Border  border1 = borders[borderIndices[1]];
                    int     plate0  = border0.plate0;
                    int     plate1  = border1.plate0 == plate0 ? border1.plate1 : border0.plate1;
                    int     oppositeCornerIndex0    = border0.OppositeCorner(borderCornerKey);
                    int     oppositeCornerIndex1    = border0.OppositeCorner(borderCornerKey);
                    var     oppositeCornerPosition0 = geometry.Topology.Centroids[oppositeCornerIndex0].position;
                    var     oppositeCornerPosition1 = geometry.Topology.Centroids[oppositeCornerIndex1].position;
                    Vector3 boundary       = oppositeCornerPosition1 = oppositeCornerPosition0;
                    Vector3 boundaryNormal = Vector3.Cross(boundary, pos);
                    borderCorners[borderCornerKey].stress = calculateStress(plateMovement[plate0], plateMovement[plate1], boundary, boundaryNormal);
                }
            }
        }