Esempio n. 1
0
        protected void Start()
        {
            var hexGridSurface = RectangularHexGrid.Create(
                HexGridDescriptor.CreateSideUp(true, HexGridAxisStyles.StaggeredSymmetric),
                Vector3.zero, Quaternion.Euler(90f, 0f, 0f),
                false, false,
                new IntVector2(topologyWidth, topologyHeight));

            _surface = hexGridSurface;

            Vector3[] vertexPositionsArray;
            _topology            = hexGridSurface.CreateManifold(out vertexPositionsArray);
            _vertexPositions     = vertexPositionsArray.AsVertexAttribute();
            _facePositions       = FaceAttributeUtility.CalculateFaceCentroidsFromVertexPositions(_topology.internalFaces, _vertexPositions);
            _faceCornerBisectors = EdgeAttributeUtility.CalculateFaceEdgeBisectorsFromVertexPositions(_topology.internalFaces, _vertexPositions, _facePositions);
            _faceBlockedStates   = new bool[_topology.internalFaces.Count].AsFaceAttribute();

            var triangulation = new SeparatedFacesUmbrellaTriangulation(2,
                                                                        (Topology.FaceEdge edge, DynamicMesh.IIndexedVertexAttributes vertexAttributes) =>
            {
                vertexAttributes.position = _vertexPositions[edge];
                vertexAttributes.normal   = Vector3.up;
                vertexAttributes.color    = borderColor;
                vertexAttributes.Advance();

                vertexAttributes.position = _vertexPositions[edge] + _faceCornerBisectors[edge] * 0.05f;
                vertexAttributes.normal   = (vertexAttributes.position + Vector3.up - _facePositions[edge.nearFace]).normalized;
                vertexAttributes.color    = normalColor;
                vertexAttributes.Advance();
            },
                                                                        (Topology.Face face, DynamicMesh.IIndexedVertexAttributes vertexAttributes) =>
            {
                vertexAttributes.position = _facePositions[face];
                vertexAttributes.normal   = Vector3.up;
                vertexAttributes.color    = normalColor;
                vertexAttributes.Advance();
            });

            _dynamicMesh = DynamicMesh.Create(
                _topology.enumerableInternalFaces,
                DynamicMesh.VertexAttributes.Position |
                DynamicMesh.VertexAttributes.Normal |
                DynamicMesh.VertexAttributes.Color,
                triangulation);

            foreach (var mesh in _dynamicMesh.submeshes)
            {
                var meshFilter = Instantiate(submeshPrefab);
                meshFilter.mesh = mesh;
                meshFilter.transform.SetParent(transform, false);
            }

            var partioning = UniversalFaceSpatialPartitioning.Create(_surface, _topology, _vertexPositions);
            var picker     = GetComponent <FaceSpatialPartitioningPicker>();

            picker.partitioning = partioning;
        }
 public void CreateIcosahedron(float radius)
 {
     surface = SphericalSurface.Create(Vector3.up, Vector3.right, radius);
     Vector3[] vertexPositionsArray;
     SphericalManifoldUtility.CreateIcosahedron((SphericalSurface)surface, out topology, out vertexPositionsArray);
     vertexPositions = vertexPositionsArray.AsVertexAttribute();
     facePositions   = FaceAttributeUtility.CalculateFaceCentroidsFromVertexPositions(topology.internalFaces, vertexPositions);
     partitioning    = UniversalFaceSpatialPartitioning.Create(surface, topology, vertexPositions);
 }
 public void CreateHexGrid(int width, int height)
 {
     surface = RectangularHexGrid.Create(HexGridDescriptor.standardCornerUp, Vector3.zero, Quaternion.identity, false, false, new IntVector2(width, height));
     Vector3[] vertexPositionsArray;
     topology        = ((RectangularHexGrid)surface).CreateManifold(out vertexPositionsArray);
     vertexPositions = vertexPositionsArray.AsVertexAttribute();
     facePositions   = FaceAttributeUtility.CalculateFaceCentroidsFromVertexPositions(topology.internalFaces, vertexPositions);
     partitioning    = UniversalFaceSpatialPartitioning.Create(surface, topology, vertexPositions);
 }
        public void CreateDistortedQuadGrid(int width, int height, int seed)
        {
            var quadGrid = RectangularQuadGrid.Create(Vector2.right, Vector2.up, Vector3.zero, Quaternion.identity, false, false, new IntVector2(width, height));

            surface = quadGrid;
            Vector3[] vertexPositionsArray;
            topology        = quadGrid.CreateManifold(out vertexPositionsArray);
            vertexPositions = vertexPositionsArray.AsVertexAttribute();
            var random          = XorShift128Plus.Create(seed);
            var maxOffsetRadius = Mathf.Sqrt(2f) / 5f;

            for (int y = 1; y < height; ++y)
            {
                for (int x = 1; x < width; ++x)
                {
                    vertexPositions[quadGrid.GetVertexIndex(x, y)] += (Vector3)random.PointWithinCircle(maxOffsetRadius);
                }
            }
            facePositions = FaceAttributeUtility.CalculateFaceCentroidsFromVertexPositions(topology.internalFaces, vertexPositions);
            partitioning  = UniversalFaceSpatialPartitioning.Create(surface, topology, vertexPositions);
        }
        public void CreateDistortedHexGrid(int width, int height, int seed)
        {
            var hexGrid = RectangularHexGrid.Create(HexGridDescriptor.standardCornerUp, Vector3.zero, Quaternion.identity, false, false, new IntVector2(width, height));

            surface = hexGrid;
            Vector3[] vertexPositionsArray;
            topology        = hexGrid.CreateManifold(out vertexPositionsArray);
            vertexPositions = vertexPositionsArray.AsVertexAttribute();
            var random          = XorShift128Plus.Create(seed);
            var maxOffsetRadius = Mathf.Sqrt(3f) / 8f;

            foreach (var vertex in topology.vertices)
            {
                if (!vertex.hasExternalFaceNeighbor)
                {
                    vertexPositions[vertex] += (Vector3)random.PointWithinCircle(maxOffsetRadius);
                }
            }
            facePositions = FaceAttributeUtility.CalculateFaceCentroidsFromVertexPositions(topology.internalFaces, vertexPositions);
            partitioning  = UniversalFaceSpatialPartitioning.Create(surface, topology, vertexPositions);
        }
