/// <summary>
        /// Creates a manifold, consisting of a topology and vertex positions, in the shape of an icosahedron.
        /// </summary>
        /// <param name="surface">The spherical surface describing the overall shape of the manifold.</param>
        /// <param name="topology">The topology created.</param>
        /// <param name="vertexPositions">The vertex positions created.</param>
        public static void CreateIcosahedron(SphericalSurface surface, out Topology topology, out Vector3[] vertexPositions)
        {
            var latitude     = Mathf.Atan2(1, 2);
            var longitude    = Mathf.PI * 0.2f;
            var cosLat       = Mathf.Cos(latitude);
            var scaledCosLat = surface.radius * cosLat;

            var x0 = 0.0f;
            var x1 = scaledCosLat * Mathf.Sin(longitude);
            var x2 = scaledCosLat * Mathf.Sin(longitude * 2.0f);
            var y0 = +surface.radius;
            var y1 = surface.radius * Mathf.Sin(latitude);
            var y2 = -surface.radius;
            var z0 = scaledCosLat;
            var z1 = scaledCosLat * Mathf.Cos(longitude);
            var z2 = scaledCosLat * Mathf.Cos(longitude * 2.0f);

            vertexPositions     = new Vector3[12];
            vertexPositions[0]  = new Vector3(x0, y0, 0f);
            vertexPositions[1]  = new Vector3(x0, +y1, -z0);
            vertexPositions[2]  = new Vector3(-x2, +y1, -z2);
            vertexPositions[3]  = new Vector3(-x1, +y1, +z1);
            vertexPositions[4]  = new Vector3(+x1, +y1, +z1);
            vertexPositions[5]  = new Vector3(+x2, +y1, -z2);
            vertexPositions[6]  = new Vector3(x0, -y1, +z0);
            vertexPositions[7]  = new Vector3(-x2, -y1, +z2);
            vertexPositions[8]  = new Vector3(-x1, -y1, -z1);
            vertexPositions[9]  = new Vector3(+x1, -y1, -z1);
            vertexPositions[10] = new Vector3(+x2, -y1, +z2);
            vertexPositions[11] = new Vector3(x0, y2, 0f);

            var orientation = surface.orientation;

            for (int i = 0; i < vertexPositions.Length; ++i)
            {
                vertexPositions[i] = orientation * vertexPositions[i];
            }

            var indexer = new ManualFaceNeighborIndexer(12, 60, 20);

            if (!surface.isInverted)
            {
                indexer.AddFace(0, 1, 2);
                indexer.AddFace(0, 2, 3);
                indexer.AddFace(0, 3, 4);
                indexer.AddFace(0, 4, 5);
                indexer.AddFace(0, 5, 1);
                indexer.AddFace(1, 8, 2);
                indexer.AddFace(2, 8, 7);
                indexer.AddFace(2, 7, 3);
                indexer.AddFace(3, 7, 6);
                indexer.AddFace(3, 6, 4);
                indexer.AddFace(4, 6, 10);
                indexer.AddFace(4, 10, 5);
                indexer.AddFace(5, 10, 9);
                indexer.AddFace(5, 9, 1);
                indexer.AddFace(1, 9, 8);
                indexer.AddFace(11, 6, 7);
                indexer.AddFace(11, 7, 8);
                indexer.AddFace(11, 8, 9);
                indexer.AddFace(11, 9, 10);
                indexer.AddFace(11, 10, 6);
            }
            else
            {
                indexer.AddFace(2, 1, 0);
                indexer.AddFace(3, 2, 0);
                indexer.AddFace(4, 3, 0);
                indexer.AddFace(5, 4, 0);
                indexer.AddFace(1, 5, 0);
                indexer.AddFace(2, 8, 1);
                indexer.AddFace(7, 8, 2);
                indexer.AddFace(3, 7, 2);
                indexer.AddFace(6, 7, 3);
                indexer.AddFace(4, 6, 3);
                indexer.AddFace(10, 6, 4);
                indexer.AddFace(5, 10, 4);
                indexer.AddFace(9, 10, 5);
                indexer.AddFace(1, 9, 5);
                indexer.AddFace(8, 9, 1);
                indexer.AddFace(7, 6, 11);
                indexer.AddFace(8, 7, 11);
                indexer.AddFace(9, 8, 11);
                indexer.AddFace(10, 9, 11);
                indexer.AddFace(6, 10, 11);
            }

            topology = TopologyUtility.BuildTopology(indexer);
        }
 /// <summary>
 /// Reverses the roles of vertices and faces, as when taking the dual of a polyhedron.
 /// </summary>
 /// <param name="surface">The spherical surface describing the overall shape of the manifold.</param>
 /// <param name="topology">The topology containing the vertices and faces to swap.</param>
 /// <param name="vertexPositions">The positions of the vertices, which will become the new positions after the call is complete, calculated as the face centroids of the original topology.</param>
 public static void MakeDual(SphericalSurface surface, Topology topology, ref Vector3[] vertexPositions)
 {
     ManifoldUtility.MakeDual(topology, FaceAttributeUtility.CalculateSphericalFaceCentroidsFromVertexPositions(topology.faces, surface, vertexPositions.AsVertexAttribute()), out vertexPositions);
 }
 /// <summary>
 /// Creates a manifold, consisting of a topology and vertex positions, in the shape of a dodecahedron.
 /// </summary>
 /// <param name="surface">The spherical surface describing the overall shape of the manifold.</param>
 /// <param name="topology">The topology created.</param>
 /// <param name="vertexPositions">The vertex positions created.</param>
 public static void CreateDodecahedron(SphericalSurface surface, out Topology topology, out Vector3[] vertexPositions)
 {
     CreateIcosahedron(surface, out topology, out vertexPositions);
     MakeDual(surface, topology, ref vertexPositions);
 }
