static void Main(string[] args) { CMdlFile file = new CMdlFile(); if (args.Length < 1) { Console.WriteLine("No source path defined"); return; } Entities modelData = new Entities(); for (int an = 0; an < args.Length; ++an) { Entities parsedData = new Entities(); FlErr result = file.LoadFile(path: args[an]); LogFileError(result, args[an]); if (FlErr.NoError != result) { continue; } if (file.IsMorph) // TODO: Read and parse a morphlist file instead of auto-detection/mapping { parsedData.meshes = modelData.meshes; // temporary shallow copy } if (CFileParser.TryParse(file, ref parsedData)) { if (modelData.IsDefined()) {// succeeding pass, copy new nodes and mesh data // Integrate nodes if ((null != parsedData.rootNode) && parsedData.rootNode.HasChilds()) { if (!file.IsMorph) {// skip first var nodes = parsedData.rootNode.Childs; modelData.rootNode.Childs.AddRange(nodes.GetRange(1, nodes.Count - 1)); //} else { //modelData.rootNode.Childs.AddRange(parsedData.rootNode.Childs); } } // Integrate meshes if ((null != parsedData.meshes) && (parsedData.meshes.Count > 0)) { modelData.meshes.AddRange(parsedData.meshes); } } else // first or previously incomplete pass { modelData.rootNode = parsedData.rootNode; modelData.meshes = parsedData.meshes; } } else { Console.WriteLine($"Parsing of model {file.Filename} interrupted. Left at byte: {file.Reader.ReaderPos}. Path: {args[an]}"); } }// load each file if (!modelData.HasAny()) { Console.WriteLine("Failed to load any model data, aborting..."); return; } string filename = Path.GetFileNameWithoutExtension(args[0]); try { using (FileStream fs = File.Create( Path.Combine( Path.GetDirectoryName(args[0]), filename + ".dae" ))) { var ColladaWriter = new CDaeSerializer(); ColladaWriter.RootName = filename; ColladaWriter.Serialize(fs, modelData); } } catch (Exception ex) { Console.WriteLine($"An exception occured in {ex.Source}: {ex.Message}"); return; } Console.WriteLine("File successfully converted"); }
//readonly CMdlFile file; //private CFileParser() //{ // throw new NotImplementedException("CFileParser()"); // Not allowed without file //} //public CFileParser(CMdlFile file) //{ // this.file = file ?? throw new ArgumentNullException(nameof(file)); //} #region public Methods public static bool TryParse(CMdlFile file, ref Entities hierachy) { if ((null == file) || !file.IsValid) { return(false); } //if (null == hierachy.meshes) // preserve when reading morphs //{ // hierachy.meshes = new List<Mdl.CMesh>(); //} string readNode; bool cancel = false; CMdlFileNavigator reader = file.Reader; // Read nodes reader.MoveDataStart(); // in case of restart if (TagInfo.root != reader.ReadTag()) // read and seek { // Does not start with RootNode return(false); } reader.SkipWhitespace(); // \r\n CFrameParser.Parse(reader, out Mdl.CFrame currFrame); //int nodeCount = hierachy.rootNode.Childs.Count; //if (file.IsMorph && (null != hierachy.rootNode) && nodeCount > 0) //{ // hierachy.rootNode.Childs.RemoveRange(1, nodeCount - 1); // hierachy.rootNode.Childs.AddRange(currFrame.Childs); //} else { // hierachy.rootNode = currFrame; //} hierachy.rootNode = currFrame; // morphs have no skeleton at index 0! reader.SkipWhitespace(); // Read mesh data var parsedMeshes = new List <Mdl.CMesh>(); while (!cancel && !String.IsNullOrEmpty(readNode = reader.ReadTag(mTags))) { switch (readNode) { case TagInfo.root: cancel = true; break; case TagInfo.mesh: Mdl.CMesh currMesh = null; if (file.IsMorph) { if ((cancel = !CMeshParser.TryParseMorph(reader, out Mdl.CMorph morph)) || (null == hierachy.meshes) || !hierachy.meshes.Any(msh => msh != null)) //< not a reason to cancel { break; } var matches = hierachy.meshes.Where( msh => msh.VerticesCount() == morph.VerticesCount() && file.Filename.Contains(msh.Name)); if (matches.Any()) { currMesh = matches.First()?.CreateMorphedMesh(morph); } } else { if (cancel = !CMeshParser.TryParse(reader, out currMesh)) { break; } currMesh.OriginName = file.Filename; } if (null != currMesh && currMesh.IsValid()) { parsedMeshes.Add(currMesh); } break; case TagInfo.collision: // skip (text block with 4 line body) reader.SeekBlockStart(); reader.SeekBlockEnd(); break; default: cancel = true; // not implemented break; } reader.SkipWhitespace(); // \r\n after each data block } if (!cancel) { hierachy.meshes = parsedMeshes; } return(!cancel); }