Esempio n. 6
0
        private void DestroyOldGame()
        {
            if (_surface == null)
            {
                return;
            }

            var existingMeshCount = gameBoardMeshes.childCount;

            for (int i = 0; i < existingMeshCount; ++i)
            {
                Destroy(gameBoardMeshes.GetChild(i).gameObject);
            }

            foreach (var face in _topology.internalFaces)
            {
                if (_facePieces[face] != null)
                {
                    Destroy(_facePieces[face].gameObject);
                }
            }

            _surface             = null;
            _topology            = null;
            _vertexPositions     = null;
            _facePositions       = null;
            _innerAngleBisectors = null;
            _facePieces          = null;
            _faceBoardStates     = null;
            _partitioning        = null;
            _dynamicMesh         = null;

            _picker.partitioning = null;
            _picker.enabled      = false;

            _gameActive = false;
        }
Esempio n. 7
0
        /// <summary>
        /// Calculates vertex normals based on the positions of their neighboring faces.
        /// </summary>
        /// <param name="vertices">The collection of vertices whose normals are to be calculated.</param>
        /// <param name="facePositions">The positions of the faces.</param>
        /// <param name="vertexNormals">A pre-allocated collection in which the vertex normals will be stored.</param>
        /// <returns>The surface normals of the vertices.</returns>
        public static IVertexAttribute <Vector3> CalculateVertexNormalsFromFacePositions(Topology.VerticesIndexer vertices, IFaceAttribute <Vector3> facePositions, IVertexAttribute <Vector3> vertexNormals)
        {
            foreach (var vertex in vertices)
            {
                var normalSum = new Vector3(0f, 0f, 0f);

                var edge = vertex.firstEdge;
                var p0   = facePositions[edge];
                edge = edge.next;
                var p1 = facePositions[edge];
                edge = edge.next;
                var firstEdge = edge;
                do
                {
                    var p2 = facePositions[edge];
                    normalSum += Vector3.Cross(p0 - p1, p2 - p1);
                    edge       = edge.next;
                } while (edge != firstEdge);

                vertexNormals[vertex] = normalSum.normalized;
            }

            return(vertexNormals);
        }
