void AddFacesFromPolyList(polylist list, mesh mesh, ModelPrim prim, Matrix4 transform) { string material = list.material; source posSrc = null; source normalSrc = null; source uvSrc = null; ulong stride = 0; int posOffset = -1; int norOffset = -1; int uvOffset = -1; foreach (var inp in list.input) { stride = Math.Max(stride, inp.offset); if (inp.semantic == "VERTEX") { posSrc = FindSource(mesh.source, mesh.vertices.input[0].source); posOffset = (int)inp.offset; } else if (inp.semantic == "NORMAL") { normalSrc = FindSource(mesh.source, inp.source); norOffset = (int)inp.offset; } else if (inp.semantic == "TEXCOORD") { uvSrc = FindSource(mesh.source, inp.source); uvOffset = (int)inp.offset; } } stride += 1; if (posSrc == null) return; var vcount = StrToArray(list.vcount); var idx = StrToArray(list.p); Vector3[] normals = null; if (normalSrc != null) { var norVal = ((float_array)normalSrc.Item).Values; normals = new Vector3[norVal.Length / 3]; for (int i = 0; i < normals.Length; i++) { normals[i] = new Vector3((float)norVal[i * 3 + 0], (float)norVal[i * 3 + 1], (float)norVal[i * 3 + 2]); normals[i] = Vector3.TransformNormal(normals[i], transform); normals[i].Normalize(); } } Vector2[] uvs = null; if (uvSrc != null) { var uvVal = ((float_array)uvSrc.Item).Values; uvs = new Vector2[uvVal.Length / 2]; for (int i = 0; i < uvs.Length; i++) { uvs[i] = new Vector2((float)uvVal[i * 2 + 0], (float)uvVal[i * 2 + 1]); } } ModelFace face = new ModelFace(); face.MaterialID = list.material; if (face.MaterialID != null) { if (MatSymTarget.ContainsKey(list.material)) { ModelMaterial mat = Materials.Find(m => m.ID == MatSymTarget[list.material]); if (mat != null) { face.Material = mat; } } } int curIdx = 0; for (int i = 0; i < vcount.Length; i++) { var nvert = vcount[i]; if (nvert < 3 || nvert > 4) { throw new InvalidDataException("Only triangles and quads supported"); } Vertex[] verts = new Vertex[nvert]; for (int j = 0; j < nvert; j++) { verts[j].Position = prim.Positions[idx[curIdx + posOffset + (int)stride * j]]; if (normals != null) { verts[j].Normal = normals[idx[curIdx + norOffset + (int)stride * j]]; } if (uvs != null) { verts[j].TexCoord = uvs[idx[curIdx + uvOffset + (int)stride * j]]; } } if (nvert == 3) // add the triangle { face.AddVertex(verts[0]); face.AddVertex(verts[1]); face.AddVertex(verts[2]); } else if (nvert == 4) // quad, add two triangles { face.AddVertex(verts[0]); face.AddVertex(verts[1]); face.AddVertex(verts[2]); face.AddVertex(verts[0]); face.AddVertex(verts[2]); face.AddVertex(verts[3]); } curIdx += (int)stride * nvert; } prim.Faces.Add(face); }
void AddPositions(mesh mesh, ModelPrim prim, Matrix4 transform) { prim.Positions = new List<Vector3>(); source posSrc = FindSource(mesh.source, mesh.vertices.input[0].source); double[] posVals = ((float_array)posSrc.Item).Values; for (int i = 0; i < posVals.Length / 3; i++) { Vector3 pos = new Vector3((float)posVals[i * 3], (float)posVals[i * 3 + 1], (float)posVals[i * 3 + 2]); pos = Vector3.Transform(pos, transform); prim.Positions.Add(pos); } prim.BoundMin = new Vector3(float.MaxValue, float.MaxValue, float.MaxValue); prim.BoundMax = new Vector3(float.MinValue, float.MinValue, float.MinValue); foreach (var pos in prim.Positions) { if (pos.X > prim.BoundMax.X) prim.BoundMax.X = pos.X; if (pos.Y > prim.BoundMax.Y) prim.BoundMax.Y = pos.Y; if (pos.Z > prim.BoundMax.Z) prim.BoundMax.Z = pos.Z; if (pos.X < prim.BoundMin.X) prim.BoundMin.X = pos.X; if (pos.Y < prim.BoundMin.Y) prim.BoundMin.Y = pos.Y; if (pos.Z < prim.BoundMin.Z) prim.BoundMin.Z = pos.Z; } prim.Scale = prim.BoundMax - prim.BoundMin; prim.Position = prim.BoundMin + (prim.Scale / 2); // Fit vertex positions into identity cube -0.5 .. 0.5 for (int i = 0; i < prim.Positions.Count; i++) { Vector3 pos = prim.Positions[i]; pos = new Vector3( prim.Scale.X == 0 ? 0 : ((pos.X - prim.BoundMin.X) / prim.Scale.X) - 0.5f, prim.Scale.Y == 0 ? 0 : ((pos.Y - prim.BoundMin.Y) / prim.Scale.Y) - 0.5f, prim.Scale.Z == 0 ? 0 : ((pos.Z - prim.BoundMin.Z) / prim.Scale.Z) - 0.5f ); prim.Positions[i] = pos; } }