Rasagar/Library/PackageCache/com.unity.probuilder/External/CSG/Classes/VertexUtility.cs

328 lines
13 KiB
C#
Raw Normal View History

2024-08-26 13:07:20 -07:00
using System;
using System.Collections.Generic;
using UnityEngine;
namespace UnityEngine.ProBuilder.Csg
{
static class VertexUtility
{
/// <summary>
/// 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()).
/// </summary>
/// <remarks>
/// If you are using this function to rebuild a mesh, use SetMesh instead. SetMesh handles setting null arrays where appropriate for you.
/// </remarks>
/// <seealso cref="SetMesh"/>
/// <param name="vertices">The source vertices.</param>
/// <param name="position">A new array of the vertex position values.</param>
/// <param name="color">A new array of the vertex color values.</param>
/// <param name="uv0">A new array of the vertex uv0 values.</param>
/// <param name="normal">A new array of the vertex normal values.</param>
/// <param name="tangent">A new array of the vertex tangent values.</param>
/// <param name="uv2">A new array of the vertex uv2 values.</param>
/// <param name="uv3">A new array of the vertex uv3 values.</param>
/// <param name="uv4">A new array of the vertex uv4 values.</param>
public static void GetArrays(
IList<Vertex> vertices,
out Vector3[] position,
out Color[] color,
out Vector2[] uv0,
out Vector3[] normal,
out Vector4[] tangent,
out Vector2[] uv2,
out List<Vector4> uv3,
out List<Vector4> uv4)
{
GetArrays(vertices, out position, out color, out uv0, out normal, out tangent, out uv2, out uv3, out uv4, VertexAttributes.All);
}
/// <summary>
/// Allocate and fill the requested attribute arrays.
/// </summary>
/// <remarks>
/// If you are using this function to rebuild a mesh, use SetMesh instead. SetMesh handles setting null arrays where appropriate for you.
/// </remarks>
/// <seealso cref="SetMesh"/>
/// <param name="vertices">The source vertices.</param>
/// <param name="position">A new array of the vertex position values if requested by the attributes parameter, or null.</param>
/// <param name="color">A new array of the vertex color values if requested by the attributes parameter, or null.</param>
/// <param name="uv0">A new array of the vertex uv0 values if requested by the attributes parameter, or null.</param>
/// <param name="normal">A new array of the vertex normal values if requested by the attributes parameter, or null.</param>
/// <param name="tangent">A new array of the vertex tangent values if requested by the attributes parameter, or null.</param>
/// <param name="uv2">A new array of the vertex uv2 values if requested by the attributes parameter, or null.</param>
/// <param name="uv3">A new array of the vertex uv3 values if requested by the attributes parameter, or null.</param>
/// <param name="uv4">A new array of the vertex uv4 values if requested by the attributes parameter, or null.</param>
/// <param name="attributes">A flag with the MeshAttributes requested.</param>
/// <seealso cref="HasArrays"/>
public static void GetArrays(
IList<Vertex> vertices,
out Vector3[] position,
out Color[] color,
out Vector2[] uv0,
out Vector3[] normal,
out Vector4[] tangent,
out Vector2[] uv2,
out List<Vector4> uv3,
out List<Vector4> 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<Vector4>(vc) : null;
uv4 = hasUv4 ? new List<Vector4>(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<Vector4> uv3s = new List<Vector4>();
List<Vector4> uv4s = new List<Vector4>();
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;
}
/// <summary>
/// Replace mesh values with vertex array. Mesh is cleared during this function, so be sure to set the triangles after calling.
/// </summary>
/// <param name="mesh">The target mesh.</param>
/// <param name="vertices">The vertices to replace the mesh attributes with.</param>
public static void SetMesh(Mesh mesh, IList<Vertex> 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<Vector4> uv3s = null;
List<Vector4> 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);
}
/// <summary>
/// Linearly interpolate between two vertices.
/// </summary>
/// <param name="x">Left parameter.</param>
/// <param name="y">Right parameter.</param>
/// <param name="weight">The weight of the interpolation. 0 is fully x, 1 is fully y.</param>
/// <returns>A new vertex interpolated by weight between x and y.</returns>
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;
}
/// <summary>
/// Transform a vertex into world space.
/// </summary>
/// <param name="transform">The transform to apply.</param>
/// <param name="vertex">A model space vertex.</param>
/// <returns>A new vertex in world coordinate space.</returns>
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;
}
}
}