Esempio n. 8
0
        public void StartNewGame()
        {
            DestroyOldGame();

            Vector3[] vertexPositionsArray;

            if (squaresToggle.isOn)
            {
                IntVector2 boardSize;
                if (smallToggle.isOn)
                {
                    boardSize = new IntVector2(9, 9);
                }
                else if (mediumToggle.isOn)
                {
                    boardSize = new IntVector2(13, 13);
                }
                else
                {
                    boardSize = new IntVector2(19, 19);
                }
                _surface         = RectangularQuadGrid.Create(Vector2.right, Vector2.up, Vector3.zero, Quaternion.identity, false, false, boardSize);
                _topology        = ((RectangularQuadGrid)_surface).CreateManifold(out vertexPositionsArray);
                _vertexPositions = PositionalVertexAttribute.Create(_surface, vertexPositionsArray);
            }
            else if (hexesToggle.isOn)
            {
                IntVector2 boardSize;
                if (smallToggle.isOn)
                {
                    boardSize = new IntVector2(9, 9);
                }
                else if (mediumToggle.isOn)
                {
                    boardSize = new IntVector2(13, 13);
                }
                else
                {
                    boardSize = new IntVector2(19, 19);
                }
                _surface = RectangularHexGrid.Create(
                    HexGridDescriptor.CreateCornerUp(true, HexGridAxisStyles.StaggeredSymmetric),
                    Vector3.zero, Quaternion.identity,
                    false, false,
                    boardSize);
                _topology        = ((RectangularHexGrid)_surface).CreateManifold(out vertexPositionsArray);
                _vertexPositions = PositionalVertexAttribute.Create(_surface, vertexPositionsArray);
            }
            else
            {
                IntVector2 boardSize;
                if (smallToggle.isOn)
                {
                    boardSize = new IntVector2(9, 9);
                }
                else if (mediumToggle.isOn)
                {
                    boardSize = new IntVector2(13, 13);
                }
                else
                {
                    boardSize = new IntVector2(19, 19);
                }
                _surface = RectangularHexGrid.Create(
                    HexGridDescriptor.CreateCornerUp(true, HexGridAxisStyles.StaggeredSymmetric),
                    Vector3.zero, Quaternion.identity,
                    false, false,
                    boardSize);
                _topology        = ((RectangularHexGrid)_surface).CreateManifold(out vertexPositionsArray);
                _vertexPositions = PositionalVertexAttribute.Create(_surface, vertexPositionsArray);

                var regularityWeight = 0.5f;
                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;
                }

                Func <float> relaxIterationFunction = () =>
                {
                    PlanarManifoldUtility.RelaxVertexPositionsForRegularity(_topology, _vertexPositions, true, regularityRelaxedVertexPositions);
                    PlanarManifoldUtility.RelaxVertexPositionsForEqualArea(_topology, _vertexPositions, totalArea, true, 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);
                };

                Func <bool> repairFunction = () =>
                {
                    return(PlanarManifoldUtility.ValidateAndRepair(_topology, _surface.normal, _vertexPositions, 0.5f, true));
                };

                Action relaxationLoopFunction = TopologyRandomizer.CreateRelaxationLoopFunction(20, 20, 0.95f, relaxIterationFunction, repairFunction);

                TopologyRandomizer.Randomize(
                    _topology, 1, 0.1f,
                    3, 3, 5, 7, true,
                    _random,
                    relaxationLoopFunction);
            }

            _facePositions = PositionalFaceAttribute.Create(_surface, _topology.internalFaces.Count);
            FaceAttributeUtility.CalculateFaceCentroidsFromVertexPositions(_topology.internalFaces, _vertexPositions, _facePositions);

            _innerAngleBisectors = EdgeAttributeUtility.CalculateFaceEdgeBisectorsFromVertexPositions(_topology.internalFaces, PlanarSurface.Create(Vector3.zero, Quaternion.identity), _vertexPositions);

            _faceBoardStates = new BoardState[_topology.internalFaces.Count].AsFaceAttribute();

            foreach (var face in _topology.internalFaces)
            {
                _faceBoardStates[face] = BoardState.Empty;
            }

            _facePieces = new Transform[_topology.internalFaces.Count].AsFaceAttribute();

            _partitioning        = UniversalFaceSpatialPartitioning.Create(_surface, _topology, _vertexPositions);
            _picker.partitioning = _partitioning;
            _picker.enabled      = true;

            var centerVertexNormal = _surface.normal.normalized;

            var triangulation = new SeparatedFacesUmbrellaTriangulation(2,
                                                                        (Topology.FaceEdge edge, DynamicMesh.IIndexedVertexAttributes vertexAttributes) =>
            {
                vertexAttributes.position = _vertexPositions[edge];
                vertexAttributes.normal   = (_vertexPositions[edge] + _surface.normal * 5f - _facePositions[edge.nearFace]).normalized;
                vertexAttributes.uv       = new Vector2(0.25f, 0f);
                vertexAttributes.Advance();

                vertexAttributes.position = _vertexPositions[edge] + _innerAngleBisectors[edge] * 0.05f;
                vertexAttributes.normal   = (vertexAttributes.position + _surface.normal * 5f - _facePositions[edge.nearFace]).normalized;
                vertexAttributes.uv       = new Vector2(0.25f, 0.5f);
                vertexAttributes.Advance();
            },
                                                                        (Topology.Face face, DynamicMesh.IIndexedVertexAttributes vertexAttributes) =>
            {
                vertexAttributes.position = _facePositions[face];
                vertexAttributes.normal   = centerVertexNormal;
                vertexAttributes.uv       = new Vector2(0.25f, 1f);
                vertexAttributes.Advance();
            });

            _dynamicMesh = DynamicMesh.Create(
                _topology.enumerableInternalFaces,
                DynamicMesh.VertexAttributes.Position |
                DynamicMesh.VertexAttributes.Normal |
                DynamicMesh.VertexAttributes.UV,
                triangulation);

            foreach (var mesh in _dynamicMesh.submeshes)
            {
                var meshObject = Instantiate(meshFilterRendererPrefab);
                meshObject.mesh = mesh;
                meshObject.transform.SetParent(gameBoardMeshes);
            }

            _gameBoardBounds = new Bounds(Vector3.zero, Vector3.zero);
            foreach (var vertex in _topology.vertices)
            {
                _gameBoardBounds.Encapsulate(_vertexPositions[vertex]);
            }

            AdjustCamera();

            var pickerCollider = GetComponent <BoxCollider>();

            pickerCollider.center = _gameBoardBounds.center;
            pickerCollider.size   = _gameBoardBounds.size;

            _whiteCount = 0;
            _blackCount = 0;
            _moveCount  = 0;

            whiteCountText.text = _whiteCount.ToString();
            blackCountText.text = _blackCount.ToString();

            _gameActive = true;
            _turn       = BoardState.Black;
        }
Esempio n. 9
0
        /// <summary>
        /// Calculates vertex normals based on the surface normals of their neighboring faces.
        /// </summary>
        /// <param name="vertices">The collection of vertices whose normals are to be calculated.</param>
        /// <param name="faceNormals">The surface normals of the faces.</param>
        /// <param name="vertexNormals">A pre-allocated collection in which the vertex normals will be stored.</param>
        /// <returns>The surface normals of the vertices.</returns>
        public static IVertexAttribute <Vector3> CalculateVertexNormalsFromFaceNormals(Topology.VerticesIndexer vertices, IFaceAttribute <Vector3> faceNormals, IVertexAttribute <Vector3> vertexNormals)
        {
            foreach (var vertex in vertices)
            {
                var normalSum = new Vector3(0f, 0f, 0f);

                foreach (var edge in vertex.edges)
                {
                    normalSum += faceNormals[edge];
                }

                vertexNormals[vertex] = normalSum.normalized;
            }

            return(vertexNormals);
        }
