383 lines
13 KiB
C#
383 lines
13 KiB
C#
using NUnit.Framework;
|
|
using UnityEngine;
|
|
|
|
public class FragmentDataTests
|
|
{
|
|
[Test]
|
|
public void EmptyInit()
|
|
{
|
|
int vertexCount = 101;
|
|
FragmentData data = new FragmentData(vertexCount, 0);
|
|
|
|
// Verify initialization
|
|
Assert.AreEqual(vertexCount, data.Vertices.Capacity);
|
|
Assert.AreEqual(vertexCount, data.IndexMap.Length);
|
|
Assert.Zero(data.Vertices.Count);
|
|
Assert.Zero(data.CutVertices.Count);
|
|
Assert.Zero(data.Constraints.Count);
|
|
Assert.Zero(data.triangleCount);
|
|
Assert.Zero(data.vertexCount);
|
|
|
|
// Assume two submeshes for now
|
|
Assert.AreEqual(data.Triangles.Length, 2);
|
|
}
|
|
|
|
[Test]
|
|
public void MeshInit()
|
|
{
|
|
// Test mesh data
|
|
var vertices = new Vector3[] {
|
|
new Vector3(0, 0, 0),
|
|
new Vector3(1, 0, 0),
|
|
new Vector3(0, 1, 0),
|
|
new Vector3(1, 1, 0)
|
|
};
|
|
var normals = new Vector3[] {
|
|
new Vector3(-0.1f, -0.1f, 1).normalized,
|
|
new Vector3(0.1f, -0.1f, 1).normalized,
|
|
new Vector3(-0.1f, 0.1f, 1).normalized,
|
|
new Vector3(0.1f, 0.1f, 1).normalized
|
|
};
|
|
var uv = new Vector2[] {
|
|
new Vector3(0, 0),
|
|
new Vector3(1, 0),
|
|
new Vector3(0, 1),
|
|
new Vector3(1, 1)
|
|
};
|
|
var triangles = new int[] { 0, 2, 1, 1, 2, 3 };
|
|
|
|
// Setup the test mesh
|
|
Mesh mesh = new Mesh();
|
|
mesh.vertices = vertices;
|
|
mesh.triangles = triangles;
|
|
mesh.normals = normals;
|
|
mesh.uv = uv;
|
|
|
|
// Generate the sliced mesh data from the mesh
|
|
FragmentData meshData = new FragmentData(mesh);
|
|
|
|
// Verify sliced mesh data was initialized properly
|
|
|
|
// Check vertex data
|
|
Assert.AreEqual(mesh.vertexCount, meshData.Vertices.Count);
|
|
for(int i = 0; i < meshData.Vertices.Count; i++)
|
|
{
|
|
var vertex = meshData.Vertices[i];
|
|
Assert.AreEqual(vertices[i], vertex.position);
|
|
Assert.AreEqual(normals[i], vertex.normal);
|
|
Assert.AreEqual(uv[i], vertex.uv);
|
|
}
|
|
|
|
// Check triangle data
|
|
Assert.AreEqual(mesh.triangles.Length, meshData.Triangles[0].Count);
|
|
// Assume two submeshes for now
|
|
Assert.AreEqual(2, meshData.Triangles.Length);
|
|
|
|
Assert.Zero(meshData.CutVertices.Count);
|
|
Assert.Zero(meshData.Constraints.Count);
|
|
Assert.AreEqual(mesh.vertexCount, meshData.IndexMap.Length);
|
|
}
|
|
|
|
[Test]
|
|
public void AddCutFaceVertex()
|
|
{
|
|
int vertexCount = 10;
|
|
var meshData = new FragmentData(vertexCount, 0);
|
|
|
|
for (int i = 0; i < vertexCount; i++)
|
|
{
|
|
meshData.AddCutFaceVertex(
|
|
new Vector3(i + 1, i + 2, i + 3),
|
|
new Vector3(i + 4, i + 5, i + 6),
|
|
new Vector2(i + 7, i + 8)
|
|
);
|
|
}
|
|
|
|
// Vertex add to both main vertex data and cut-face vertex data
|
|
Assert.AreEqual(vertexCount, meshData.Vertices.Count);
|
|
Assert.AreEqual(vertexCount, meshData.CutVertices.Count);
|
|
|
|
// Index map should be updated as well
|
|
for (int i = 0; i < vertexCount; i++)
|
|
{
|
|
Assert.AreEqual(new Vector3(i + 1, i + 2, i + 3), meshData.Vertices[i].position);
|
|
Assert.AreEqual(new Vector3(i + 4, i + 5, i + 6), meshData.Vertices[i].normal);
|
|
Assert.AreEqual(new Vector2(i + 7, i + 8), meshData.Vertices[i].uv);
|
|
Assert.AreEqual(new Vector3(i + 1, i + 2, i + 3), meshData.CutVertices[i].position);
|
|
Assert.AreEqual(new Vector3(i + 4, i + 5, i + 6), meshData.CutVertices[i].normal);
|
|
Assert.AreEqual(new Vector2(i + 7, i + 8), meshData.CutVertices[i].uv);
|
|
}
|
|
}
|
|
|
|
[Test]
|
|
public void AddMappedVertex()
|
|
{
|
|
int vertexCount = 10;
|
|
var meshData = new FragmentData(vertexCount, 0);
|
|
|
|
for (int i = 0; i < vertexCount; i++)
|
|
{
|
|
MeshVertex vertex = new MeshVertex(
|
|
new Vector3(i + 1, i + 2, i + 3),
|
|
new Vector3(i + 4, i + 5, i + 6),
|
|
new Vector2(i + 7, i + 8));
|
|
|
|
meshData.AddMappedVertex(vertex, i);
|
|
}
|
|
|
|
// Vertex added only to main vertex data
|
|
Assert.AreEqual(vertexCount, meshData.Vertices.Count);
|
|
Assert.AreEqual(0, meshData.CutVertices.Count);
|
|
|
|
// Index map should be updated as well
|
|
for (int i = 0; i < vertexCount; i++)
|
|
{
|
|
Assert.AreEqual(new Vector3(i + 1, i + 2, i + 3), meshData.Vertices[i].position);
|
|
Assert.AreEqual(new Vector3(i + 4, i + 5, i + 6), meshData.Vertices[i].normal);
|
|
Assert.AreEqual(new Vector2(i + 7, i + 8), meshData.Vertices[i].uv);
|
|
Assert.AreEqual(i, meshData.IndexMap[i]);
|
|
}
|
|
}
|
|
|
|
[Test]
|
|
public void AddTriangle()
|
|
{
|
|
FragmentData meshData = new FragmentData(0, 0);
|
|
|
|
int v1 = 1;
|
|
int v2 = 2;
|
|
int v3 = 3;
|
|
|
|
meshData.AddTriangle(v1, v2, v3, SlicedMeshSubmesh.Default);
|
|
|
|
Assert.AreEqual(3, meshData.Triangles[(int)SlicedMeshSubmesh.Default].Count);
|
|
Assert.AreEqual(v1, meshData.Triangles[(int)SlicedMeshSubmesh.Default][0]);
|
|
Assert.AreEqual(v2, meshData.Triangles[(int)SlicedMeshSubmesh.Default][1]);
|
|
Assert.AreEqual(v3, meshData.Triangles[(int)SlicedMeshSubmesh.Default][2]);
|
|
}
|
|
|
|
[Test]
|
|
public void AddMappedTriangle()
|
|
{
|
|
int vertexCount = 46;
|
|
FragmentData meshData = new FragmentData(vertexCount, 0);
|
|
|
|
// Indices of the vertices in the original mesh (arbitary indices)
|
|
int v1 = 11;
|
|
int v2 = 23;
|
|
int v3 = 45;
|
|
|
|
// First, add the vertx data. v1, v2, v3 will be mapped to the indices
|
|
// 0, 1, 2 (respectively) since that is the order they are added
|
|
meshData.AddMappedVertex(new MeshVertex(Vector3.zero), v1);
|
|
int v1Mapped = meshData.vertexCount - 1;
|
|
meshData.AddMappedVertex(new MeshVertex(Vector3.zero), v2);
|
|
int v2Mapped = meshData.vertexCount - 1;
|
|
meshData.AddMappedVertex(new MeshVertex(Vector3.zero), v3);
|
|
int v3Mapped = meshData.vertexCount - 1;
|
|
|
|
// Add the triangle, but map v1, v2, v3 to the indices for the sliced mesh
|
|
meshData.AddMappedTriangle(v1, v2, v3, SlicedMeshSubmesh.Default);
|
|
|
|
Assert.AreEqual(3, meshData.Triangles[(int)SlicedMeshSubmesh.Default].Count);
|
|
Assert.AreEqual(v1Mapped, meshData.Triangles[(int)SlicedMeshSubmesh.Default][0]);
|
|
Assert.AreEqual(v2Mapped, meshData.Triangles[(int)SlicedMeshSubmesh.Default][1]);
|
|
Assert.AreEqual(v3Mapped, meshData.Triangles[(int)SlicedMeshSubmesh.Default][2]);
|
|
}
|
|
|
|
[Test]
|
|
public void WeldCutFaceVertices_AllVerticesUnique()
|
|
{
|
|
int vertexCount = 10;
|
|
FragmentData meshData = new FragmentData(vertexCount, 0);
|
|
|
|
for (int i = 0; i < vertexCount; i++)
|
|
{
|
|
meshData.AddCutFaceVertex(
|
|
new Vector3(i + 1, i + 2, i + 3),
|
|
Vector3.zero,
|
|
Vector2.zero
|
|
);
|
|
}
|
|
|
|
// Verify vertex count prior to weld
|
|
Assert.AreEqual(vertexCount, meshData.CutVertices.Count);
|
|
|
|
meshData.WeldCutFaceVertices();
|
|
|
|
// # of cut vertices should remain unchanged after weld
|
|
Assert.AreEqual(vertexCount, meshData.CutVertices.Count);
|
|
}
|
|
|
|
[Test]
|
|
public void WeldCutFaceVertices_OneDuplicateVertex()
|
|
{
|
|
int vertexCount = 10;
|
|
FragmentData meshData = new FragmentData(vertexCount, 0);
|
|
|
|
for (int i = 0; i < vertexCount; i++)
|
|
{
|
|
meshData.AddCutFaceVertex(
|
|
new Vector3(i + 1, i + 2, i + 3),
|
|
Vector3.zero,
|
|
Vector2.zero
|
|
);
|
|
}
|
|
|
|
// Duplicate one of the vertices
|
|
meshData.CutVertices[vertexCount - 1] = meshData.CutVertices[0];
|
|
|
|
// Verify vertex count prior to weld
|
|
Assert.AreEqual(vertexCount, meshData.CutVertices.Count);
|
|
|
|
meshData.WeldCutFaceVertices();
|
|
|
|
// Expect two vertices welded, so final count is one less vertex
|
|
Assert.AreEqual(vertexCount - 1, meshData.CutVertices.Count);
|
|
}
|
|
|
|
[Test]
|
|
public void WeldCutFaceVertices_GreaterThanEpsilon()
|
|
{
|
|
int vertexCount = 10;
|
|
FragmentData meshData = new FragmentData(vertexCount, 0);
|
|
|
|
for (int i = 0; i < vertexCount; i++)
|
|
{
|
|
meshData.AddCutFaceVertex(
|
|
new Vector3(i + 1, i + 2, i + 3),
|
|
Vector3.zero,
|
|
Vector2.zero
|
|
);
|
|
}
|
|
|
|
var magnitude = meshData.CutVertices[0].position.magnitude;
|
|
|
|
// According to Unity documentation, == comparison between two vectors
|
|
// returns true if their magnitude is less than 1E-5. We make two vertices
|
|
// differ by slightly larger than this amount so that they are not welded together.
|
|
meshData.CutVertices[vertexCount - 1] = new MeshVertex(
|
|
(magnitude + 1.1E-5f) * meshData.CutVertices[0].position.normalized,
|
|
Vector3.zero,
|
|
Vector2.zero
|
|
);
|
|
|
|
// Verify vertex count prior to weld
|
|
Assert.AreEqual(vertexCount, meshData.CutVertices.Count);
|
|
|
|
meshData.WeldCutFaceVertices();
|
|
|
|
// Expect same vertex count since no vertices welded
|
|
Assert.AreEqual(vertexCount, meshData.CutVertices.Count);
|
|
}
|
|
|
|
[Test]
|
|
public void WeldCutFaceVertices_LessThanEpsilon()
|
|
{
|
|
int vertexCount = 10;
|
|
FragmentData meshData = new FragmentData(vertexCount, 0);
|
|
|
|
for (int i = 0; i < vertexCount; i++)
|
|
{
|
|
meshData.AddCutFaceVertex(
|
|
new Vector3(i + 1, i + 2, i + 3),
|
|
Vector3.zero,
|
|
Vector2.zero
|
|
);
|
|
}
|
|
|
|
var magnitude = meshData.CutVertices[0].position.magnitude;
|
|
|
|
// According to Unity documentation, == comparison between two vectors
|
|
// returns true if their magnitude is less than 1E-5. We make two vertices
|
|
// differ by slightly less than this amount so that they are welded together.
|
|
meshData.CutVertices[vertexCount - 1] = new MeshVertex(
|
|
(magnitude + 0.9E-5f) * meshData.CutVertices[0].position.normalized,
|
|
Vector3.zero,
|
|
Vector2.zero
|
|
);
|
|
|
|
// Verify vertex count prior to weld
|
|
Assert.AreEqual(vertexCount, meshData.CutVertices.Count);
|
|
|
|
meshData.WeldCutFaceVertices();
|
|
|
|
// Expect two vertices welded, so final count is one less vertex
|
|
Assert.AreEqual(vertexCount - 1, meshData.CutVertices.Count);
|
|
}
|
|
|
|
[Test]
|
|
public void WeldCutFaceVertices_CutEdgeUpdate()
|
|
{
|
|
int vertexCount = 10;
|
|
FragmentData meshData = new FragmentData(vertexCount, 0);
|
|
|
|
for (int i = 0; i < vertexCount; i++)
|
|
{
|
|
meshData.AddCutFaceVertex(
|
|
new Vector3(i + 1, i + 2, i + 3),
|
|
Vector3.zero,
|
|
Vector2.zero
|
|
);
|
|
}
|
|
|
|
// Last vertex is equal to the first vertex
|
|
meshData.CutVertices[vertexCount - 1] = meshData.CutVertices[0];
|
|
|
|
// Add cut edges that map to the duplicate vertex
|
|
meshData.Constraints.Add(new EdgeConstraint(0, vertexCount - 1));
|
|
|
|
// Assert expected edge state prior to weld
|
|
Assert.AreEqual(0, meshData.Constraints[0].v1);
|
|
Assert.AreEqual(vertexCount - 1, meshData.Constraints[0].v2);
|
|
|
|
meshData.WeldCutFaceVertices();
|
|
|
|
// Assert expected edge state after the weld
|
|
Assert.AreEqual(0, meshData.Constraints[0].v1);
|
|
Assert.AreEqual(0, meshData.Constraints[0].v2);
|
|
}
|
|
|
|
[Test]
|
|
public void ToMesh()
|
|
{
|
|
int vertexCount = 100;
|
|
int cutVertexCount = 50;
|
|
int triangleCount1 = 10;
|
|
int triangleCount2 = 15;
|
|
|
|
FragmentData meshData = new FragmentData(vertexCount, 0);
|
|
|
|
// Add some fake data
|
|
for (int i = 0; i < vertexCount; i++)
|
|
{
|
|
meshData.AddMappedVertex(new MeshVertex(), 0);
|
|
}
|
|
|
|
for (int i = 0; i < cutVertexCount; i++)
|
|
{
|
|
meshData.AddCutFaceVertex(Vector3.zero, Vector3.zero, Vector2.zero);
|
|
}
|
|
|
|
for (int i = 0; i < triangleCount1; i++)
|
|
{
|
|
meshData.AddTriangle(0, 0, 0, SlicedMeshSubmesh.Default);
|
|
}
|
|
|
|
for (int i = 0; i < triangleCount2; i++)
|
|
{
|
|
meshData.AddTriangle(0, 0, 0, SlicedMeshSubmesh.CutFace);
|
|
}
|
|
|
|
Mesh mesh = meshData.ToMesh();
|
|
|
|
// Each time we add a cut face vertex, it adds two vertices, one for the
|
|
// original sub mesh and another for the cut face sub mesh.
|
|
Assert.AreEqual(vertexCount + 2 * cutVertexCount, mesh.vertexCount);
|
|
Assert.AreEqual(2, mesh.subMeshCount);
|
|
|
|
// Three indices for each triangle
|
|
Assert.AreEqual(3 * triangleCount1, mesh.GetTriangles(0).Length);
|
|
Assert.AreEqual(3 * triangleCount2, mesh.GetTriangles(1).Length);
|
|
}
|
|
} |