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);
}
}
}