Beispiel #1
0
        public Vector3 CalculateSpin(Vector3 position)
        {
            // Combine transverse movement about center and pivot.
            // First project center onto position vector to get an orthogonal spin vector.
            Vector3 spin = Math2.ProjectOnVector(Traits.Center, position) - Traits.Center;

            if (spin.Length > 0.0001f)
            {
                Vector3 tangent = Vector3.Cross(spin, position);
                tangent.Normalize();
                tangent *= spin.Length * (float)Math.Tan(Traits.CenterRotation);
                return(tangent);
            }
            return(Vector3.Zero);
        }
Beispiel #2
0
        static Stress calculateStress(Vector3 movement0, Vector3 movement1, Vector3 boundaryVector, Vector3 boundaryNormal)
        {
            var relativeMovement = movement0 - movement1;
            var pressureVector   = Math2.ProjectOnVector(relativeMovement, boundaryNormal);
            var pressure         = pressureVector.Length;

            if (Vector3.Dot(pressureVector, boundaryNormal) > 0)
            {
                pressure = -pressure;
            }
            var shear = Math2.ProjectOnVector(relativeMovement, boundaryVector).Length;

            return(new Stress(2.0f / (1.0f + (float)Math.Exp(-pressure / 30.0f)) - 1.0f,
                              2.0f / (1.0f + (float)Math.Exp(-shear / 30.0f)) - 1.0f));
        }
Beispiel #3
0
        public Geometry <Vertex3DColor> GenerateDistanceDebugGeom()
        {
            List <Vertex3DColor> verts   = new List <Vertex3DColor>();
            List <uint>          indices = new List <uint>();

            for (int plateIndex = 0; plateIndex < plates.Length; ++plateIndex)
            {
                Vector3 center      = plates[plateIndex].Traits.Center;
                int     cornerIndex = 0;
                foreach (int corner in plates[plateIndex].Corners)
                {
                    float    hue       = (float)cornerIndex / (float)plates[plateIndex].Corners.Count;
                    Vector3  color3    = Math2.HSV2RGB(new Vector3(hue, 0.7f, 0.5f));
                    Vector4  color     = new Vector4(color3.X, color3.Y, color3.Z, 1.0f);
                    Centroid centroid  = geometry.Topology.Centroids[corner];
                    Vector3  cornerPos = centroid.position;
                    Vector3  direction = cornerPos - center;
                    direction.Normalize();
                    float theta    = centroid.PlateDistances[plateIndex];
                    float distance = 2.0f * (float)Math.Sin(theta * 0.5f);
                    direction *= distance;
                    cornerPos  = center + direction;
                    cornerPos.Normalize();
                    int vertexStart = verts.Count;
                    GeometryFactory.AddArcVerts(verts, center, cornerPos, 1.001f, color);
                    for (int vertexIndex = vertexStart; vertexIndex < verts.Count - 1; ++vertexIndex)
                    {
                        indices.Add((uint)vertexIndex);
                        indices.Add((uint)vertexIndex + 1);
                    }
                    ++cornerIndex;
                }
            }
            Mesh <Vertex3DColor>     mesh = new Mesh <Vertex3DColor>(verts.ToArray());
            Geometry <Vertex3DColor> geom = new Geometry <Vertex3DColor>(mesh, indices.ToArray());

            geom.PrimitiveType = OpenTK.Graphics.OpenGL.PrimitiveType.Lines;
            return(geom);
        }