Esempio n. 10
0
 /// <summary>
 /// Calculates vertex normals based on the surface normals of their neighboring faces.
 /// </summary>
 /// <param name="vertices">The collection of vertices whose normals are to be calculated.</param>
 /// <param name="faceNormals">The surface normals of the faces.</param>
 /// <returns>The surface normals of the vertices.</returns>
 public static IVertexAttribute <Vector3> CalculateVertexNormalsFromFaceNormals(Topology.VerticesIndexer vertices, IFaceAttribute <Vector3> faceNormals)
 {
     return(CalculateVertexNormalsFromFaceNormals(vertices, faceNormals, new Vector3[vertices.Count].AsVertexAttribute()));
 }
Esempio n. 11
0
        /// <summary>
        /// Attempts to move the positions of vertices such that they have roughly uniform density, with a bias towards also making sure that the surface areas of the faces also become more uniform.
        /// </summary>
        /// <param name="topology">The topology to relax.</param>
        /// <param name="vertexPositions">The original positions of the vertices to relax.</param>
        /// <param name="totalArea">The total surface area of the internal faces of the topology.</param>
        /// <param name="lockBoundaryPositions">Indicates that vertices with an external neighboring face should not have their positions altered.</param>
        /// <param name="relaxedVertexPositions">A pre-allocated collection in which the relaxed vertex positions will be stored.  Should not be the same collection as <paramref name="vertexPositions"/>.</param>
        /// <param name="faceCentroids">A pre-allocated collection in which the intermediate face centroid positions will be stored.</param>
        /// <param name="vertexAreas">A pre-allocated collection in which the intermediate nearby surface areas of vertices will be stored.</param>
        /// <returns>The relaxed vertex positions.</returns>
        public static IVertexAttribute <Vector3> RelaxVertexPositionsForEqualArea(Topology topology, IVertexAttribute <Vector3> vertexPositions, float totalArea, bool lockBoundaryPositions, IVertexAttribute <Vector3> relaxedVertexPositions, IFaceAttribute <Vector3> faceCentroids, IVertexAttribute <float> vertexAreas)
        {
            var idealArea = totalArea / topology.vertices.Count;

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

            for (int i = 0; i < topology.vertices.Count; ++i)
            {
                relaxedVertexPositions[i] = new Vector3(0f, 0f, 0f);
            }

            foreach (var vertex in topology.vertices)
            {
                var multiplier = Mathf.Sqrt(idealArea / vertexAreas[vertex]);
                foreach (var edge in vertex.edges)
                {
                    var neighborVertex         = edge.vertex;
                    var neighborRelativeCenter = vertexPositions[edge.twin];
                    relaxedVertexPositions[neighborVertex] += (vertexPositions[neighborVertex] - neighborRelativeCenter) * multiplier + neighborRelativeCenter;
                }
            }

            foreach (var vertex in topology.vertices)
            {
                if (!lockBoundaryPositions || !vertex.hasExternalFaceNeighbor)
                {
                    relaxedVertexPositions[vertex] /= vertex.neighborCount;
                }
                else
                {
                    relaxedVertexPositions[vertex] = vertexPositions[vertex];
                }
            }

            return(relaxedVertexPositions);
        }
Esempio n. 12
0
        private void CreateGrid(out Topology topology, out IVertexAttribute <Vector3> vertexPositions, out IFaceAttribute <Vector3> facePositions)
        {
            if (squareGridToggle.isOn)
            {
                CreateSquareGrid(out topology, out vertexPositions);
            }
            else if (hexGrid1Toggle.isOn)
            {
                CreateHexGrid1(out topology, out vertexPositions);
            }
            else if (hexGrid2Toggle.isOn)
            {
                CreateHexGrid2(out topology, out vertexPositions);
            }
            else
            {
                CreateJumbledGrid(out topology, out vertexPositions);
            }

            _topology        = topology;
            _vertexPositions = vertexPositions;

            facePositions = FaceAttributeUtility.CalculateFaceCentroidsFromVertexPositions(topology.internalFaces, vertexPositions);
        }
