コード例 #1
0
        public static void DisplacePolygons(Polygon[] polygons, float distance)
        {
            // Used for determining if two vertices are the same
            Polygon.VertexComparerEpsilon vertexComparer = new Polygon.VertexComparerEpsilon();
            // Used for determining if two positions or normals are the same
            Polygon.Vector3ComparerEpsilon vectorComparer = new Polygon.Vector3ComparerEpsilon();

            // Group overlapping positions and also track their normals
            List <List <Vertex> >  groupedVertices = new List <List <Vertex> >();
            List <List <Vector3> > groupedNormals  = new List <List <Vector3> >();

            // Maps back from a vertex to the polygon it came from, used for UV calculation
            Dictionary <Vertex, Polygon> vertexPolygonMappings = new Dictionary <Vertex, Polygon>();

            for (int polygonIndex = 0; polygonIndex < polygons.Length; polygonIndex++)
            {
                Vertex[] vertices = polygons[polygonIndex].Vertices;

                // Group the selected vertices into clusters
                for (int vertexIndex = 0; vertexIndex < vertices.Length; vertexIndex++)
                {
                    Vertex sourceVertex = vertices[vertexIndex];

                    vertexPolygonMappings[sourceVertex] = polygons[polygonIndex];

                    bool added = false;

                    for (int groupIndex = 0; groupIndex < groupedVertices.Count; groupIndex++)
                    {
                        if (groupedVertices[groupIndex].Contains(sourceVertex, vertexComparer))
                        {
                            groupedVertices[groupIndex].Add(sourceVertex);
                            // Add the normal of the polygon if it hasn't already been added (this prevents issues with two polygons that are coplanar)
                            if (!groupedNormals[groupIndex].Contains(polygons[polygonIndex].Plane.normal, vectorComparer))
                            {
                                groupedNormals[groupIndex].Add(polygons[polygonIndex].Plane.normal);
                            }
                            added = true;
                            break;
                        }
                    }

                    if (!added)
                    {
                        groupedVertices.Add(new List <Vertex>()
                        {
                            sourceVertex
                        });
                        groupedNormals.Add(new List <Vector3>()
                        {
                            polygons[polygonIndex].Plane.normal
                        });
                    }
                }
            }

            List <List <Vector3> > groupedPositions = new List <List <Vector3> >();
            List <List <Vector2> > groupedUV        = new List <List <Vector2> >();

            // Calculate the new positions and UVs, but don't assign them as they must be calculated in one go
            for (int i = 0; i < groupedVertices.Count; i++)
            {
                groupedPositions.Add(new List <Vector3>());
                groupedUV.Add(new List <Vector2>());

                for (int j = 0; j < groupedVertices[i].Count; j++)
                {
                    Vector3 position = groupedVertices[i][j].Position;
                    for (int k = 0; k < groupedNormals[i].Count; k++)
                    {
                        position += groupedNormals[i][k] * distance;
                    }
                    Polygon primaryPolygon = vertexPolygonMappings[groupedVertices[i][j]];

                    Vector2 uv = GeometryHelper.GetUVForPosition(primaryPolygon, position);
                    groupedPositions[i].Add(position);
                    groupedUV[i].Add(uv);
                }
            }

            // Apply the new positions and UVs now that they've all been calculated
            for (int i = 0; i < groupedVertices.Count; i++)
            {
                for (int j = 0; j < groupedVertices[i].Count; j++)
                {
                    Vertex vertex = groupedVertices[i][j];
                    vertex.Position = groupedPositions[i][j];
                    vertex.UV       = groupedUV[i][j];
                }
            }

            // Polygon planes have moved, so recalculate them
            for (int polygonIndex = 0; polygonIndex < polygons.Length; polygonIndex++)
            {
                polygons[polygonIndex].CalculatePlane();
            }
        }