Beispiel #4
0
        public Scene(World world, float width, float height)
        {
            this.world = world;

            camera = new Camera
            {
                Position = Vector3.UnitZ * 2.0f,
                Width    = width,
                Height   = height
            };

            ambientColor = Math2.ToVec3(Color.Aquamarine) * 0.25f;

            Shader  quadShader   = new Shader(SHADER_PATH + "quadVertShader.glsl", SHADER_PATH + "texFragShader.glsl");
            Shader  shader       = new Shader(SHADER_PATH + "Vert3DColorUVShader.glsl", SHADER_PATH + "shadedFragShader.glsl");
            Shader  pointShader  = new Shader(SHADER_PATH + "pointVertShader.glsl", SHADER_PATH + "pointFragShader.glsl");
            Shader  lineShader   = new Shader(SHADER_PATH + "pointColorVertShader.glsl", SHADER_PATH + "pointFragShader.glsl");
            Shader  texShader2   = new Shader(SHADER_PATH + "Vert3DColorUVShader.glsl", SHADER_PATH + "texFragShader.glsl");
            Shader  borderShader = new Shader(SHADER_PATH + "Vert3DColorShader.glsl", SHADER_PATH + "pointFragShader.glsl");
            Texture cellTexture  = new Texture("Edge.png");
            Texture arrowTexture = new Texture("Arrow.png");

            var node = new Node
            {
                Position = new Vector3(0, 0, -3)
            };

            node.Model = Matrix4.CreateTranslation(node.Position);
            nodes.Add(node);

            worldRenderGeometry = world.geometry.GenerateDualMesh <Vertex3DColorUV>();

            worldRenderer = new Renderer(worldRenderGeometry, shader);
            worldRenderer.AddUniform(new UniformProperty("lightPosition", lightPosition));
            worldRenderer.AddUniform(new UniformProperty("ambientColor", ambientColor));
            worldRenderer.AddTexture(cellTexture);
            worldRenderer.CullFaceFlag = true;
            node.Add(worldRenderer);

            borderGeometry = world.plates.GenerateBorderGeometry <Vertex3DColor>();
            borderGeometry.PrimitiveType = PrimitiveType.Triangles;
            borderRenderer = new Renderer(borderGeometry, borderShader)
            {
                DepthTestFlag = true,
                CullFaceFlag  = true,
                CullFaceMode  = CullFaceMode.Back
            };
            node.Add(borderRenderer);

            worldVertsDebugRenderer = new Renderer(world.geometry, pointShader);
            worldVertsDebugRenderer.AddUniform(new UniformProperty("color", new Vector4(0, 0.2f, 0.7f, 1)));
            worldVertsDebugRenderer.AddUniform(new UniformProperty("pointSize", 3f));
            //node.Add(worldVertsDebugRenderer);

            Geometry <Vertex3D> centroidGeom = new Geometry <Vertex3D>(world.geometry.GenerateCentroidPointMesh())
            {
                PrimitiveType = PrimitiveType.Points
            };

            worldCentroidDebugRenderer = new Renderer(centroidGeom, pointShader)
            {
                DepthTestFlag = false,
                CullFaceFlag  = false
            };
            worldCentroidDebugRenderer.AddUniform(new UniformProperty("color", new Vector4(0.5f, 0.5f, 0.5f, 1)));
            worldCentroidDebugRenderer.AddUniform(new UniformProperty("pointSize", 3f));
            worldCentroidDebugRenderer.AddUniform(new UniformProperty("zCutoff", -2.8f));
            //node.Add(worldCentroidDebugRenderer);

            var spinGeom = world.plates.GenerateSpinDriftDebugGeom(true);

            worldPlateSpinDebugRenderer = new Renderer(spinGeom, texShader2)
            {
                DepthTestFlag = false,
                CullFaceFlag  = false,
                BlendingFlag  = true
            };
            worldPlateSpinDebugRenderer.AddTexture(arrowTexture);
            worldPlateSpinDebugRenderer.AddUniform(new UniformProperty("color", new Vector4(1, 1, 1, 1.0f)));
            node.Add(worldPlateSpinDebugRenderer);

            var driftGeom = world.plates.GenerateSpinDriftDebugGeom(false);

            worldPlateDriftDebugRenderer = new Renderer(driftGeom, texShader2)
            {
                DepthTestFlag = false,
                CullFaceFlag  = false,
                BlendingFlag  = true
            };
            worldPlateDriftDebugRenderer.AddTexture(arrowTexture);
            worldPlateDriftDebugRenderer.AddUniform(new UniformProperty("color", new Vector4(.75f, 0.75f, 0.0f, 1.0f)));
            node.Add(worldPlateDriftDebugRenderer);

            var equatorGeom     = GeometryFactory.GenerateCircle(Vector3.Zero, Vector3.UnitY, 1.001f, new Vector4(1.0f, 0, 0, 1.0f));
            var equatorRenderer = new Renderer(equatorGeom, lineShader);

            equatorRenderer.AddUniform(new UniformProperty("zCutoff", -2.8f));
            node.Add(equatorRenderer);

            //var plateDistanceGeom = world.plates.GenerateDistanceDebugGeom();
            //var plateDistanceRenderer = new Renderer(plateDistanceGeom, lineShader)
            //{
            //    DepthTestFlag = true;
            //}
            //plateDistanceRenderer.AddUniform(new UniformProperty("zCutoff", -2.8f));
            //node.Add(plateDistanceRenderer);
        }