Esempio n. 13
0
        protected void Start()
        {
            orbitalCamera.enabled = !isInverted;
            pivotalCamera.enabled = isInverted;

            exteriorLight.enabled = !isInverted;
            interiorLight.enabled = isInverted;

            _lightVector = (isInverted ? interiorLight : exteriorLight).transform.position;
            _lightAxis   = Vector3.Cross(Vector3.Cross(Vector3.up, _lightVector), _lightVector);

            RenderSettings.ambientLight          = new Color(0.3f, 0.4f, 0.5f);
            RenderSettings.ambientIntensity      = 0.25f;
            RenderSettings.customReflection      = whiteCubeMap;
            RenderSettings.reflectionIntensity   = 0.125f;
            RenderSettings.defaultReflectionMode = UnityEngine.Rendering.DefaultReflectionMode.Custom;

            _picker = GetComponent <FaceSpatialPartitioningPicker>();

            _surface = SphericalSurface.Create(Vector3.up, Vector3.right, 10f, isInverted);
            Vector3[] baseVertexPositionsArray;
            Topology  baseTopology;

            SphericalManifoldUtility.CreateIcosahedron(_surface, out baseTopology, out baseVertexPositionsArray);

            Vector3[] vertexPositionsArray;
            SphericalManifoldUtility.Subdivide(_surface, baseTopology, baseVertexPositionsArray.AsVertexAttribute(), topologySubdivision, out _topology, out vertexPositionsArray);

            _vertexPositions = PositionalVertexAttribute.Create(_surface, vertexPositionsArray);

            SphericalManifoldUtility.MakeDual(_surface, _topology, _vertexPositions, out vertexPositionsArray);
            _vertexPositions = PositionalVertexAttribute.Create(_surface, vertexPositionsArray);

            var regularityWeight = 0.5f;
            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();

            FaceAttributeUtility.CalculateFaceCentroidsFromVertexPositions(_topology.internalFaces, _vertexPositions, faceCentroids);
            VertexAttributeUtility.CalculateVertexAreasFromVertexPositionsAndFaceCentroids(_topology.vertices, _vertexPositions, faceCentroids, vertexAreas);

            Func <float> relaxIterationFunction = () =>
            {
                SphericalManifoldUtility.RelaxVertexPositionsForRegularity(_surface, _topology, _vertexPositions, true, regularityRelaxedVertexPositions);
                SphericalManifoldUtility.RelaxVertexPositionsForEqualArea(_surface, _topology, _vertexPositions, true, 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);
            };

            Func <bool> repairFunction = () =>
            {
                return(SphericalManifoldUtility.ValidateAndRepair(_surface, _topology, _vertexPositions, 0.5f, true));
            };

            Action relaxationLoopFunction = TopologyRandomizer.CreateRelaxationLoopFunction(20, 20, 0.95f, relaxIterationFunction, repairFunction);

            TopologyRandomizer.Randomize(
                _topology, 1, 0.1f,
                3, 3, 5, 7, true,
                _random,
                relaxationLoopFunction);

            _facePositions = PositionalFaceAttribute.Create(_surface, _topology.internalFaces.Count);
            FaceAttributeUtility.CalculateFaceCentroidsFromVertexPositions(_topology.internalFaces, _vertexPositions, _facePositions);

            _maximumFaceDistance = 0f;
            foreach (var edge in _topology.faceEdges)
            {
                var distance = Geometry.AngleBetweenVectors(_facePositions[edge.nearFace], _facePositions[edge.farFace]) * _surface.radius;
                _maximumFaceDistance = Mathf.Max(_maximumFaceDistance, distance);
            }

            _innerAngleBisectors = EdgeAttributeUtility.CalculateFaceEdgeBisectorsFromVertexPositions(_topology.internalFaces, _vertexPositions, _facePositions);

            _innerVertexPositions = new Vector3[_topology.faceEdges.Count].AsEdgeAttribute();
            foreach (var edge in _topology.faceEdges)
            {
                _innerVertexPositions[edge] = _vertexPositions[edge] + _innerAngleBisectors[edge] * 0.03f;
            }

            _faceNormals      = FaceAttributeUtility.CalculateFaceNormalsFromSurface(_topology.faces, _surface, _facePositions);
            _faceUVFrames     = FaceAttributeUtility.CalculatePerFaceSphericalUVFramesFromFaceNormals(_topology.faces, _faceNormals, Quaternion.identity);
            _faceOuterEdgeUVs = EdgeAttributeUtility.CalculatePerFaceUnnormalizedUVsFromVertexPositions(_topology.faces, _vertexPositions, _faceUVFrames);
            _faceInnerEdgeUVs = EdgeAttributeUtility.CalculatePerFaceUnnormalizedUVsFromVertexPositions(_topology.faces, _innerVertexPositions, _faceUVFrames);
            _faceCenterUVs    = FaceAttributeUtility.CalculateUnnormalizedUVsFromFacePositions(_topology.faces, _facePositions, _faceUVFrames);

            var faceMinUVs   = new Vector2[_topology.faces.Count].AsFaceAttribute();
            var faceRangeUVs = new Vector2[_topology.faces.Count].AsFaceAttribute();

            FaceAttributeUtility.CalculateFaceEdgeMinAndRangeValues(_topology.faces, _faceOuterEdgeUVs, faceMinUVs, faceRangeUVs);

            foreach (var face in _topology.faces)
            {
                var uvMin    = faceMinUVs[face];
                var uvRange  = faceRangeUVs[face];
                var adjusted = AspectRatioUtility.Expand(new Rect(uvMin.x, uvMin.y, uvRange.x, uvRange.y), 1f);
                faceMinUVs[face]   = adjusted.min;
                faceRangeUVs[face] = adjusted.size;
            }

            _faceOuterEdgeUVs = EdgeAttributeUtility.CalculatePerFaceUniformlyNormalizedUVsFromFaceUVMinAndRange(_topology.faces, faceMinUVs, faceRangeUVs, _faceOuterEdgeUVs);
            _faceInnerEdgeUVs = EdgeAttributeUtility.CalculatePerFaceUniformlyNormalizedUVsFromFaceUVMinAndRange(_topology.faces, faceMinUVs, faceRangeUVs, _faceInnerEdgeUVs);
            _faceCenterUVs    = FaceAttributeUtility.CalculateUniformlyNormalizedUVsFromFaceUVMinAndRange(_topology.faces, faceMinUVs, faceRangeUVs, _faceCenterUVs);

            _partitioning        = UniversalFaceSpatialPartitioning.Create(_surface, _topology, _vertexPositions);
            _picker.partitioning = _partitioning;
            _picker.enabled      = true;

            _faceTerrainIndices = new int[_topology.faces.Count].AsFaceAttribute();
            var terrainWeights   = new int[] { grassWeight, waterWeight, desertWeight, mountainWeight };
            int terrainWeightSum = 0;

            foreach (var weight in terrainWeights)
            {
                terrainWeightSum += weight;
            }

            var rootFaces     = new List <Topology.Face>();
            var rootFaceEdges = new List <Topology.FaceEdge>();

            for (int regionIndex = 0; regionIndex < geographicalRegionCount; ++regionIndex)
            {
                Topology.Face face;
                do
                {
                    face = _topology.internalFaces[_random.Index(_topology.internalFaces.Count)];
                } while (rootFaces.Contains(face));
                rootFaces.Add(face);
                foreach (var edge in face.edges)
                {
                    rootFaceEdges.Add(edge);
                }
                _faceTerrainIndices[face] = _random.WeightedIndex(terrainWeights, terrainWeightSum);
            }

            TopologyVisitor.VisitFacesInRandomOrder(rootFaceEdges, (FaceEdgeVisitor visitor) =>
            {
                _faceTerrainIndices[visitor.edge.farFace] = _faceTerrainIndices[visitor.edge.nearFace];

                visitor.VisitInternalNeighborsExceptSource();
            },
                                                    _random);

            _faceSeenStates  = new bool[_topology.faces.Count].AsFaceAttribute();
            _faceSightCounts = new int[_topology.faces.Count].AsFaceAttribute();

            var triangulation = new SeparatedFacesUmbrellaTriangulation(2,
                                                                        (Topology.FaceEdge edge, DynamicMesh.IIndexedVertexAttributes vertexAttributes) =>
            {
                var face         = edge.nearFace;
                var faceNormal   = _faceNormals[face];
                var gridOverlayU = GetGridOverlayU(false, _faceSeenStates[face], _faceSightCounts[face]);

                vertexAttributes.position = _vertexPositions[edge];
                vertexAttributes.normal   = faceNormal;
                vertexAttributes.uv1      = AdjustSurfaceUV(_faceOuterEdgeUVs[edge], _faceTerrainIndices[face]);
                vertexAttributes.uv2      = new Vector2(gridOverlayU, 0f);
                vertexAttributes.Advance();

                vertexAttributes.position = _innerVertexPositions[edge];
                vertexAttributes.normal   = faceNormal;
                vertexAttributes.uv1      = AdjustSurfaceUV(_faceInnerEdgeUVs[edge], _faceTerrainIndices[face]);
                vertexAttributes.uv2      = new Vector2(gridOverlayU, 0.5f);
                vertexAttributes.Advance();
            },
                                                                        (Topology.Face face, DynamicMesh.IIndexedVertexAttributes vertexAttributes) =>
            {
                vertexAttributes.position = _facePositions[face];
                vertexAttributes.normal   = _faceNormals[face];
                vertexAttributes.uv1      = AdjustSurfaceUV(_faceCenterUVs[face], _faceTerrainIndices[face]);
                vertexAttributes.uv2      = new Vector2(GetGridOverlayU(false, _faceSeenStates[face], _faceSightCounts[face]), 1f);
                vertexAttributes.Advance();
            });

            _dynamicMesh = DynamicMesh.Create(
                _topology.enumerableInternalFaces,
                DynamicMesh.VertexAttributes.Position |
                DynamicMesh.VertexAttributes.Normal |
                DynamicMesh.VertexAttributes.UV1 |
                DynamicMesh.VertexAttributes.UV2,
                triangulation);

            foreach (var mesh in _dynamicMesh.submeshes)
            {
                var meshObject = Instantiate(planetMeshPrefab);
                meshObject.mesh = mesh;
                meshObject.transform.SetParent(planetMeshes, false);
            }

            _faceUnits = new Transform[_topology.faces.Count].AsFaceAttribute();
            for (int i = 0; i < unitCount; ++i)
            {
                Topology.Face face;
                do
                {
                    face = _topology.internalFaces[_random.Index(_topology.internalFaces.Count)];
                } while (_faceTerrainIndices[face] == 1 || _faceUnits[face] != null);

                var unit = Instantiate(unitPrefab);
                unit.SetParent(units, false);
                unit.transform.position = _facePositions[face] + _faceNormals[face] * 0.15f;
                _faceUnits[face]        = unit;

                RevealUnitVicinity(face);
            }
            _dynamicMesh.RebuildMesh(DynamicMesh.VertexAttributes.UV2);
        }
