public override IEnumerator BeginGeneration()
        {
            var surface         = surfaceInputSlot.GetAsset <Surface>();
            var topology        = topologyInputSlot.GetAsset <Topology>();
            var vertexPositions = vertexPositionsInputSlot.source != null?vertexPositionsInputSlot.GetAsset <IVertexAttribute <Vector3> >() : null;

            var random = randomness.GetRandom();

            System.Func <float> relaxIterationFunction = null;
            System.Func <bool>  repairFunction         = null;
            System.Action       relaxationLoopFunction = null;

            if (vertexPositions != null)
            {
                if (surface is QuadrilateralSurface)
                {
                    if (relaxForRegularityWeight >= 1.0f)
                    {
                        var relaxedVertexPositions = new Vector3[topology.vertices.Count].AsVertexAttribute();
                        relaxIterationFunction = () =>
                        {
                            PlanarManifoldUtility.RelaxVertexPositionsForRegularity(topology, vertexPositions, lockBoundaryPositions, relaxedVertexPositions);
                            var relaxationAmount = PlanarManifoldUtility.CalculateRelaxationAmount(vertexPositions, relaxedVertexPositions);
                            for (int i = 0; i < vertexPositions.Count; ++i)
                            {
                                vertexPositions[i] = relaxedVertexPositions[i];
                            }
                            return(relaxationAmount);
                        };
                    }
                    else if (relaxForRegularityWeight <= 0.0f)
                    {
                        var relaxedVertexPositions = new Vector3[topology.vertices.Count].AsVertexAttribute();
                        var faceCentroids          = PositionalFaceAttribute.Create(surface, topology.internalFaces.Count);
                        var vertexAreas            = new float[topology.vertices.Count].AsVertexAttribute();

                        FaceAttributeUtility.CalculateFaceCentroidsFromVertexPositions(topology.internalFaces, vertexPositions, faceCentroids);
                        VertexAttributeUtility.CalculateVertexAreasFromVertexPositionsAndFaceCentroids(topology.vertices, vertexPositions, faceCentroids, vertexAreas);

                        var totalArea = 0f;
                        foreach (var vertexArea in vertexAreas)
                        {
                            totalArea += vertexArea;
                        }

                        relaxIterationFunction = () =>
                        {
                            PlanarManifoldUtility.RelaxVertexPositionsForEqualArea(topology, vertexPositions, totalArea, lockBoundaryPositions, relaxedVertexPositions, faceCentroids, vertexAreas);
                            var relaxationAmount = PlanarManifoldUtility.CalculateRelaxationAmount(vertexPositions, relaxedVertexPositions);
                            for (int i = 0; i < vertexPositions.Count; ++i)
                            {
                                vertexPositions[i] = relaxedVertexPositions[i];
                            }
                            return(relaxationAmount);
                        };
                    }
                    else
                    {
                        var regularityWeight = Mathf.Clamp01(relaxForRegularityWeight);
                        var equalAreaWeight  = 1f - regularityWeight;

                        var regularityRelaxedVertexPositions = new Vector3[topology.vertices.Count].AsVertexAttribute();
                        var equalAreaRelaxedVertexPositions  = new Vector3[topology.vertices.Count].AsVertexAttribute();
                        var relaxedVertexPositions           = regularityRelaxedVertexPositions;
                        var faceCentroids = PositionalFaceAttribute.Create(surface, topology.internalFaces.Count);
                        var vertexAreas   = new float[topology.vertices.Count].AsVertexAttribute();

                        FaceAttributeUtility.CalculateFaceCentroidsFromVertexPositions(topology.internalFaces, vertexPositions, faceCentroids);
                        VertexAttributeUtility.CalculateVertexAreasFromVertexPositionsAndFaceCentroids(topology.vertices, vertexPositions, faceCentroids, vertexAreas);

                        var totalArea = 0f;
                        foreach (var vertexArea in vertexAreas)
                        {
                            totalArea += vertexArea;
                        }

                        relaxIterationFunction = () =>
                        {
                            PlanarManifoldUtility.RelaxVertexPositionsForRegularity(topology, vertexPositions, lockBoundaryPositions, regularityRelaxedVertexPositions);
                            PlanarManifoldUtility.RelaxVertexPositionsForEqualArea(topology, vertexPositions, totalArea, lockBoundaryPositions, equalAreaRelaxedVertexPositions, faceCentroids, vertexAreas);
                            for (int i = 0; i < relaxedVertexPositions.Count; ++i)
                            {
                                relaxedVertexPositions[i] = regularityRelaxedVertexPositions[i] * regularityWeight + equalAreaRelaxedVertexPositions[i] * equalAreaWeight;
                            }
                            var relaxationAmount = PlanarManifoldUtility.CalculateRelaxationAmount(vertexPositions, relaxedVertexPositions);
                            for (int i = 0; i < vertexPositions.Count; ++i)
                            {
                                vertexPositions[i] = relaxedVertexPositions[i];
                            }
                            return(relaxationAmount);
                        };
                    }

                    repairFunction = () =>
                    {
                        return(PlanarManifoldUtility.ValidateAndRepair(topology, ((QuadrilateralSurface)surface).normal, vertexPositions, repairRate, lockBoundaryPositions));
                    };

                    relaxationLoopFunction = TopologyRandomizer.CreateRelaxationLoopFunction(maxRelaxIterations, maxRepairIterations, relaxRelativePrecision, relaxIterationFunction, repairFunction);
                }
                else if (surface is SphericalSurface)
                {
                    var sphericalSurface = (SphericalSurface)surface;
                    if (relaxForRegularityWeight >= 1.0f)
                    {
                        var relaxedVertexPositions = new Vector3[topology.vertices.Count].AsVertexAttribute();
                        relaxIterationFunction = () =>
                        {
                            SphericalManifoldUtility.RelaxVertexPositionsForRegularity(sphericalSurface, topology, vertexPositions, lockBoundaryPositions, relaxedVertexPositions);
                            var relaxationAmount = SphericalManifoldUtility.CalculateRelaxationAmount(vertexPositions, relaxedVertexPositions);
                            for (int i = 0; i < vertexPositions.Count; ++i)
                            {
                                vertexPositions[i] = relaxedVertexPositions[i];
                            }
                            return(relaxationAmount);
                        };
                    }
                    else if (relaxForRegularityWeight <= 0.0f)
                    {
                        var relaxedVertexPositions = new Vector3[topology.vertices.Count].AsVertexAttribute();
                        var faceCentroids          = PositionalFaceAttribute.Create(surface, topology.internalFaces.Count);
                        var faceCentroidAngles     = new float[topology.faceEdges.Count].AsEdgeAttribute();
                        var vertexAreas            = new float[topology.vertices.Count].AsVertexAttribute();
                        relaxIterationFunction = () =>
                        {
                            SphericalManifoldUtility.RelaxVertexPositionsForEqualArea(sphericalSurface, topology, vertexPositions, lockBoundaryPositions, relaxedVertexPositions, faceCentroids, faceCentroidAngles, vertexAreas);
                            var relaxationAmount = SphericalManifoldUtility.CalculateRelaxationAmount(vertexPositions, relaxedVertexPositions);
                            for (int i = 0; i < vertexPositions.Count; ++i)
                            {
                                vertexPositions[i] = relaxedVertexPositions[i];
                            }
                            return(relaxationAmount);
                        };
                    }
                    else
                    {
                        var regularityWeight = Mathf.Clamp01(relaxForRegularityWeight);
                        var equalAreaWeight  = 1f - regularityWeight;

                        var regularityRelaxedVertexPositions = new Vector3[topology.vertices.Count].AsVertexAttribute();
                        var equalAreaRelaxedVertexPositions  = new Vector3[topology.vertices.Count].AsVertexAttribute();
                        var relaxedVertexPositions           = regularityRelaxedVertexPositions;
                        var faceCentroids      = PositionalFaceAttribute.Create(surface, topology.internalFaces.Count);
                        var faceCentroidAngles = new float[topology.faceEdges.Count].AsEdgeAttribute();
                        var vertexAreas        = new float[topology.vertices.Count].AsVertexAttribute();
                        relaxIterationFunction = () =>
                        {
                            SphericalManifoldUtility.RelaxVertexPositionsForRegularity(sphericalSurface, topology, vertexPositions, lockBoundaryPositions, regularityRelaxedVertexPositions);
                            SphericalManifoldUtility.RelaxVertexPositionsForEqualArea(sphericalSurface, topology, vertexPositions, lockBoundaryPositions, equalAreaRelaxedVertexPositions, faceCentroids, faceCentroidAngles, vertexAreas);
                            for (int i = 0; i < relaxedVertexPositions.Count; ++i)
                            {
                                relaxedVertexPositions[i] = regularityRelaxedVertexPositions[i] * regularityWeight + equalAreaRelaxedVertexPositions[i] * equalAreaWeight;
                            }
                            var relaxationAmount = SphericalManifoldUtility.CalculateRelaxationAmount(vertexPositions, relaxedVertexPositions);
                            for (int i = 0; i < vertexPositions.Count; ++i)
                            {
                                vertexPositions[i] = relaxedVertexPositions[i];
                            }
                            return(relaxationAmount);
                        };
                    }

                    repairFunction = () =>
                    {
                        return(SphericalManifoldUtility.ValidateAndRepair(sphericalSurface, topology, vertexPositions, repairRate, lockBoundaryPositions));
                    };

                    relaxationLoopFunction = TopologyRandomizer.CreateRelaxationLoopFunction(maxRelaxIterations, maxRepairIterations, relaxRelativePrecision, relaxIterationFunction, repairFunction);
                }
            }

            yield return(executive.GenerateConcurrently(() =>
            {
                TopologyRandomizer.Randomize(topology, passCount, frequency,
                                             minVertexNeighbors, maxVertexNeighbors, minFaceNeighbors, maxFaceNeighbors,
                                             lockBoundaryPositions, random, relaxationLoopFunction);
            }));

            EditorUtility.SetDirty(topology);

            if (vertexPositions != null)
            {
                EditorUtility.SetDirty((Object)vertexPositions);
            }

            yield break;
        }