Esempio n. 4
0
        protected override void OnPropertiesGUI()
        {
            var generator = (PlanarManifoldGenerator)target;

            EditorGUILayout.PropertyField(_serializedGenerator.FindProperty("size"), new GUIContent("Size"));

            EditorGUILayout.Space();

            generator.tileType = (PlanarManifoldGenerator.TileTypes)EditorGUILayout.EnumPopup("Tile Type", generator.tileType);

            switch (generator.tileType)
            {
            case PlanarManifoldGenerator.TileTypes.Quadrilateral:
            {
                generator.SetQuadTileShape((PlanarManifoldGenerator.QuadTileShapes)EditorGUILayout.EnumPopup("Tile Shape", generator.quadTileShape));

                bool canGenerate                    = generator.canGenerate;
                RectangularQuadGrid surface         = null;
                Topology            topology        = null;
                Vector3[]           vertexPositions = null;

                if (canGenerate && Event.current.type == EventType.Repaint)
                {
                    surface  = generator.ResetSurface(CreateInstance <RectangularQuadGrid>(), Vector3.zero, Quaternion.identity, true, new Numerics.IntVector2(3, 3));
                    topology = surface.CreateManifold(out vertexPositions);
                }

                EditorGUILayout.BeginHorizontal();
                {
                    EditorGUILayout.Space();

                    float previewSize = 128f;
                    var   previewRect = GUILayoutUtility.GetRect(previewSize, previewSize + _previewStyle.margin.top + _previewStyle.margin.bottom, _previewStyle, GUILayout.ExpandWidth(false));
                    if (canGenerate && Event.current.type == EventType.Repaint)
                    {
                        DrawQuadTilePreview(generator, previewRect.min, previewSize);
                    }

                    EditorGUILayout.Space();

                    previewRect = GUILayoutUtility.GetRect(previewSize, previewSize + _previewStyle.margin.top + _previewStyle.margin.bottom, _previewStyle, GUILayout.ExpandWidth(false));
                    if (canGenerate && Event.current.type == EventType.Repaint)
                    {
                        DrawQuadTile3x3Preview(generator, topology, vertexPositions, previewRect.min, previewSize);
                    }

                    EditorGUILayout.Space();
                }
                EditorGUILayout.EndHorizontal();

                EditorGUI.BeginChangeCheck();
                generator.axis0 = EditorGUILayout.Vector2Field("Axis 0", generator.axis0);
                generator.axis1 = EditorGUILayout.Vector2Field("Axis 1", generator.axis1);
                if (EditorGUI.EndChangeCheck())
                {
                    generator.SetQuadTileShape(PlanarManifoldGenerator.QuadTileShapes.Custom);
                }
                break;
            }

            case PlanarManifoldGenerator.TileTypes.Hexagonal:
            {
                generator.SetHexTileShape((PlanarManifoldGenerator.HexTileShapes)EditorGUILayout.EnumPopup("Tile Shape", generator.hexTileShape));

                bool canGenerate                   = generator.canGenerate;
                RectangularHexGrid surface         = null;
                Topology           topology        = null;
                Vector3[]          vertexPositions = null;

                if (canGenerate && Event.current.type == EventType.Repaint)
                {
                    surface  = generator.ResetSurface(CreateInstance <RectangularHexGrid>(), Vector3.zero, Quaternion.identity, true, new Numerics.IntVector2(3, 3));
                    topology = surface.CreateManifold(out vertexPositions);
                }

                EditorGUILayout.BeginHorizontal();
                {
                    EditorGUILayout.Space();

                    float previewSize = 128f;
                    var   previewRect = GUILayoutUtility.GetRect(previewSize, previewSize + _previewStyle.margin.top + _previewStyle.margin.bottom, _previewStyle, GUILayout.ExpandWidth(false));
                    if (canGenerate && Event.current.type == EventType.Repaint)
                    {
                        DrawHexTilePreview(generator, surface, topology, vertexPositions, previewRect.min, previewSize);
                    }

                    EditorGUILayout.Space();

                    previewRect = GUILayoutUtility.GetRect(previewSize, previewSize + _previewStyle.margin.top + _previewStyle.margin.bottom, _previewStyle, GUILayout.ExpandWidth(false));
                    if (canGenerate && Event.current.type == EventType.Repaint)
                    {
                        DrawHexTile3x3Preview(generator, surface, topology, vertexPositions, previewRect.min, previewSize);
                    }

                    EditorGUILayout.Space();
                }
                EditorGUILayout.EndHorizontal();

                EditorGUI.BeginChangeCheck();
                generator.midpoint         = EditorGUILayout.Vector2Field("Midpoint", generator.midpoint);
                generator.majorCorner      = EditorGUILayout.Vector2Field("Major Corner", generator.majorCorner);
                generator.minorCorner      = EditorGUILayout.Vector2Field("Minor Corner", generator.minorCorner);
                generator.hexGridAxisStyle = (HexGridAxisStyles)EditorGUILayout.EnumPopup("Axis Style", generator.hexGridAxisStyle);
                generator.swapAxes         = EditorGUILayout.Toggle("Swap Axes", generator.swapAxes);
                if (EditorGUI.EndChangeCheck())
                {
                    generator.SetHexTileShape(PlanarManifoldGenerator.HexTileShapes.Custom);
                }
                break;
            }

            default: throw new System.NotImplementedException();
            }

            generator.isAxis0Wrapped = EditorGUILayout.Toggle("Axis 0 Wraps", generator.isAxis0Wrapped, GUILayout.ExpandWidth(false));
            generator.isAxis1Wrapped = EditorGUILayout.Toggle("Axis 1 Wraps", generator.isAxis1Wrapped, GUILayout.ExpandWidth(false));

            EditorGUILayout.Space();

            generator.origin   = EditorGUILayout.Vector3Field("Origin", generator.origin);
            generator.rotation = EditorGUILayout.Vector3Field("Rotation", generator.rotation);
        }