Esempio n. 14
0
        /// <summary>
        /// Calculates the planar surface area around each vertex that is closest to that vertex, based on the centroid positions of their neighboring faces.  For non-flat surfaces, the calculated areas are only approximate.
        /// </summary>
        /// <param name="vertices">The collection of vertices whose areas are to be calculated.</param>
        /// <param name="faceCentroids">The centroids of the faces.</param>
        /// <param name="vertexAreas">A pre-allocated collection in which the surrounding surface areas will be stored.</param>
        /// <returns>The surrounding surface areas of the vertices.</returns>
        public static IVertexAttribute <float> CalculatePlanarVertexAreasFromFaceCentroids(Topology.VerticesIndexer vertices, IFaceAttribute <Vector3> faceCentroids, IVertexAttribute <float> vertexAreas)
        {
            foreach (var vertex in vertices)
            {
                if (vertex.neighborCount == 3)
                {
                    var edge = vertex.firstEdge;
                    var p0   = faceCentroids[edge];
                    edge = edge.next;
                    var p1 = faceCentroids[edge];
                    edge = edge.next;
                    var p2 = faceCentroids[edge];
                    vertexAreas[vertex] = Vector3.Cross(p1 - p0, p2 - p0).magnitude * 0.5f;
                }
                else
                {
                    throw new System.NotImplementedException();
                }
            }

            return(vertexAreas);
        }