Esempio n. 2
0
        public override IEnumerator BeginGeneration()
        {
            var surface = surfaceOutputSlot.GetAsset <SphericalSurface>();

            if (surface == null)
            {
                surface = surfaceOutputSlot.SetAsset(CreateInstance <SphericalSurface>(), false);
            }
            surface.Reset(primaryPole, equatorialPole, radius, isInverted);

            Topology topology;

            Vector3[] vertexPositions;

            switch (sphericalPolyhedron)
            {
            case SphericalPolyhedrons.Tetrahedron:
                SphericalManifoldUtility.CreateTetrahedron(surface, out topology, out vertexPositions);
                break;

            case SphericalPolyhedrons.Cube:
                SphericalManifoldUtility.CreateCube(surface, out topology, out vertexPositions);
                break;

            case SphericalPolyhedrons.Octahedron:
                SphericalManifoldUtility.CreateOctahedron(surface, out topology, out vertexPositions);
                break;

            case SphericalPolyhedrons.Dodecahedron:
                if (subdivisionDegree == 0)
                {
                    SphericalManifoldUtility.CreateDodecahedron(surface, out topology, out vertexPositions);
                }
                else
                {
                    SphericalManifoldUtility.CreateIcosahedron(surface, out topology, out vertexPositions);
                }
                break;

            case SphericalPolyhedrons.Icosahedron:
                SphericalManifoldUtility.CreateIcosahedron(surface, out topology, out vertexPositions);
                break;

            default:
                throw new System.NotImplementedException();
            }

            SphericalManifoldUtility.Subdivide(surface, topology, vertexPositions.AsVertexAttribute(), subdivisionDegree, out topology, out vertexPositions);

            var alreadyDual = sphericalPolyhedron == SphericalPolyhedrons.Dodecahedron && subdivisionDegree != 0;

            if (useDualPolyhedron != alreadyDual)
            {
                SphericalManifoldUtility.MakeDual(surface, topology, ref vertexPositions);
            }

            surfaceOutputSlot.Persist();
            topologyOutputSlot.SetAsset(topology);
            vertexPositionsOutputSlot.SetAsset(Vector3VertexAttribute.Create(vertexPositions).SetName("Vertex Positions"));

            yield break;
        }