Esempio n. 5
0
        private void DrawHexTile3x3Preview(PlanarManifoldGenerator generator, RectangularHexGrid surface, Topology topology, Vector3[] vertexPositions, Vector3 root, float previewSize)
        {
            var adjustedVertexPositions = new Vector3[vertexPositions.Length].AsVertexAttribute();

            Vector3 min = vertexPositions[0];
            Vector3 max = vertexPositions[0];

            for (int i = 1; i < vertexPositions.Length; ++i)
            {
                min = Vector3.Min(min, vertexPositions[i]);
                max = Vector3.Max(max, vertexPositions[i]);
            }
            Vector3 range    = max - min;
            float   maxRange = Mathf.Max(range.x, range.y);
            Vector3 margin   = (new Vector3(maxRange, maxRange, 0f) - range) * 0.5f;
            Vector3 offset   = margin - min;
            float   scale    = previewSize / maxRange;

            for (int i = 0; i < vertexPositions.Length; ++i)
            {
                adjustedVertexPositions[i] = AdjustPosition(vertexPositions[i], offset, root, maxRange, scale);
            }

            var faceVertexPositions = new Vector3[6];

            Handles.color = fillColor;
            foreach (var face in topology.internalFaces)
            {
                var edge = face.firstEdge;
                for (int i = 0; i < 6; ++i)
                {
                    faceVertexPositions[i] = adjustedVertexPositions[edge];
                    edge = edge.next;
                }
                Handles.DrawAAConvexPolygon(faceVertexPositions);
            }

            Handles.color = outlineColor;
            foreach (var edge in topology.vertexEdges)
            {
                if (edge.nearVertex < edge.farVertex)
                {
                    Handles.DrawAAPolyLine(adjustedVertexPositions[edge.nearVertex], adjustedVertexPositions[edge.farVertex]);
                }
            }

            var p0 = adjustedVertexPositions[surface.GetVertexIndex(0, 0)];;

            if (!generator.swapAxes)
            {
                var a01 = adjustedVertexPositions[surface.GetVertexIndex(2, 0)];
                var a02 = adjustedVertexPositions[surface.GetVertexIndex(4, 0)];
                var a11 = adjustedVertexPositions[surface.GetVertexIndex(0, 1)];
                var a12 = adjustedVertexPositions[surface.GetVertexIndex(0, 2)];

                Handles.color = Handles.xAxisColor;
                Handles.DrawAAPolyLine(p0, a01, a02);
                Handles.DrawSolidDisc(a01, Vector3.back, 3f);
                Handles.DrawSolidDisc(a02, Vector3.back, 3f);

                if (generator.hexGridAxisStyle != HexGridAxisStyles.Straight)
                {
                    Handles.color = ChangeAlpha(Handles.yAxisColor + Color.white * 0.25f, 0.75f);
                    Handles.DrawAAPolyLine(p0, a12);
                }
                Handles.color = Handles.yAxisColor;
                Handles.DrawAAPolyLine(p0, a11, a12);
                Handles.DrawSolidDisc(a11, Vector3.back, 3f);
                Handles.DrawSolidDisc(a12, Vector3.back, 3f);
            }
            else
            {
                var a01 = adjustedVertexPositions[surface.GetVertexIndex(1, 0)];
                var a02 = adjustedVertexPositions[surface.GetVertexIndex(2, 0)];
                var a11 = adjustedVertexPositions[surface.GetVertexIndex(0, 2)];
                var a12 = adjustedVertexPositions[surface.GetVertexIndex(0, 4)];

                if (generator.hexGridAxisStyle != HexGridAxisStyles.Straight)
                {
                    Handles.color = ChangeAlpha(Handles.xAxisColor + Color.white * 0.25f, 0.75f);
                    Handles.DrawAAPolyLine(p0, a02);
                }
                Handles.color = Handles.xAxisColor;
                Handles.DrawAAPolyLine(p0, a01, a02);
                Handles.DrawSolidDisc(a01, Vector3.back, 3f);
                Handles.DrawSolidDisc(a02, Vector3.back, 3f);

                Handles.color = Handles.yAxisColor;
                Handles.DrawAAPolyLine(p0, a11, a12);
                Handles.DrawSolidDisc(a11, Vector3.back, 3f);
                Handles.DrawSolidDisc(a12, Vector3.back, 3f);
            }
        }
