private static void initData(SoftwareMesh softwareMesh, bool loadColors, bool loadUVs, bool loadNormals, out List<BufferLayoutElement> elements, out float[] vertices, out int[] indices) { // get position float size int posFloatCount = 0; var posElementType = BufferLayoutElementTypes.Vector3; switch (softwareMesh.Dimensions) { case 2: posElementType = BufferLayoutElementTypes.Vector2; posFloatCount = 2; break; case 3: posElementType = BufferLayoutElementTypes.Vector3; posFloatCount = 3; break; } // get vertex float size and create layout elements = new List<BufferLayoutElement>(); int vertFloatCount = 0, posCount = 0, colorCount = 0, normalCount = 0, uvCount = 0; foreach (var key in softwareMesh.VertexComponentKeys) { switch (key.Key) { case VertexComponentKeyTypes.Positions: elements.Add(new BufferLayoutElement(posElementType, BufferLayoutElementUsages.Position, 0, posCount, vertFloatCount)); vertFloatCount += posFloatCount; ++posCount; break; } } foreach (var key in softwareMesh.TriangleComponentKeys) { switch (key.Key) { case TriangleComponentKeyTypes.ColorComponents: if (loadColors) { elements.Add(new BufferLayoutElement(BufferLayoutElementTypes.Vector4, BufferLayoutElementUsages.Color, 0, colorCount, vertFloatCount)); vertFloatCount += 4; ++colorCount; } break; case TriangleComponentKeyTypes.NormalComponents: if (loadNormals) { elements.Add(new BufferLayoutElement(BufferLayoutElementTypes.Vector3, BufferLayoutElementUsages.Normal, 0, normalCount, vertFloatCount)); vertFloatCount += 3; ++normalCount; } break; case TriangleComponentKeyTypes.UVComponents: if (loadUVs) { elements.Add(new BufferLayoutElement(BufferLayoutElementTypes.Vector2, BufferLayoutElementUsages.UV, 0, uvCount, vertFloatCount)); vertFloatCount += 2; ++uvCount; } break; } } // create vertex buffer var meshProcessor = new HardwareMeshProcessor(softwareMesh, loadColors, loadUVs, loadNormals); vertices = new float[meshProcessor.Verticies.Count * vertFloatCount]; int vi = 0; foreach (var vertex in meshProcessor.Verticies) { int posIndex = 0, colorIndex = 0, normIndex = 0, uvIndex = 0; foreach (var element in elements) { switch (element.Usage) { case BufferLayoutElementUsages.Position: vertices[vi] = vertex.Positions[posIndex].X; vertices[vi+1] = vertex.Positions[posIndex].Y; if (posFloatCount == 3) vertices[vi+2] = vertex.Positions[posIndex].Z; vi += posFloatCount; ++posIndex; break; case BufferLayoutElementUsages.Color: if (loadColors) { vertices[vi] = vertex.Colors[uvIndex].X; vertices[vi+1] = vertex.Colors[uvIndex].Y; vi += 4; ++colorIndex; } break; case BufferLayoutElementUsages.Normal: if (loadNormals) { vertices[vi] = vertex.Normals[normIndex].X; vertices[vi+1] = vertex.Normals[normIndex].Y; vertices[vi+2] = vertex.Normals[normIndex].Z; vi += 3; ++normIndex; } break; case BufferLayoutElementUsages.UV: if (loadUVs) { vertices[vi] = vertex.UVs[uvIndex].X; vertices[vi+1] = vertex.UVs[uvIndex].Y; vi += 2; ++uvIndex; } break; } } } // create index buffer indices = new int[meshProcessor.Triangles.Count * 3]; int ti = 0; foreach (var triangle in meshProcessor.Triangles) { indices[ti] = triangle.Verticies[0].Index; indices[ti+1] = triangle.Verticies[1].Index; indices[ti+2] = triangle.Verticies[2].Index; ti += 3; } }
public HardwareMeshProcessor(SoftwareMesh mesh, bool loadColors, bool loadUVs, bool loadNormals) { this.mesh = mesh; // get vertex component types positions = new List<Vector3[]>(); foreach (var key in mesh.VertexComponentKeys) { switch (key.Key) { case VertexComponentKeyTypes.Positions: var vertexComponents = mesh.VetexComponents[key.Value]; if (vertexComponents.GetType() == typeof(Vector3[])) { positions.Add((Vector3[])vertexComponents); } else if (vertexComponents.GetType() == typeof(Vector2[])) { var verts = (Vector2[])vertexComponents; var newVerts = new Vector3[verts.Length]; for (int i = 0; i != verts.Length; ++i) newVerts[i] = new Vector3(verts[i].X, verts[i].Y, 0); positions.Add(newVerts); } else { Debug.ThrowError("HardwareMeshProcessor", "Unsuported VectorComponent type"); } break; } } // get triangle component types if (loadColors) colorComponents = new List<TriangleColorComponent[]>(); if (loadNormals) normalComponents = new List<TriangleNormalComponent[]>(); if (loadUVs) uvComponents = new List<TriangleUVComponent[]>(); foreach (var key in mesh.TriangleComponentKeys) { switch (key.Key) { case TriangleComponentKeyTypes.ColorComponents: if (loadColors) colorComponents.Add((TriangleColorComponent[])mesh.TriangleComponents[key.Value]); break; case TriangleComponentKeyTypes.NormalComponents: if (loadNormals) normalComponents.Add((TriangleNormalComponent[])mesh.TriangleComponents[key.Value]); break; case TriangleComponentKeyTypes.UVComponents: if (loadUVs) uvComponents.Add((TriangleUVComponent[])mesh.TriangleComponents[key.Value]); break; } } // create triangles with there own verticies Verticies = new LinkedList<VertexProcessor>(); Triangles = new List<TriangleProcessor>(); foreach (var triangle in mesh.Triangles) { var newTriangle = new TriangleProcessor(triangle, this, loadColors, loadUVs, loadNormals); } // process (remove duplicate verticies from triangles) const float tolerance = .002f; int count = Triangles.Count-1, count2 = Triangles.Count; for (int i = 0; i != count; ++i) { for (int vi = 0; vi != 3; ++vi) { var vertex = Triangles[i].Verticies[vi]; for (int i2 = i+1; i2 != count2; ++i2) { for (int vi2 = 0; vi2 != 3; ++vi2) { var vertex2 = Triangles[i2].Verticies[vi2]; if (vertex == vertex2) continue; // position tolerance bool canRemoveVertex = true; for (int pi = 0; pi != vertex.Positions.Length; ++pi) { if (!vertex.Positions[pi].AproxEqualsBox(vertex2.Positions[pi], tolerance)) { canRemoveVertex = false; break; } } // color tolerance if (canRemoveVertex && loadColors) { for (int pi = 0; pi != vertex.Colors.Length; ++pi) { if (!vertex.Colors[pi].AproxEqualsBox(vertex2.Colors[pi], tolerance)) { canRemoveVertex = false; break; } } } // normal tolerance if (canRemoveVertex && loadNormals) { for (int pi = 0; pi != vertex.Normals.Length; ++pi) { if (!vertex.Normals[pi].AproxEqualsBox(vertex2.Normals[pi], tolerance)) { canRemoveVertex = false; break; } } } // uv tolerance if (canRemoveVertex && loadUVs) { for (int pi = 0; pi != vertex.UVs.Length; ++pi) { if (!vertex.UVs[pi].AproxEqualsBox(vertex2.UVs[pi], tolerance)) { canRemoveVertex = false; break; } } } // remove vertex if (canRemoveVertex) { Verticies.Remove(vertex2); Triangles[i2].Verticies[vi2] = vertex; } } } } } // process (set vertex indicies) int index = 0; foreach (var vertex in Verticies) { vertex.Index = index; ++index; } }
public static void Write(BinaryWriter writer, SoftwareModel softwareModel, SoftwareMesh softwareMesh, bool loadColors, bool loadUVs, bool loadNormals) { List<BufferLayoutElement> elements; float[] vertices; int[] indices; initData(softwareMesh, loadColors, loadUVs, loadNormals, out elements, out vertices, out indices); // name writer.Write(softwareMesh.Name); // material int materialIndex = -1; if (softwareMesh.Material != null) { for (int i = 0; i != softwareModel.Materials.Count; ++i) { if (softwareMesh.Material == softwareModel.Materials[i]) { materialIndex = i; break; } } } writer.Write(materialIndex); // elements writer.Write(elements.Count); foreach (var element in elements) { writer.Write((int)element.Type); writer.Write((int)element.Usage); writer.Write(element.StreamIndex); writer.Write(element.UsageIndex); writer.Write(element.FloatOffset); } // vertices writer.Write(vertices.Length); foreach (var vertex in vertices) { writer.Write(vertex); } // indices writer.Write(indices.Length); foreach (var index in indices) { writer.Write(index); } }