Beispiel #1
0
        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));
        }