Esempio n. 6
0
        private void DrawHexTilePreview(PlanarManifoldGenerator generator, RectangularHexGrid surface, Topology topology, Vector3[] vertexPositions, Vector3 root, float previewSize)
        {
            var face = topology.internalFaces[0];
            var adjustedVertexPositions = new Vector3[face.neighborCount].AsVertexAttribute();

            var     firstEdge = face.firstEdge;
            var     pos       = vertexPositions[firstEdge.vertex.index];
            Vector3 min       = pos;
            Vector3 max       = pos;
            var     edge      = firstEdge.next;

            while (edge != firstEdge)
            {
                pos  = vertexPositions[edge.vertex.index];
                min  = Vector3.Min(min, pos);
                max  = Vector3.Max(max, pos);
                edge = edge.next;
            }
            Vector3 range    = max - min;
            float   maxRange = Mathf.Max(range.x, range.y);
            Vector3 margin   = (new Vector3(maxRange, maxRange, 0f) - range) * 0.5f;
            Vector3 offset   = margin - min;
            float   scale    = previewSize / maxRange;

            for (int i = 0; i < face.neighborCount; ++i)
            {
                adjustedVertexPositions[i] = AdjustPosition(vertexPositions[edge.vertex.index], offset, root, maxRange, scale);
                edge = edge.next;
            }

            Handles.color = fillColor;
            Handles.DrawAAConvexPolygon(adjustedVertexPositions.array);

            Handles.color = outlineColor;
            Handles.DrawAAPolyLine(adjustedVertexPositions.array);
            Handles.DrawAAPolyLine(adjustedVertexPositions[5], adjustedVertexPositions[0]);

            Vector2 pC = (vertexPositions[firstEdge.vertex.index] + vertexPositions[firstEdge.next.next.next.vertex.index]) * 0.5f;
            Vector3 vC = AdjustPosition(pC, offset, root, maxRange, scale);
            Vector3 v2 = AdjustPosition(pC + generator.majorCorner, offset, root, maxRange, scale);
            Vector3 v3 = AdjustPosition(pC + generator.minorCorner, offset, root, maxRange, scale);
            Vector3 vM = AdjustPosition(pC + generator.midpoint, offset, root, maxRange, scale);

            var midpointColor = generator.swapAxes ? Handles.yAxisColor : Handles.xAxisColor;

            Handles.color = midpointColor;
            Handles.DrawAAPolyLine(vC, vM);
            Handles.color = ChangeAlpha(midpointColor, 0.25f);
            Handles.DrawSolidDisc(vM, Vector3.back, 5f);
            Handles.color = midpointColor;
            Handles.DrawWireDisc(vM, Vector3.back, 5f);

            Color majorCornerColor;

            if (generator.hexGridAxisStyle == HexGridAxisStyles.Straight)
            {
                majorCornerColor = Embolden(Average(Handles.xAxisColor, Handles.yAxisColor));
            }
            else
            {
                majorCornerColor = generator.swapAxes ? Handles.xAxisColor : Handles.yAxisColor;
            }
            Handles.color = majorCornerColor;
            Handles.DrawAAPolyLine(vC, v2);
            Handles.color = ChangeAlpha(majorCornerColor, 0.25f);
            Handles.DrawSolidDisc(v2, Vector3.back, 5f);
            Handles.color = majorCornerColor;
            Handles.DrawWireDisc(v2, Vector3.back, 5f);

            Color minorCornerColor = Handles.zAxisColor;

            Handles.color = minorCornerColor;
            Handles.DrawAAPolyLine(vC, v3);
            Handles.color = ChangeAlpha(minorCornerColor, 0.25f);
            Handles.DrawSolidDisc(v3, Vector3.back, 5f);
            Handles.color = minorCornerColor;
            Handles.DrawWireDisc(v3, Vector3.back, 5f);

            if (generator.hexGridAxisStyle == HexGridAxisStyles.Straight)
            {
                Handles.color = generator.swapAxes ? Handles.xAxisColor : Handles.yAxisColor;
                Handles.DrawAAPolyLine(vC, (v2 + v3) * 0.5f);
            }
        }