Beispiel #5
0
        public float RelaxTriangles(float multiplier)
        {
            NeedsUpdate = true;

            double totalSurfaceArea        = 4.0 * Math.PI;
            double idealFaceArea           = totalSurfaceArea / (indices.Length / 3);
            double idealEdgeLength         = Math.Sqrt(idealFaceArea * 4.0 / Math.Sqrt(3.0));
            double idealDistanceToCentroid = idealEdgeLength * Math.Sqrt(3) / 3.0 * 0.9;

            Vector3[] shiftPositions = new Vector3[mesh.vertices.Length];
            for (int i = 0; i < mesh.vertices.Length; ++i)
            {
                shiftPositions[i] = new Vector3(Vector3.Zero);
            }
            int numIndices = indices.Length;

            TVertex[] centroidVerts  = new TVertex[numIndices / 3];
            TVertex   centroidVertex = new TVertex();

            for (int i = 0; i < numIndices; i += 3)
            {
                Vector3 centroid = Topology.CalculateCentroid(i / 3);
                centroid.Normalize();
                MeshAttr.SetPosition(ref centroidVertex, ref centroid);

                Vector3[] oldPositions = new Vector3[3]
                {
                    new Vector3(MeshAttr.GetPosition(ref mesh.vertices[indices[i]])),
                    new Vector3(MeshAttr.GetPosition(ref mesh.vertices[indices[i + 1]])),
                    new Vector3(MeshAttr.GetPosition(ref mesh.vertices[indices[i + 2]])),
                };

                for (int j = 0; j < 3; ++j)
                {
                    Vector3 midLine   = centroid - oldPositions[j];
                    float   midLength = midLine.Length;
                    midLine *= (float)(multiplier * (midLength - idealDistanceToCentroid) / midLength);
                    shiftPositions[indices[i + j]] += midLine;
                }
            }

            var   origin = Vector3.Zero;
            Plane p      = new Plane(Vector3.UnitY, Vector3.Zero);

            for (int i = 0; i < mesh.vertices.Length; ++i)
            {
                Vector3 vertexPosition = MeshAttr.GetPosition(ref mesh.vertices[i]);
                p.Redefine(vertexPosition, origin);
                shiftPositions[i] = vertexPosition + p.ProjectPoint(shiftPositions[i]);
                shiftPositions[i].Normalize();
            }

            // Stop poylgons rotating about their centroid.
            // Doesn't stop triangles flipping.
            float[] rotationSuppressions = new float[mesh.vertices.Length];
            rotationSuppressions.Initialize();

            Topology.GenerateEdges();
            float minEdgeLength = (float)idealEdgeLength * 0.8f;
            float maxEdgeLength = (float)idealEdgeLength * 1.2f;

            foreach (var iter in Topology.Edges)
            {
                Int64   key     = iter.Key;
                int     index1  = (int)(key & 0xffffffff);
                int     index2  = (int)((key >> 32) & 0xffffffff);
                Vector3 oldPos1 = MeshAttr.GetPosition(ref mesh.vertices[index1]);
                Vector3 oldPos2 = MeshAttr.GetPosition(ref mesh.vertices[index2]);
                Vector3 newPos1 = shiftPositions[index1];
                Vector3 newPos2 = shiftPositions[index2];
                Vector3 oldEdge = oldPos2 - oldPos1;
                Vector3 newEdge = newPos2 - newPos1;
                if (newEdge.Length < minEdgeLength)
                {
                    // Move shift positions back out to ensure that the edge is never too small.
                    Vector3 midPt = newPos1 + 0.5f * newEdge;
                    newEdge.Normalize();
                    newEdge *= minEdgeLength * 0.5f;
                    shiftPositions[index1] = midPt - newEdge;
                    shiftPositions[index2] = midPt + newEdge;
                    newEdge = shiftPositions[index2] - shiftPositions[index1];
                }
                if (newEdge.Length > maxEdgeLength)
                {
                    // Move shift positions back in to ensure that the edge is never too large.
                    Vector3 midPt = newPos1 + 0.5f * newEdge;
                    newEdge.Normalize();
                    newEdge *= (maxEdgeLength * 0.5f);
                    shiftPositions[index1] = midPt - newEdge;
                    shiftPositions[index2] = midPt + newEdge;
                    newEdge = shiftPositions[index2] - shiftPositions[index1];
                }
                oldEdge.Normalize();
                newEdge.Normalize();
                float suppression = (1.0f - Vector3.Dot(oldEdge, newEdge)) * 0.5f;
                rotationSuppressions[index1] = Math.Max(suppression, rotationSuppressions[index1]);
                rotationSuppressions[index2] = Math.Max(suppression, rotationSuppressions[index2]);
            }

            for (int i = 0; i < mesh.vertices.Length; ++i)
            {
                Vector3 pos   = MeshAttr.GetPosition(ref mesh.vertices[i]);
                Vector3 delta = pos;
                pos = Math2.Lerp(pos, shiftPositions[i], (float)(1.0f - Math.Sqrt(rotationSuppressions[i])));
                pos.Normalize();
                shiftPositions[i] = pos;
            }

            float totalShift = 0;

            for (int i = 0; i < mesh.vertices.Length; ++i)
            {
                Vector3 delta = MeshAttr.GetPosition(ref mesh.vertices[i]);
                MeshAttr.SetPosition(ref mesh.vertices[i], ref shiftPositions[i]);
                delta      -= shiftPositions[i];
                totalShift += delta.Length;
            }

            Topology.Regenerate();

            return(totalShift);
        }
