static bool TestAttributeLerp() { var mesh = new BMesh(); mesh.AddVertexAttribute(new AttributeDefinition("uv", AttributeBaseType.Float, 2)); mesh.AddVertexAttribute(new AttributeDefinition("mat", AttributeBaseType.Int, 1)); Vertex v0 = mesh.AddVertex(new Vector3(0, 0, 0)); Vertex v1 = mesh.AddVertex(new Vector3(0, 0, 0)); Vertex v2 = mesh.AddVertex(new Vector3(0, 0, 0)); v0.attributes["uv"] = new FloatAttributeValue(0.12f, 0.0f); v2.attributes["uv"] = new FloatAttributeValue(0.33f, 1.0f); v0.attributes["mat"] = new IntAttributeValue(0); v2.attributes["mat"] = new IntAttributeValue(1); BMeshOperators.AttributeLerp(mesh, v1, v0, v2, 0.4f); var uv1 = v1.attributes["uv"] as FloatAttributeValue; var mat1 = v1.attributes["mat"] as IntAttributeValue; Debug.Assert(uv1.data.Length == 2 && uv1.data[0] == Mathf.Lerp(0.12f, 0.33f, 0.4f) && uv1.data[1] == 0.4f, "interpolate uv"); Debug.Assert(mat1.data.Length == 1 && mat1.data[0] == 0, "interpolate mat"); Debug.Log("TestBMeshOperators TestAttributeLerp passed."); return(true); }
static bool TestSubdivideTris() { var mesh = new BMesh(); mesh.AddVertexAttribute(new AttributeDefinition("uv", AttributeBaseType.Float, 2)); Vertex v0 = mesh.AddVertex(new Vector3(-1, 0, -1)); Vertex v1 = mesh.AddVertex(new Vector3(-1, 0, 1)); Vertex v2 = mesh.AddVertex(new Vector3(1, 0, 1)); Vertex v3 = mesh.AddVertex(new Vector3(1, 0, -1)); Face f0 = mesh.AddFace(v0, v1, v2); Face f1 = mesh.AddFace(v2, v1, v3); foreach (var v in mesh.vertices) { v.attributes["uv"] = new FloatAttributeValue(v.point.x, v.point.z); } BMeshOperators.Subdivide(mesh); Debug.Assert(mesh.vertices.Count == 11, "vertex count"); Debug.Assert(mesh.edges.Count == 16, "edge count"); Debug.Assert(mesh.loops.Count == 24, "loop count"); Debug.Assert(mesh.faces.Count == 6, "face count"); foreach (Face f in mesh.faces) { Debug.Assert(f.vertcount == 4, "faces are quads"); } foreach (var v in mesh.vertices) { var uv = v.attributes["uv"] as FloatAttributeValue; Debug.Assert(Mathf.Abs(uv.data[0] - v.point.x) < epsilon && Mathf.Abs(uv.data[1] - v.point.z) < epsilon, "attribute interpolation: " + uv.data[0] + " == " + v.point.x + " && " + uv.data[1] + " == " + v.point.z); } Debug.Log("TestBMeshOperators TestSubdivideTris passed."); return(true); }
/////////////////////////////////////////////////////////////////////////// #region [Merge] /** * Merge a Unity Mesh into a BMesh. Can be used with an empty BMesh to * create a BMesh from a Unity Mesh * TODO: Add support for uvs etc. */ public static void Merge(BMesh mesh, Mesh unityMesh, bool flipFaces = false) { Vector3[] unityVertices = unityMesh.vertices; Vector2[] unityUvs = unityMesh.uv; Vector2[] unityUvs2 = unityMesh.uv2; Vector3[] unityNormals = unityMesh.normals; Color[] unityColors = unityMesh.colors; bool hasUvs = unityUvs != null && unityUvs.Length > 0; bool hasUvs2 = unityUvs2 != null && unityUvs2.Length > 0; bool hasNormals = unityNormals != null && unityNormals.Length > 0; bool hasColors = unityColors != null && unityColors.Length > 0; int[] unityTriangles = unityMesh.triangles; var verts = new Vertex[unityVertices.Length]; if (hasUvs) { mesh.AddVertexAttribute(new AttributeDefinition("uv", AttributeBaseType.Float, 2)); } if (hasUvs2) { mesh.AddVertexAttribute(new AttributeDefinition("uv2", AttributeBaseType.Float, 2)); } if (hasNormals) { mesh.AddVertexAttribute(new AttributeDefinition("normal", AttributeBaseType.Float, 3)); } if (hasColors) { mesh.AddVertexAttribute(new AttributeDefinition("color", AttributeBaseType.Float, 4)); } for (int i = 0; i < unityVertices.Length; ++i) { Vector3 p = unityVertices[i]; verts[i] = mesh.AddVertex(p); if (hasUvs) { verts[i].attributes["uv"].asFloat().FromVector2(unityUvs[i]); } if (hasUvs2) { verts[i].attributes["uv2"].asFloat().FromVector2(unityUvs2[i]); } if (hasNormals) { verts[i].attributes["normal"].asFloat().FromVector3(unityNormals[i]); } if (hasColors) { verts[i].attributes["color"].asFloat().FromColor(unityColors[i]); } } for (int i = 0; i < unityTriangles.Length / 3; ++i) { mesh.AddFace( verts[unityTriangles[3 * i + (flipFaces ? 1 : 0)]], verts[unityTriangles[3 * i + (flipFaces ? 0 : 1)]], verts[unityTriangles[3 * i + 2]] ); } }
static bool TestAttributes() { var mesh = new BMesh(); mesh.AddVertexAttribute(new AttributeDefinition("test", AttributeBaseType.Float, 3)); mesh.AddEdgeAttribute("edgetest", AttributeBaseType.Float, 2); mesh.AddFaceAttribute("facetest", AttributeBaseType.Int, 1); Vertex v0 = mesh.AddVertex(new Vector3(-1, 0, -1)); Vertex v1 = mesh.AddVertex(new Vector3(-1, 0, 1)); Vertex v2 = mesh.AddVertex(new Vector3(1, 0, 1)); Vertex v3 = mesh.AddVertex(new Vector3(1, 0, -1)); Face f0 = mesh.AddFace(v0, v1, v2); Face f1 = mesh.AddFace(v2, v1, v3); var otherAttr = new AttributeDefinition("other", AttributeBaseType.Int, 1); var def = otherAttr.defaultValue as IntAttributeValue; def.data[0] = 42; mesh.AddVertexAttribute(otherAttr); foreach (var v in mesh.vertices) { Debug.Assert(v.attributes.ContainsKey("test"), "vertex has test attribute"); var test = v.attributes["test"] as FloatAttributeValue; Debug.Assert(test != null, "vertex test attribute has float value"); var testAsInt = v.attributes["test"] as IntAttributeValue; Debug.Assert(testAsInt == null, "vertex test attribute has no int value"); Debug.Assert(test.data.Length == 3, "vertex test attribute has 3 dimensions"); Debug.Assert(test.data[0] == 0 && test.data[1] == 0 && test.data[2] == 0, "vertex test attribute has value (0, 0, 0)"); Debug.Assert(v.attributes.ContainsKey("other"), "vertex has other attribute"); var other = v.attributes["other"] as IntAttributeValue; Debug.Assert(other.data.Length == 1, "vertex other attribute has 1 dimension"); Debug.Assert(other.data[0] == 42, "vertex other attribute has value 42"); } foreach (var e in mesh.edges) { Debug.Assert(e.attributes.ContainsKey("edgetest"), "edge has test attribute"); var edgetest = e.attributes["edgetest"] as FloatAttributeValue; Debug.Assert(edgetest != null, "edge test attribute has float value"); var edgetestAsInt = e.attributes["edgetest"] as IntAttributeValue; Debug.Assert(edgetestAsInt == null, "edge test attribute has no int value"); Debug.Assert(edgetest.data.Length == 2, "edge test attribute has 2 dimensions"); Debug.Assert(edgetest.data[0] == 0 && edgetest.data[1] == 0, "edge test attribute has value (0, 0)"); } foreach (var f in mesh.faces) { Debug.Assert(f.attributes.ContainsKey("facetest"), "face has test attribute"); var facetest = f.attributes["facetest"] as IntAttributeValue; Debug.Assert(facetest != null, "face test attribute has int value"); var facetestAsFloat = f.attributes["facetest"] as FloatAttributeValue; Debug.Assert(facetestAsFloat == null, "face test attribute has no float value"); Debug.Assert(facetest.data.Length == 1, "face test attribute has 1 dimensions"); Debug.Assert(facetest.data[0] == 0, "face test attribute has value (0)"); } { var other1 = v1.attributes["other"] as IntAttributeValue; var other2 = v2.attributes["other"] as IntAttributeValue; other1.data[0] = 43; Debug.Assert(other2.data[0] == 42, "default vertex attribute values are independent"); } { var v4 = new Vertex(new Vector3(0, 0, 0)) { attributes = new Dictionary <string, AttributeValue> { ["other"] = new FloatAttributeValue { data = new float[] { 1, 2, 3 } } } }; Debug.Log("Test expects warning:"); Debug.Assert(mesh.AddVertex(v4) == v4, "add point is conservative"); Debug.Assert(v4.attributes.ContainsKey("test"), "new vertex has test attribute"); var test = v4.attributes["test"] as FloatAttributeValue; Debug.Assert(test.data[0] == 0 && test.data[1] == 0 && test.data[2] == 0, "new vertex test attribute has value (0, 0, 0)"); var other = v4.attributes["other"] as IntAttributeValue; Debug.Assert(other != null, "new vertex other attribute is an int"); Debug.Assert(other.data[0] == 42, "new vertex other attribute ignored non int provided value"); } Debug.Log("TestBMesh TestAttributes passed."); return(true); }