Esempio n. 7
0
        private void DrawQuadTile3x3Preview(PlanarManifoldGenerator generator, Topology topology, Vector3[] vertexPositions, Vector3 root, float previewSize)
        {
            var adjustedVertexPositions = new Vector3[vertexPositions.Length].AsVertexAttribute();

            Vector3 min = vertexPositions[0];
            Vector3 max = vertexPositions[0];

            for (int i = 1; i < vertexPositions.Length; ++i)
            {
                min = Vector3.Min(min, vertexPositions[i]);
                max = Vector3.Max(max, vertexPositions[i]);
            }
            Vector3 range    = max - min;
            float   maxRange = Mathf.Max(range.x, range.y);
            Vector3 margin   = (new Vector3(maxRange, maxRange, 0f) - range) * 0.5f;
            Vector3 offset   = margin - min;
            float   scale    = previewSize / maxRange;

            for (int i = 0; i < vertexPositions.Length; ++i)
            {
                adjustedVertexPositions[i] = AdjustPosition(vertexPositions[i], offset, root, maxRange, scale);
            }

            var faceVertexPositions = new Vector3[4];

            Handles.color = fillColor;
            foreach (var face in topology.internalFaces)
            {
                var edge = face.firstEdge;
                for (int i = 0; i < 4; ++i)
                {
                    faceVertexPositions[i] = adjustedVertexPositions[edge];
                    edge = edge.next;
                }
                Handles.DrawAAConvexPolygon(faceVertexPositions);
            }

            Handles.color = outlineColor;
            foreach (var edge in topology.vertexEdges)
            {
                if (edge.nearVertex < edge.farVertex)
                {
                    Handles.DrawAAPolyLine(adjustedVertexPositions[edge.nearVertex], adjustedVertexPositions[edge.farVertex]);
                }
            }

            var p0  = AdjustPosition(Vector3.zero, offset, root, maxRange, scale);
            var a01 = AdjustPosition(generator.axis0 * 1f, offset, root, maxRange, scale);
            var a02 = AdjustPosition(generator.axis0 * 2f, offset, root, maxRange, scale);
            var a03 = AdjustPosition(generator.axis0 * 3f, offset, root, maxRange, scale);
            var a11 = AdjustPosition(generator.axis1 * 1f, offset, root, maxRange, scale);
            var a12 = AdjustPosition(generator.axis1 * 2f, offset, root, maxRange, scale);
            var a13 = AdjustPosition(generator.axis1 * 3f, offset, root, maxRange, scale);

            Handles.color = Handles.xAxisColor;
            Handles.DrawAAPolyLine(p0, a03);
            Handles.DrawSolidDisc(a01, Vector3.back, 3f);
            Handles.DrawSolidDisc(a02, Vector3.back, 3f);
            Handles.DrawSolidDisc(a03, Vector3.back, 3f);

            Handles.color = Handles.yAxisColor;
            Handles.DrawAAPolyLine(p0, a13);
            Handles.DrawSolidDisc(a11, Vector3.back, 3f);
            Handles.DrawSolidDisc(a12, Vector3.back, 3f);
            Handles.DrawSolidDisc(a13, Vector3.back, 3f);
        }