Esempio n. 15
0
 /// <summary>
 /// Finds the shortest or path from the specified source face to the specified target face,
 /// using the A* algorithm and the supplied face positions to measure standard Euclidean
 /// distance between faces and over face edges.
 /// </summary>
 /// <param name="source">The source face from which the path should start.</param>
 /// <param name="target">The target face that the path should attempt to reach.</param>
 /// <param name="facePositions">The three dimensional positions of each face in the world.</param>
 /// <param name="path">An optional existing path created by an earlier call to one of the <seealso cref="O:MakeIt.Tile.PathFinder.FindPath"/> functions, which will be overwritten with the new path data.</param>
 /// <returns>A face edge path instance describing the path found from source to target, or an incomplete object if no path was found.</returns>
 /// <remarks><para>The optional <paramref name="path"/> parameter is useful for reducing allocation activity
 /// and pressure on the garbage collector.  Reusing an existing path object will not require an additional
 /// allocation to store the path as long as the new path fits inside the capacity already available in the
 /// existing path.</para></remarks>
 public IFaceEdgePath FindEuclideanPath(Topology.Face source, Topology.Face target, IFaceAttribute <Vector3> facePositions, IFaceEdgePath path = null)
 {
     return(FindPath(source, target,
                     (Topology.Face s, Topology.Face t, int pathLength) =>
     {
         return (facePositions[s] - facePositions[t]).magnitude;
     },
                     (Topology.FaceEdge edge, int pathLength) =>
     {
         if (edge.isOuterBoundary)
         {
             return float.PositiveInfinity;
         }
         return (facePositions[edge.nearFace] - facePositions[edge.farFace]).magnitude;
     },
                     path));
 }
Esempio n. 16
0
        /// <summary>
        /// Calculates the surface area around each vertex that is closest to that vertex, based on the positions of the vertices and the centroid positions of their neighboring faces.
        /// </summary>
        /// <param name="vertices">The collection of vertices whose areas are to be calculated.</param>
        /// <param name="vertexPositions">The positions of the vertices.</param>
        /// <param name="faceCentroids">The centroids of the faces.</param>
        /// <param name="vertexAreas">A pre-allocated collection in which the surrounding surface areas will be stored.</param>
        /// <returns>The surrounding surface areas of the vertices.</returns>
        public static IVertexAttribute <float> CalculateVertexAreasFromVertexPositionsAndFaceCentroids(Topology.VerticesIndexer vertices, IVertexAttribute <Vector3> vertexPositions, IFaceAttribute <Vector3> faceCentroids, IVertexAttribute <float> vertexAreas)
        {
            foreach (var vertex in vertices)
            {
                var center      = vertexPositions[vertex];
                var quadAreaSum = 0f;
                var edge        = vertex.firstEdge;
                var v0          = vertexPositions[edge] - center;
                edge = edge.next;
                var firstEdge = edge;
                do
                {
                    var v2 = vertexPositions[edge] - center;
                    if (!edge.isOuterBoundary)
                    {
                        var v1 = faceCentroids[edge] - center;
                        quadAreaSum += Vector3.Cross(v0, v1).magnitude + Vector3.Cross(v1, v2).magnitude;
                    }
                    v0   = v2;
                    edge = edge.next;
                } while (edge != firstEdge);

                vertexAreas[vertex] = quadAreaSum / 4;
            }

            return(vertexAreas);
        }
Esempio n. 17
0
 /// <summary>
 /// Calculates the surface area around each vertex that is closest to that vertex, based on the positions of the vertices and the centroid positions of their neighboring faces.
 /// </summary>
 /// <param name="vertices">The collection of vertices whose areas are to be calculated.</param>
 /// <param name="vertexPositions">The positions of the vertices.</param>
 /// <param name="faceCentroids">The centroids of the faces.</param>
 /// <returns>The surrounding surface areas of the vertices.</returns>
 public static IVertexAttribute <float> CalculateVertexAreasFromVertexPositionsAndFaceCentroids(Topology.VerticesIndexer vertices, IVertexAttribute <Vector3> vertexPositions, IFaceAttribute <Vector3> faceCentroids)
 {
     return(CalculateVertexAreasFromVertexPositionsAndFaceCentroids(vertices, vertexPositions, faceCentroids, new float[vertices.Count].AsVertexAttribute()));
 }