Beispiel #6
0
        public Geometry <AltVertex> GenerateBorderGeometry <AltVertex>()
            where AltVertex : struct, IVertex
        {
            if (borders == null || borders.Count == 0)
            {
                return(null);
            }
            else
            {
                List <AltVertex> vertices   = new List <AltVertex>();
                List <uint>      newIndices = new List <uint>();

                const float h = 0.1f;

                foreach (var iter in borders)
                {
                    Int64  borderKey = iter.Key;
                    int    v1index   = (int)(borderKey & 0xffffffff);
                    int    v2index   = (int)((borderKey >> 32) & 0xffffffff);
                    Border border    = iter.Value;

                    // The border lies along an edge in the dual geometry.
                    int     plateIndex1 = border.plate0;
                    int     plateIndex2 = border.plate1;
                    Vector3 v1Pos       = geometry.Mesh.GetPosition(v1index);
                    Vector3 v2Pos       = geometry.Mesh.GetPosition(v2index);
                    Vector3 centroid1   = geometry.Topology.Centroids[border.c1Index].position;
                    Vector3 centroid2   = geometry.Topology.Centroids[border.c2Index].position;

                    Vector3 v1g1prime = Math2.BaseProjection(v1Pos, centroid1, centroid2, h);
                    Vector3 v1g2prime = Math2.BaseProjection(v1Pos, centroid2, centroid1, h);
                    Vector3 v2g1prime = Math2.BaseProjection(v2Pos, centroid1, centroid2, h);
                    Vector3 v2g2prime = Math2.BaseProjection(v2Pos, centroid2, centroid1, h);

                    centroid1 *= 1.01f; // Project the centroids out of the sphere slightly
                    centroid2 *= 1.01f;

                    bool edgeOrderIsAnticlockwise = false;
                    for (int i = 0; i < 3; i++)
                    {
                        if (geometry.Indices[border.c1Index * 3 + i] == v1index)
                        {
                            if (geometry.Indices[border.c1Index * 3 + (i + 1) % 3] == v2index)
                            {
                                edgeOrderIsAnticlockwise = true;
                            }
                            break;
                        }
                    }

                    int index = vertices.Count;
                    geometry.AddTriangle(ref vertices, ref newIndices, ref v1g2prime, ref centroid2, ref centroid1, edgeOrderIsAnticlockwise);
                    geometry.AddTriangle(ref vertices, ref newIndices, ref v1g2prime, ref centroid1, ref v1g1prime, edgeOrderIsAnticlockwise);
                    geometry.AddTriangle(ref vertices, ref newIndices, ref v2g1prime, ref centroid1, ref centroid2, edgeOrderIsAnticlockwise);
                    geometry.AddTriangle(ref vertices, ref newIndices, ref v2g1prime, ref centroid2, ref v2g2prime, edgeOrderIsAnticlockwise);

                    float     p1      = Math2.Clamp(Math.Abs(borderCorners[border.c1Index].stress.pressure) * 1000.0f, 0, 1.0f);
                    float     p2      = Math2.Clamp(Math.Abs(borderCorners[border.c2Index].stress.pressure) * 1000.0f, 0, 1.0f);
                    float     hue1    = borderCorners[border.c1Index].stress.pressure > 0 ? 0 : 0.5f;
                    float     hue2    = borderCorners[border.c2Index].stress.pressure > 0 ? 0 : 0.5f;
                    Vector3   rgb1    = Math2.HSV2RGB(new Vector3(hue1, p1, 1.0f - p1));
                    Vector3   rgb2    = Math2.HSV2RGB(new Vector3(hue2, p2, 1.0f - p2));
                    Vector4   c1Color = new Vector4(rgb1.X, rgb1.Y, rgb1.Z, 1);
                    Vector4   c2Color = new Vector4(rgb2.X, rgb2.Y, rgb2.Z, 1);
                    AltVertex v;
                    for (int i = 0; i < 12; ++i)
                    {
                        Vector4 color = new Vector4(1.0f, 1.0f, 1.0f, 1.0f);
                        if (i == 0 || i == 1 || i == 3 || i == 8 || i == 10 || i == 11)
                        {
                            color = c2Color;
                        }
                        else if (i == 2 || i == 4 || i == 5 || i == 6 || i == 7 || i == 9)
                        {
                            color = c1Color;
                        }
                        v = vertices[index + i]; MeshAttr.SetColor(ref v, ref color); vertices[index + i] = v;
                    }
                }
                Mesh <AltVertex> newMesh = new Mesh <AltVertex>(vertices.ToArray());
                return(new Geometry <AltVertex>(newMesh, newIndices.ToArray()));
            }
        }