using UnityEngine; using System; using System.Collections; using System.Collections.Generic; using System.Linq; namespace UnityEngine.ProBuilder { /// /// Contains a set of commonly used functions for modifying mesh positions. /// public static class VertexPositioning { static List s_CoincidentVertices = new List(); /// /// Returns a copy of a mesh positions array transformed into world coordinates. /// /// The source mesh. /// An array containing all vertex positions in world space. public static Vector3[] VerticesInWorldSpace(this ProBuilderMesh mesh) { if (mesh == null) throw new ArgumentNullException("mesh"); int len = mesh.vertexCount; Vector3[] worldPoints = new Vector3[len]; Vector3[] localPoints = mesh.positionsInternal; for (int i = 0; i < len; i++) worldPoints[i] = mesh.transform.TransformPoint(localPoints[i]); return worldPoints; } /// /// Translates a set of vertices with a world space offset. /// /// This applies the mesh positions to both the and the . /// /// The mesh containing the vertices you want to translate. /// An array of triangles pointing to the vertex positions that you want to translate. /// The offset to apply in world coordinates. public static void TranslateVerticesInWorldSpace(this ProBuilderMesh mesh, int[] indexes, Vector3 offset) { if (mesh == null) throw new ArgumentNullException("mesh"); mesh.TranslateVerticesInWorldSpace(indexes, offset, 0f, false); } /// /// Translate a set of vertices with a world space offset. ///
/// Unlike most other mesh operations, this function applies the mesh positions to both ProBuilderMesh and the UnityEngine.Mesh. ///
/// /// A distinct list of vertex indexes. /// The direction and magnitude to translate selectedTriangles, in world space. /// If > 0 snap each vertex to the nearest on-grid point in world space. /// If true vertices will only be snapped along the active axis. internal static void TranslateVerticesInWorldSpace(this ProBuilderMesh mesh, int[] indexes, Vector3 offset, float snapValue, bool snapAxisOnly) { if (mesh == null) throw new ArgumentNullException("mesh"); int i = 0; mesh.GetCoincidentVertices(indexes, s_CoincidentVertices); Matrix4x4 w2l = mesh.transform.worldToLocalMatrix; Vector3 localOffset = w2l * offset; Vector3[] verts = mesh.positionsInternal; // Snaps to world grid if (Mathf.Abs(snapValue) > Mathf.Epsilon) { Matrix4x4 l2w = mesh.transform.localToWorldMatrix; var mask = snapAxisOnly ? new Vector3Mask(offset, Math.handleEpsilon) : Vector3Mask.XYZ; for (i = 0; i < s_CoincidentVertices.Count; i++) { var v = l2w.MultiplyPoint3x4(verts[s_CoincidentVertices[i]] + localOffset); verts[s_CoincidentVertices[i]] = w2l.MultiplyPoint3x4(ProBuilderSnapping.Snap(v, ((Vector3)mask) * snapValue)); } } else { for (i = 0; i < s_CoincidentVertices.Count; i++) verts[s_CoincidentVertices[i]] += localOffset; } // don't bother calling a full ToMesh() here because we know for certain that the vertices and msh.vertices arrays are equal in length mesh.positionsInternal = verts; mesh.mesh.vertices = verts; } /// /// Translates a set of vertices with an offset provided in local (model) coordinates. /// /// This applies the mesh positions to both the and the . /// /// The mesh containing the vertices that you want to translate. /// A set of triangles pointing to the vertex positions that you want to translate. /// The offset to apply in local coordinates. public static void TranslateVertices(this ProBuilderMesh mesh, IEnumerable indexes, Vector3 offset) { if (mesh == null) throw new ArgumentNullException("mesh"); mesh.GetCoincidentVertices(indexes, s_CoincidentVertices); TranslateVerticesInternal(mesh, s_CoincidentVertices, offset); } /// /// Translates a set of edges with an offset provided in local (model) coordinates. /// /// This applies the mesh positions to both the and the . /// /// The mesh containing the edges that you want to translate. /// The set of edges that you want to translate. /// The offset to apply in local coordinates. public static void TranslateVertices(this ProBuilderMesh mesh, IEnumerable edges, Vector3 offset) { if (mesh == null) throw new ArgumentNullException("mesh"); mesh.GetCoincidentVertices(edges, s_CoincidentVertices); TranslateVerticesInternal(mesh, s_CoincidentVertices, offset); } /// /// Translates a set of faces with an offset provided in local (model) coordinates. /// /// This applies the mesh positions to both the and the . /// /// The mesh containing the faces that you want to translate. /// The set of faces that you want to translate. /// The offset to apply in local coordinates. public static void TranslateVertices(this ProBuilderMesh mesh, IEnumerable faces, Vector3 offset) { if (mesh == null) throw new ArgumentNullException("mesh"); mesh.GetCoincidentVertices(faces, s_CoincidentVertices); TranslateVerticesInternal(mesh, s_CoincidentVertices, offset); } static void TranslateVerticesInternal(ProBuilderMesh mesh, IEnumerable indices, Vector3 offset) { Vector3[] verts = mesh.positionsInternal; for (int i = 0, c = s_CoincidentVertices.Count; i < c; i++) verts[s_CoincidentVertices[i]] += offset; // don't bother calling a full ToMesh() here because we know for certain that the vertices and msh.vertices arrays are equal in length mesh.mesh.vertices = verts; } /// /// Takes a index (index of the triangle in the sharedIndexes /// array), and changes its vertices to a new position in model space coordinates. /// /// Use sharedIndexes and to get a shared (or common) index. /// /// The mesh containing the vertices you want to modify. /// The shared (or common) index to set the vertex position of. /// The new position in model coordinates. public static void SetSharedVertexPosition(this ProBuilderMesh mesh, int sharedVertexHandle, Vector3 position) { if (mesh == null) throw new ArgumentNullException("mesh"); Vector3[] v = mesh.positionsInternal; foreach (var index in mesh.sharedVerticesInternal[sharedVertexHandle]) v[index] = position; mesh.positionsInternal = v; mesh.mesh.vertices = v; } /// /// Set a collection of mesh attributes with a Vertex. ///

/// Use @"UnityEngine.ProBuilder.ProBuilderMesh.sharedIndexes" and IntArrayUtility.IndexOf to get a shared (or common) index. ///
/// /// /// internal static void SetSharedVertexValues(this ProBuilderMesh mesh, int sharedVertexHandle, Vertex vertex) { Vertex[] vertices = mesh.GetVertices(); foreach (var index in mesh.sharedVerticesInternal[sharedVertexHandle]) vertices[index] = vertex; mesh.SetVertices(vertices); } } }