static VMeshDump ProcessRef(VMeshRef vms, ResourceManager resources) { var d = new VMeshDump(); List <VertexPositionNormalDiffuseTextureTwo> verts = new List <VertexPositionNormalDiffuseTextureTwo>(); List <int> hashes = new List <int>(); for (int meshi = vms.StartMesh; meshi < vms.StartMesh + vms.MeshCount; meshi++) { var m = vms.Mesh.Meshes[meshi]; var dc = new VmsDrawcall(); LibreLancer.Utf.Mat.Material mat; if ((mat = resources.FindMaterial(m.MaterialCrc)) != null) { dc.Material = new ExportMaterial() { Name = mat.Name, Dc = mat.Dc }; } else { dc.Material = new ExportMaterial() { Name = string.Format("material_0x{0:X8}", m.MaterialCrc), Dc = Color4.White }; } List <int> indices = new List <int>(m.NumRefVertices); for (int i = m.TriangleStart; i < m.TriangleStart + m.NumRefVertices; i++) { int idx = vms.Mesh.Indices[i] + m.StartVertex + vms.StartVertex; VertexPositionNormalDiffuseTextureTwo vert; if (vms.Mesh.verticesVertexPosition != null) { vert = new VertexPositionNormalDiffuseTextureTwo() { Position = vms.Mesh.verticesVertexPosition[idx].Position } } ; else if (vms.Mesh.verticesVertexPositionNormal != null) { vert = new VertexPositionNormalDiffuseTextureTwo() { Position = vms.Mesh.verticesVertexPositionNormal[idx].Position, Normal = vms.Mesh.verticesVertexPositionNormal[idx].Normal }; } else if (vms.Mesh.verticesVertexPositionTexture != null) { vert = new VertexPositionNormalDiffuseTextureTwo() { Position = vms.Mesh.verticesVertexPositionTexture[idx].Position, TextureCoordinate = vms.Mesh.verticesVertexPositionTexture[idx].TextureCoordinate }; } else if (vms.Mesh.verticesVertexPositionNormalTexture != null) { vert = new VertexPositionNormalDiffuseTextureTwo() { Position = vms.Mesh.verticesVertexPositionNormalTexture[idx].Position, Normal = vms.Mesh.verticesVertexPositionNormalTexture[idx].Normal, TextureCoordinate = vms.Mesh.verticesVertexPositionNormalTexture[idx].TextureCoordinate }; } else if (vms.Mesh.verticesVertexPositionNormalTextureTwo != null) { vert = new VertexPositionNormalDiffuseTextureTwo() { Position = vms.Mesh.verticesVertexPositionNormalTextureTwo[idx].Position, Normal = vms.Mesh.verticesVertexPositionNormalTextureTwo[idx].Normal, TextureCoordinate = vms.Mesh.verticesVertexPositionNormalTextureTwo[idx].TextureCoordinate, TextureCoordinateTwo = vms.Mesh.verticesVertexPositionNormalTextureTwo[idx] .TextureCoordinateTwo }; } else if (vms.Mesh.verticesVertexPositionNormalDiffuseTexture != null) { vert = new VertexPositionNormalDiffuseTextureTwo() { Position = vms.Mesh.verticesVertexPositionNormalDiffuseTexture[idx].Position, Normal = vms.Mesh.verticesVertexPositionNormalDiffuseTexture[idx].Normal, Diffuse = vms.Mesh.verticesVertexPositionNormalDiffuseTexture[idx].Diffuse, TextureCoordinate = vms.Mesh.verticesVertexPositionNormalDiffuseTexture[idx] .TextureCoordinate }; } else if (vms.Mesh.verticesVertexPositionNormalDiffuseTextureTwo != null) { vert = vms.Mesh.verticesVertexPositionNormalDiffuseTextureTwo[idx]; } else { throw new Exception("something in state is real bad"); //Never called } var hash = HashVert(ref vert); int newIndex = FindDuplicate(hashes, verts, 0, ref vert, hash); if (newIndex == -1) { newIndex = verts.Count; verts.Add(vert); hashes.Add(hash); } indices.Add(newIndex); } dc.Indices = indices.ToArray(); d.Drawcalls.Add(dc); } d.Vertices = verts.ToArray(); d.FVF = vms.Mesh.OriginalFVF; return(d); }
public static Model3D LoadModel(string file) { UtfManager utfManager = new UtfManager(file); UtfNode root = utfManager.Read(); if (root == null || root.Nodes.Count == 0) { return(null); } // select root (\) node root = root.Nodes[0]; Dictionary <uint, VMeshData> meshes = null; List <MeshReferenceMatch> meshReferenceNodes = new List <MeshReferenceMatch>(); List <CmpPart> constructs = new List <CmpPart>(); Dictionary <string, string> mapFileToObj = new Dictionary <string, string> { { "\\", "Model" } }; foreach (UtfNode node in root.Nodes) { switch (node.Name.ToLowerInvariant()) { case "vmeshlibrary": meshes = new Dictionary <uint, VMeshData>(node.Nodes.Count); foreach (UtfNode vmsNode in node.Nodes) { if (vmsNode.Nodes.Count > 0) { meshes.Add(CrcTool.FlModelCrc(vmsNode.Name), new VMeshData(vmsNode.Nodes[0].Data)); } } break; case "cmpnd": foreach (UtfNode cmpndNode in node.Nodes) { if (cmpndNode.Name.Equals("cons", StringComparison.OrdinalIgnoreCase)) { foreach (UtfNode constructNode in cmpndNode.Nodes) { switch (constructNode.Name.ToLowerInvariant()) { case "fix": FixConstruct.Parse(constructs, constructNode.Data); break; case "rev": RevConstruct.Parse(constructs, constructNode.Data); break; case "pris": PrisConstruct.Parse(constructs, constructNode.Data); break; case "sphere": SphereConstruct.Parse(constructs, constructNode.Data); break; } } } else if (cmpndNode.Name.StartsWith("part_", StringComparison.OrdinalIgnoreCase) || cmpndNode.Name.Equals("root", StringComparison.OrdinalIgnoreCase)) { string objectName = null; string fileName = null; // int index = -1; foreach (UtfNode partNode in cmpndNode.Nodes) { switch (partNode.Name.ToLowerInvariant()) { case "object name": objectName = Encoding.ASCII.GetString(partNode.Data).TrimEnd('\0'); break; case "file name": fileName = Encoding.ASCII.GetString(partNode.Data).TrimEnd('\0'); break; // case "index": // index = BitConverter.ToInt32(partNode.Data, 0); // break; } } if (objectName != null && fileName != null) { mapFileToObj[fileName] = objectName; } } } break; case "multilevel": // multi LoD 3db model (\MultiLevel\Level0\VMeshPart\VMeshRef => \) VMeshRef meshReference2 = ParseMultiLevelNode(node); if (meshReference2 != null) { meshReferenceNodes.Add(new MeshReferenceMatch { FileName = "\\", MeshReference = meshReference2 }); } break; case "vmeshpart": // single LoD 3db model (\VMeshPart\VMeshRef => \) VMeshRef meshReference3 = ParseMeshPartNode(node); if (meshReference3 != null) { meshReferenceNodes.Add(new MeshReferenceMatch { FileName = "\\", MeshReference = meshReference3 }); } break; default: if (node.Name.EndsWith(".3db", StringComparison.OrdinalIgnoreCase)) { foreach (UtfNode subNode in node.Nodes) { if (subNode.Name.Equals("multilevel", StringComparison.OrdinalIgnoreCase)) { // multi LoD cmp model (\PARTNAME.3db\MultiLevel\Level0\VMeshPart\VMeshRef => PARTNAME.3db) VMeshRef meshReference = ParseMultiLevelNode(subNode); if (meshReference != null) { meshReferenceNodes.Add(new MeshReferenceMatch { FileName = node.Name, MeshReference = meshReference }); } break; } if (subNode.Name.Equals("vmeshpart", StringComparison.OrdinalIgnoreCase)) { // single LoD cmp model (\PARTNAME.3db\VMeshPart\VMeshRef => PARTNAME.3db) VMeshRef meshReference = ParseMeshPartNode(subNode); if (meshReference != null) { meshReferenceNodes.Add(new MeshReferenceMatch { FileName = node.Name, MeshReference = meshReference }); } break; } } } break; } } if (meshes == null || meshReferenceNodes.Count == 0) { return(null); } List <MeshGroup> meshGroups = new List <MeshGroup>(); foreach (MeshReferenceMatch meshReferenceNode in meshReferenceNodes) { string meshGroupName; if (mapFileToObj.TryGetValue(meshReferenceNode.FileName, out meshGroupName)) { VMeshData mesh; if (meshes.TryGetValue(meshReferenceNode.MeshReference.VMeshLibId, out mesh)) { meshGroups.Add(new MeshGroup { MeshReference = meshReferenceNode.MeshReference, Mesh = mesh, Transform = GetTransform(constructs, meshGroupName) }); } } } return(GetCmpModelGroup(meshGroups)); }