private static IEnumerable <IntVector3[]> FaceSymmetryGroup(string symmetryType, params IntVector3[] vertexKeys)
 {
     foreach (Symmetry symmetry in Symmetry.SymmetryGroup(symmetryType))
     {
         yield return(symmetry.Apply(vertexKeys));
     }
 }
    public static RenderGeometry CreateCuboctahedronGeometry(float size, float ratio)
    {
        if (ratio <= 0)
        {
            return(CreateTetrahedronGeometry(size, 1));
        }
        if (ratio >= 1)
        {
            RenderGeometry result = CreateTetrahedronGeometry(size, 1);
            result.ApplyRotation(Quaternion.AngleAxis(90, Vector3.up));
            return(result);
        }

        RenderGeometry geometry = new RenderGeometry();

        var corners = new Dictionary <IntVector3, Vertex>();

        foreach (var symmetry in Symmetry.SymmetryGroup("110"))
        {
            IntVector3 key      = symmetry.Apply(Key(1, 1, 0));
            Vector3    position = symmetry.Apply(Vec(1, 1, (1 - ratio * 2) * (symmetry.isNegative ? -1 : 1)) * (size / 2));
            corners[key] = geometry.CreateVertex(position);
        }
        foreach (IntVector3[] keys in Combine(
                     FaceSymmetryGroup("100", Key(1, 0, -1), Key(1, 1, 0), Key(1, 0, 1), Key(1, -1, 0)),
                     FaceSymmetryGroup("111", Key(1, 1, 0), Key(0, 1, 1), Key(1, 0, 1))))
        {
            geometry.CreateFace(keys.Select(key => corners[key]).ToArray());
        }
        return(geometry);
    }
 private static IEnumerable <KeyValuePair <IntVector3, Vector3> > VertexSymmetryGroup(string symmetryType, IntVector3 key, Vector3 position)
 {
     foreach (Symmetry symmetry in Symmetry.SymmetryGroup(symmetryType))
     {
         yield return(new KeyValuePair <IntVector3, Vector3>(symmetry.Apply(key), symmetry.Apply(position)));
     }
 }
    private static RenderGeometry CreateCubeGeometryInternal(Vector3 size, Func <int, SurfaceComponentGeometry> surfaceGenerator)
    {
        StructureGeometry structure = new StructureGeometry();

        var corners = new Dictionary <IntVector3, Vertex>();

        foreach (var keyAndPosition in VertexSymmetryGroup("111", Key(1, 1, 1), Vector3.one))
        {
            corners[keyAndPosition.Key] = structure.CreateVertex(keyAndPosition.Value.Times(size / 2));
        }
        foreach (Symmetry symmetry in Symmetry.SymmetryGroup("100"))
        {
            Vertex[] verts = symmetry.Apply(Key(1, -1, -1), Key(1, 1, -1), Key(1, 1, 1), Key(1, -1, 1)).Select(key => corners[key]).ToArray();
            structure.CreateFace(surfaceGenerator.Invoke(symmetry.rotation), true, verts);
        }
        return(structure.Build());
    }
    public static RenderGeometry CreateBuildingBlockGeometry(Vector3 size, bool[,,] corners)
    {
        RenderGeometry geometry = new RenderGeometry();

        bool cornerUsed(IntVector3 key) => corners[(key.x + 1) / 2, (key.y + 1) / 2, (key.z + 1) / 2];

        var cornerVerts = new Dictionary <IntVector3, Vertex>();

        foreach (IntVector3 key in IntVector3.allTriaxialDirections)
        {
            if (cornerUsed(key))
            {
                cornerVerts[key] = geometry.CreateVertex(key * (size / 2));
            }
        }

        void construct(string symmetryType, IntVector3[] faceKeys, IntVector3[] outsideKeys)
        {
            int n = faceKeys.Length;

            foreach (Symmetry symmetry in Symmetry.SymmetryGroup(symmetryType))
            {
                if (symmetry.Apply(outsideKeys).Any(key => cornerUsed(key)))
                {
                    continue;
                }

                IntVector3[] newFaceKeys = symmetry.Apply(faceKeys);
                if (newFaceKeys.All(key => cornerUsed(key)))
                {
                    geometry.CreateFace(newFaceKeys.Select(key => cornerVerts[key]).ToArray());
                }
                else if (n == 4)
                {
                    for (int i = 0; i < 4; i++)
                    {
                        IntVector3[] subFaceKeys = new[] { newFaceKeys[i], newFaceKeys[(i + 1) % 4], newFaceKeys[(i + 2) % 4] };
                        if (subFaceKeys.All(key => cornerUsed(key)))
                        {
                            geometry.CreateFace(subFaceKeys.Select(key => cornerVerts[key]).ToArray());
                        }
                    }
                }
            }
        }

        construct("100",
                  new[] { Key(1, -1, -1), Key(1, 1, -1), Key(1, 1, 1), Key(1, -1, 1) },
                  new IntVector3[0]);
        construct("100",
                  new[] { Key(-1, -1, -1), Key(-1, 1, -1), Key(-1, 1, 1), Key(-1, -1, 1) },
                  new[] { Key(1, -1, -1), Key(1, 1, -1), Key(1, 1, 1), Key(1, -1, 1) });
        construct("110",
                  new[] { Key(-1, 1, -1), Key(-1, 1, 1), Key(1, -1, 1), Key(1, -1, -1) },
                  new[] { Key(1, 1, -1), Key(1, 1, 1) });
        construct("111",
                  new[] { Key(-1, 1, 1), Key(1, -1, 1), Key(1, 1, -1) },
                  new[] { Key(1, 1, 1) });
        construct("111",
                  new[] { Key(1, -1, -1), Key(-1, 1, -1), Key(-1, -1, 1) },
                  new[] { Key(-1, 1, 1), Key(1, -1, 1), Key(1, 1, -1), Key(1, 1, 1) });

        return(geometry);
    }