Esempio n. 18
0
 /// <summary>
 /// Finds the shortest or path from the specified source face to the specified target face,
 /// using the A* algorithm and the supplied face positions to measure spherical arc distance
 /// between faces and over face edges.
 /// </summary>
 /// <param name="source">The source face from which the path should start.</param>
 /// <param name="target">The target face that the path should attempt to reach.</param>
 /// <param name="surface">The surface describing the overall shape of the spherical manifold.</param>
 /// <param name="facePositions">The three dimensional positions of each face in the world.</param>
 /// <param name="path">An optional existing path created by an earlier call to one of the <seealso cref="O:MakeIt.Tile.PathFinder.FindPath"/> functions, which will be overwritten with the new path data.</param>
 /// <returns>A face edge path instance describing the path found from source to target, or an incomplete object if no path was found.</returns>
 /// <remarks><para>The optional <paramref name="path"/> parameter is useful for reducing allocation activity
 /// and pressure on the garbage collector.  Reusing an existing path object will not require an additional
 /// allocation to store the path as long as the new path fits inside the capacity already available in the
 /// existing path.</para></remarks>
 public IFaceEdgePath FindSphericalEuclideanPath(Topology.Face source, Topology.Face target, SphericalSurface surface, IFaceAttribute <Vector3> facePositions, IFaceEdgePath path = null)
 {
     return(FindPath(source, target,
                     (Topology.Face s, Topology.Face t, int pathLength) =>
     {
         var sourcePosition = facePositions[s];
         var targetPosition = facePositions[t];
         return Geometry.SphericalArcLength(sourcePosition, targetPosition, surface.radius);
     },
                     (Topology.FaceEdge edge, int pathLength) =>
     {
         if (edge.isOuterBoundary)
         {
             return float.PositiveInfinity;
         }
         var sourcePosition = facePositions[edge.nearFace];
         var targetPosition = facePositions[edge.farFace];
         return Geometry.SphericalArcLength(sourcePosition, targetPosition, surface.radius);
     },
                     path));
 }
        /// <summary>
        /// Attempts to move the positions of vertices such that they have roughly uniform density, with a bias towards also making sure that the surface areas of the faces also become more uniform.
        /// </summary>
        /// <param name="surface">The spherical surface describing the overall shape of the manifold.</param>
        /// <param name="topology">The topology to relax.</param>
        /// <param name="vertexPositions">The original positions of the vertices to relax.</param>
        /// <param name="lockBoundaryPositions">Indicates that vertices with an external neighboring face should not have their positions altered.</param>
        /// <param name="relaxedVertexPositions">A pre-allocated collection in which the relaxed vertex positions will be stored.  Should not be the same collection as <paramref name="vertexPositions"/>.</param>
        /// <param name="faceCentroids">A pre-allocated collection in which the intermediate face centroid positions will be stored.</param>
        /// <param name="vertexAreas">A pre-allocated collection in which the intermediate nearby surface areas of vertices will be stored.</param>
        /// <param name="faceCentroidAngles">A pre-allocated collection in which the intermediate face centroid angles will be stored.</param>
        /// <returns>The relaxed vertex positions.</returns>
        public static IVertexAttribute <Vector3> RelaxVertexPositionsForEqualArea(SphericalSurface surface, Topology topology, IVertexAttribute <Vector3> vertexPositions, bool lockBoundaryPositions, IVertexAttribute <Vector3> relaxedVertexPositions, IFaceAttribute <Vector3> faceCentroids, IEdgeAttribute <float> faceCentroidAngles, IVertexAttribute <float> vertexAreas)
        {
            var idealArea = surface.radius * surface.radius * 4f * Mathf.PI / topology.vertices.Count;

            FaceAttributeUtility.CalculateSphericalFaceCentroidsFromVertexPositions(topology.internalFaces, surface, vertexPositions, faceCentroids);
            EdgeAttributeUtility.CalculateSphericalFaceCentroidAnglesFromFaceCentroids(topology.faceEdges, surface, faceCentroids, faceCentroidAngles);
            VertexAttributeUtility.CalculateSphericalVertexAreasFromFaceCentroidAngles(topology.vertices, surface, faceCentroidAngles, vertexAreas);

            for (int i = 0; i < topology.vertices.Count; ++i)
            {
                relaxedVertexPositions[i] = new Vector3(0f, 0f, 0f);
            }

            foreach (var vertex in topology.vertices)
            {
                var multiplier = Mathf.Sqrt(idealArea / vertexAreas[vertex]);
                foreach (var edge in vertex.edges)
                {
                    var neighborVertex         = edge.vertex;
                    var neighborRelativeCenter = vertexPositions[edge.twin];
                    relaxedVertexPositions[neighborVertex] += (vertexPositions[neighborVertex] - neighborRelativeCenter) * multiplier + neighborRelativeCenter;
                }
            }

            foreach (var vertex in topology.vertices)
            {
                if (!lockBoundaryPositions || !vertex.hasExternalFaceNeighbor)
                {
                    relaxedVertexPositions[vertex] = relaxedVertexPositions[vertex].WithMagnitude(surface.radius);
                }
                else
                {
                    relaxedVertexPositions[vertex] = vertexPositions[vertex];
                }
            }

            return(relaxedVertexPositions);
        }