using System;
using System.Collections.Generic;
using UnityEngine;
namespace UnityEngine.ProBuilder.Csg
{
static class VertexUtility
{
///
/// Allocate and fill all attribute arrays. This method will fill all arrays, regardless of whether or not real data populates the values (check what attributes a Vertex contains with HasAttribute()).
///
///
/// If you are using this function to rebuild a mesh, use SetMesh instead. SetMesh handles setting null arrays where appropriate for you.
///
///
/// The source vertices.
/// A new array of the vertex position values.
/// A new array of the vertex color values.
/// A new array of the vertex uv0 values.
/// A new array of the vertex normal values.
/// A new array of the vertex tangent values.
/// A new array of the vertex uv2 values.
/// A new array of the vertex uv3 values.
/// A new array of the vertex uv4 values.
public static void GetArrays(
IList vertices,
out Vector3[] position,
out Color[] color,
out Vector2[] uv0,
out Vector3[] normal,
out Vector4[] tangent,
out Vector2[] uv2,
out List uv3,
out List uv4)
{
GetArrays(vertices, out position, out color, out uv0, out normal, out tangent, out uv2, out uv3, out uv4, VertexAttributes.All);
}
///
/// Allocate and fill the requested attribute arrays.
///
///
/// If you are using this function to rebuild a mesh, use SetMesh instead. SetMesh handles setting null arrays where appropriate for you.
///
///
/// The source vertices.
/// A new array of the vertex position values if requested by the attributes parameter, or null.
/// A new array of the vertex color values if requested by the attributes parameter, or null.
/// A new array of the vertex uv0 values if requested by the attributes parameter, or null.
/// A new array of the vertex normal values if requested by the attributes parameter, or null.
/// A new array of the vertex tangent values if requested by the attributes parameter, or null.
/// A new array of the vertex uv2 values if requested by the attributes parameter, or null.
/// A new array of the vertex uv3 values if requested by the attributes parameter, or null.
/// A new array of the vertex uv4 values if requested by the attributes parameter, or null.
/// A flag with the MeshAttributes requested.
///
public static void GetArrays(
IList vertices,
out Vector3[] position,
out Color[] color,
out Vector2[] uv0,
out Vector3[] normal,
out Vector4[] tangent,
out Vector2[] uv2,
out List uv3,
out List uv4,
VertexAttributes attributes)
{
if (vertices == null)
throw new ArgumentNullException("vertices");
int vc = vertices.Count;
var first = vc < 1 ? new Vertex() : vertices[0];
bool hasPosition = ((attributes & VertexAttributes.Position) == VertexAttributes.Position) && first.hasPosition;
bool hasColor = ((attributes & VertexAttributes.Color) == VertexAttributes.Color) && first.hasColor;
bool hasUv0 = ((attributes & VertexAttributes.Texture0) == VertexAttributes.Texture0) && first.hasUV0;
bool hasNormal = ((attributes & VertexAttributes.Normal) == VertexAttributes.Normal) && first.hasNormal;
bool hasTangent = ((attributes & VertexAttributes.Tangent) == VertexAttributes.Tangent) && first.hasTangent;
bool hasUv2 = ((attributes & VertexAttributes.Texture1) == VertexAttributes.Texture1) && first.hasUV2;
bool hasUv3 = ((attributes & VertexAttributes.Texture2) == VertexAttributes.Texture2) && first.hasUV3;
bool hasUv4 = ((attributes & VertexAttributes.Texture3) == VertexAttributes.Texture3) && first.hasUV4;
position = hasPosition ? new Vector3[vc] : null;
color = hasColor ? new Color[vc] : null;
uv0 = hasUv0 ? new Vector2[vc] : null;
normal = hasNormal ? new Vector3[vc] : null;
tangent = hasTangent ? new Vector4[vc] : null;
uv2 = hasUv2 ? new Vector2[vc] : null;
uv3 = hasUv3 ? new List(vc) : null;
uv4 = hasUv4 ? new List(vc) : null;
for (int i = 0; i < vc; i++)
{
if (hasPosition)
position[i] = vertices[i].position;
if (hasColor)
color[i] = vertices[i].color;
if (hasUv0)
uv0[i] = vertices[i].uv0;
if (hasNormal)
normal[i] = vertices[i].normal;
if (hasTangent)
tangent[i] = vertices[i].tangent;
if (hasUv2)
uv2[i] = vertices[i].uv2;
if (hasUv3)
uv3.Add(vertices[i].uv3);
if (hasUv4)
uv4.Add(vertices[i].uv4);
}
}
public static Vertex[] GetVertices(this Mesh mesh)
{
if (mesh == null)
return null;
int vertexCount = mesh.vertexCount;
Vertex[] v = new Vertex[vertexCount];
Vector3[] positions = mesh.vertices;
Color[] colors = mesh.colors;
Vector3[] normals = mesh.normals;
Vector4[] tangents = mesh.tangents;
Vector2[] uv0s = mesh.uv;
Vector2[] uv2s = mesh.uv2;
List uv3s = new List();
List uv4s = new List();
mesh.GetUVs(2, uv3s);
mesh.GetUVs(3, uv4s);
bool _hasPositions = positions != null && positions.Length == vertexCount;
bool _hasColors = colors != null && colors.Length == vertexCount;
bool _hasNormals = normals != null && normals.Length == vertexCount;
bool _hasTangents = tangents != null && tangents.Length == vertexCount;
bool _hasUv0 = uv0s != null && uv0s.Length == vertexCount;
bool _hasUv2 = uv2s != null && uv2s.Length == vertexCount;
bool _hasUv3 = uv3s.Count == vertexCount;
bool _hasUv4 = uv4s.Count == vertexCount;
for (int i = 0; i < vertexCount; i++)
{
v[i] = new Vertex();
if (_hasPositions)
v[i].position = positions[i];
if (_hasColors)
v[i].color = colors[i];
if (_hasNormals)
v[i].normal = normals[i];
if (_hasTangents)
v[i].tangent = tangents[i];
if (_hasUv0)
v[i].uv0 = uv0s[i];
if (_hasUv2)
v[i].uv2 = uv2s[i];
if (_hasUv3)
v[i].uv3 = uv3s[i];
if (_hasUv4)
v[i].uv4 = uv4s[i];
}
return v;
}
///
/// Replace mesh values with vertex array. Mesh is cleared during this function, so be sure to set the triangles after calling.
///
/// The target mesh.
/// The vertices to replace the mesh attributes with.
public static void SetMesh(Mesh mesh, IList vertices)
{
if (mesh == null)
throw new ArgumentNullException("mesh");
if (vertices == null)
throw new ArgumentNullException("vertices");
Vector3[] positions = null;
Color[] colors = null;
Vector2[] uv0s = null;
Vector3[] normals = null;
Vector4[] tangents = null;
Vector2[] uv2s = null;
List uv3s = null;
List uv4s = null;
GetArrays(vertices, out positions,
out colors,
out uv0s,
out normals,
out tangents,
out uv2s,
out uv3s,
out uv4s);
mesh.Clear();
Vertex first = vertices[0];
if (first.hasPosition) mesh.vertices = positions;
if (first.hasColor) mesh.colors = colors;
if (first.hasUV0) mesh.uv = uv0s;
if (first.hasNormal) mesh.normals = normals;
if (first.hasTangent) mesh.tangents = tangents;
if (first.hasUV2) mesh.uv2 = uv2s;
if (first.hasUV3)
if (uv3s != null)
mesh.SetUVs(2, uv3s);
if (first.hasUV4)
if (uv4s != null)
mesh.SetUVs(3, uv4s);
}
///
/// Linearly interpolate between two vertices.
///
/// Left parameter.
/// Right parameter.
/// The weight of the interpolation. 0 is fully x, 1 is fully y.
/// A new vertex interpolated by weight between x and y.
public static Vertex Mix(this Vertex x, Vertex y, float weight)
{
float i = 1f - weight;
Vertex v = new Vertex();
v.position = x.position * i + y.position * weight;
if (x.hasColor && y.hasColor)
v.color = x.color * i + y.color * weight;
else if (x.hasColor)
v.color = x.color;
else if (y.hasColor)
v.color = y.color;
if (x.hasNormal && y.hasNormal)
v.normal = x.normal * i + y.normal * weight;
else if (x.hasNormal)
v.normal = x.normal;
else if (y.hasNormal)
v.normal = y.normal;
if (x.hasTangent && y.hasTangent)
v.tangent = x.tangent * i + y.tangent * weight;
else if (x.hasTangent)
v.tangent = x.tangent;
else if (y.hasTangent)
v.tangent = y.tangent;
if (x.hasUV0 && y.hasUV0)
v.uv0 = x.uv0 * i + y.uv0 * weight;
else if (x.hasUV0)
v.uv0 = x.uv0;
else if (y.hasUV0)
v.uv0 = y.uv0;
if (x.hasUV2 && y.hasUV2)
v.uv2 = x.uv2 * i + y.uv2 * weight;
else if (x.hasUV2)
v.uv2 = x.uv2;
else if (y.hasUV2)
v.uv2 = y.uv2;
if (x.hasUV3 && y.hasUV3)
v.uv3 = x.uv3 * i + y.uv3 * weight;
else if (x.hasUV3)
v.uv3 = x.uv3;
else if (y.hasUV3)
v.uv3 = y.uv3;
if (x.hasUV4 && y.hasUV4)
v.uv4 = x.uv4 * i + y.uv4 * weight;
else if (x.hasUV4)
v.uv4 = x.uv4;
else if (y.hasUV4)
v.uv4 = y.uv4;
return v;
}
///
/// Transform a vertex into world space.
///
/// The transform to apply.
/// A model space vertex.
/// A new vertex in world coordinate space.
public static Vertex TransformVertex(this Transform transform, Vertex vertex)
{
var v = new Vertex();
if (vertex.HasArrays(VertexAttributes.Position))
v.position = transform.TransformPoint(vertex.position);
if (vertex.HasArrays(VertexAttributes.Color))
v.color = vertex.color;
if (vertex.HasArrays(VertexAttributes.Normal))
v.normal = transform.TransformDirection(vertex.normal);
if (vertex.HasArrays(VertexAttributes.Tangent))
v.tangent = transform.rotation * vertex.tangent;
if (vertex.HasArrays(VertexAttributes.Texture0))
v.uv0 = vertex.uv0;
if (vertex.HasArrays(VertexAttributes.Texture1))
v.uv2 = vertex.uv2;
if (vertex.HasArrays(VertexAttributes.Texture2))
v.uv3 = vertex.uv3;
if (vertex.HasArrays(VertexAttributes.Texture3))
v.uv4 = vertex.uv4;
return v;
}
}
}