コード例 #2
0
        /// <summary>
        /// Constructs a polygon from an unordered coplanar set of positions
        /// </summary>
        public static Polygon ConstructPolygon(List <Vector3> sourcePositions, bool removeExtraPositions)
        {
            List <Vector3> positions;

            if (removeExtraPositions)
            {
                Polygon.Vector3ComparerEpsilon equalityComparer = new Polygon.Vector3ComparerEpsilon();
                positions = sourcePositions.Distinct(equalityComparer).ToList();
            }
            else
            {
                positions = sourcePositions;
            }

            // If positions is smaller than 3 then we can't construct a polygon. This could happen if you try to cut the
            // tip off a very, very thin brush. While the plane and the brushes would intersect, the actual
            // cross-sectional area is near zero and too small to create a valid polygon. In this case simply return
            // null to indicate polygon creation was impossible
            if (positions.Count < 3)
            {
                return(null);
            }

            // Find center point, so we can sort the positions around it
            Vector3 center = positions[0];

            for (int i = 1; i < positions.Count; i++)
            {
                center += positions[i];
            }

            center *= 1f / positions.Count;

            if (positions.Count < 3)
            {
                Debug.LogError("Position count is below 3, this is probably unhandled");
            }

            // Find the plane
            UnityEngine.Plane plane = new UnityEngine.Plane(positions[0], positions[1], positions[2]);



            // Rotation to go from the polygon's plane to XY plane (for sorting)
            Quaternion cancellingRotation = Quaternion.Inverse(Quaternion.LookRotation(plane.normal));

            // Rotate the center point onto the plane too
            Vector3 rotatedCenter = cancellingRotation * center;

            // Sort the positions, passing the rotation to put the positions on XY plane and the rotated center point
            IComparer <Vector3> comparer = new SortVectorsClockwise(cancellingRotation, rotatedCenter);

            positions.Sort(comparer);


            // Create the vertices from the positions
            Vertex[] newPolygonVertices = new Vertex[positions.Count];
            for (int i = 0; i < positions.Count; i++)
            {
                newPolygonVertices[i] = new Vertex(positions[i], -plane.normal, (cancellingRotation * positions[i]) * 0.5f);
            }
            Polygon newPolygon = new Polygon(newPolygonVertices, null, false, false);

            if (newPolygon.Plane.normal == Vector3.zero)
            {
                Debug.LogError("Zero normal found, this leads to invalid polyhedron-point tests");

                // hacky
                //				if(removeExtraPositions)
                //				{
                //					Polygon.Vector3ComparerEpsilon equalityComparer = new Polygon.Vector3ComparerEpsilon();
                //					List<Vector3> testFoo = newPolygonVertices.Select(item => item.Position).Distinct(equalityComparer).ToList();
                //				}
            }
            return(newPolygon);
        }
コード例 #3
0
        /// <summary>
        /// Translates the specified vertices by a position delta (local to the brush) and updates the UVs
        /// </summary>
        /// <param name="brush">Brush from which the vertices belong.</param>
        /// <param name="specifiedVertices">Specified vertices to be translated.</param>
        /// <param name="localDelta">Local positional delta.</param>
        public static void TranslateSpecifiedVertices(Brush brush, List <Vertex> specifiedVertices, Vector3 localDelta)
        {
            Polygon.Vector3ComparerEpsilon positionComparer = new Polygon.Vector3ComparerEpsilon();

            // Cache the positions as the position of vertices will change while in the for loop
            List <Vector3> specifiedPositions = specifiedVertices.Select(item => item.Position).ToList();

            // So we know which polygons need to have their normals recalculated
            List <Polygon> affectedPolygons = new List <Polygon>();

            Polygon[] polygons = brush.GetPolygons();

            for (int i = 0; i < polygons.Length; i++)
            {
                Polygon polygon = polygons[i];

                int vertexCount = polygon.Vertices.Length;

                Vector3[] newPositions = new Vector3[vertexCount];
                Vector2[] newUV        = new Vector2[vertexCount];

                for (int j = 0; j < vertexCount; j++)
                {
                    newPositions[j] = polygon.Vertices[j].Position;
                    newUV[j]        = polygon.Vertices[j].UV;
                }

                bool polygonAffected = false;

                for (int j = 0; j < vertexCount; j++)
                {
                    Vertex vertex = polygon.Vertices[j];
                    if (specifiedPositions.Contains(vertex.Position, positionComparer))
                    {
                        Vector3 newPosition = vertex.Position + localDelta;

                        newPositions[j] = newPosition;

                        newUV[j] = GeometryHelper.GetUVForPosition(polygon, newPosition);

                        polygonAffected = true;
                    }
                }

                if (polygonAffected)
                {
                    affectedPolygons.Add(polygon);
                }

                // Apply all the changes to the polygon
                for (int j = 0; j < vertexCount; j++)
                {
                    Vertex vertex = polygon.Vertices[j];
                    vertex.Position = newPositions[j];
                    vertex.UV       = newUV[j];
                }

                polygon.CalculatePlane();
            }

            if (affectedPolygons.Count > 0)
            {
                for (int i = 0; i < affectedPolygons.Count; i++)
                {
                    affectedPolygons[i].ResetVertexNormals();
                }
            }
        }