示例#1
0
        public static FullModelData Open(string filepath)
        {
            FullModelData data = new FullModelData();

            StaticStorage.hashindex.Load();

            Log.Default.Info("Opening Model: {0}", filepath);

            Read(data, filepath);

            return(data);
        }
 public static IEnumerable <(string fullpath, string relativepath, FullModelData data)> EveryModel(string root)
 {
     foreach (var i in WalkDirectoryTreeDepth(new DirectoryInfo(root), "*.model"))
     {
         FullModelData fmd = null;
         try
         {
             fmd = ModelReader.Open(i.FullName);
         }
         catch (Exception e)
         {
             Log.Default.Warn($"Unable to read {i.FullName}: {e}");
         }
         if (fmd != null)
         {
             yield return(i.FullName, i.FullName.Substring(root.Length), fmd);
         }
     }
 }
        public static string ExportFile(FullModelData data, string path)
        {
            path = path.Replace(".model", ".dae");

            List <SectionHeader>          sections        = data.sections;
            Dictionary <UInt32, ISection> parsed_sections = data.parsed_sections;

            byte[] leftover_data = data.leftover_data;

            // Set up the XML structure
            library_geometries libgeoms = new library_geometries();

            library_visual_scenes libscenes = new library_visual_scenes();

            COLLADAScene scene = new COLLADAScene
            {
                instance_visual_scene = new InstanceWithExtra
                {
                    url = "#scene"
                }
            };

            COLLADA collada = new COLLADA
            {
                Items = new object[] { libgeoms, libscenes },
                scene = scene,
                asset = new asset
                {
                    created  = DateTime.UtcNow,
                    modified = DateTime.UtcNow,

                    // Otherwise it defaults to Y-up (see asset's constructor), while we're
                    //  using Z-up. Without the asset tag Blender defaults to Z-up, so if you
                    //  remove this then the presence of the asset tag flips the model.
                    up_axis = UpAxisType.Z_UP,
                },
            };

            // Build the mesh

            List <geometry> geometries = new List <geometry>();
            List <node>     nodes      = new List <node>();

            int model_i = 0;

            foreach (SectionHeader sectionheader in sections)
            {
                if (sectionheader.type == model_data_tag)
                {
                    Model model_data = (Model)parsed_sections[sectionheader.id];
                    if (model_data.version == 6)
                    {
                        continue;
                    }

                    model_i++;

                    string model_id = model_i + "-" + model_data.HashName.String;

                    PassthroughGP passthrough_section = model_data.PassthroughGP;
                    Geometry      geometry_section    = passthrough_section.Geometry;
                    Topology      topology_section    = passthrough_section.Topology;
                    geometry      geom = SerializeModel(geometry_section, topology_section, model_data, model_id);

                    geometries.Add(geom);

                    node root_node = new node
                    {
                        id   = "model-" + model_id,
                        name = "Model " + model_id,
                        type = NodeType.NODE,

                        instance_geometry = new instance_geometry[]
                        {
                            new instance_geometry
                            {
                                url  = "#model-geom-" + model_id,
                                name = "Model Geom" + model_id
                            }
                        }
                    };

                    nodes.Add(root_node);

                    if (model_data.SkinBones == null)
                    {
                        continue;
                    }

                    SkinBones sb = model_data.SkinBones;
                    //Console.WriteLine(sb.bones);
                    //Console.WriteLine(sb);

                    node bone_root_node = new node
                    {
                        id   = "model-" + model_id + "-boneroot",
                        name = "Model " + model_id + " Bones",
                        type = NodeType.NODE,

                        /*Items = new object[]
                         *  {
                         *      new matrix
                         *      {
                         *          sid = "transform", // Apparently Blender really wants this
                         *          Values = MathUtil.Serialize(sb.unknown_matrix)
                         *      }
                         *  },
                         * ItemsElementName = new ItemsChoiceType2[]
                         *  {
                         *      ItemsChoiceType2.matrix
                         *  }*/
                    };
                    root_node.node1 = new node[] { bone_root_node };

                    Dictionary <Object3D, node> bones = new Dictionary <Object3D, node>();

                    // In order to find locators, which aren't present in the SkinBones
                    // object, we check the child of each object we process.
                    //
                    // To then process those, we use a queue (to_parse) which lists the
                    // objects in our TODO list to search. We draw from this as we process them.
                    //
                    // We also keep the list of what we have processed in (parsed), so we don't
                    // process anything twice.
                    //
                    // TODO rewrite this code to be based around children, removing the need for a seperate
                    // loop after this that arranges the heirachy of nodes.
                    List <Object3D>  parsed   = new List <Object3D>(sb.Objects);
                    Queue <Object3D> to_parse = new Queue <Object3D>(sb.Objects);

                    int i = 0;
                    while (to_parse.Count != 0)
                    {
                        Object3D obj = to_parse.Dequeue();

                        string bonename = obj.HashName.String;

                        // Find the locators and such, and add them to the TODO list
                        foreach (Object3D child in obj.children)
                        {
                            if (!parsed.Contains(child)) // Don't process something twice
                            {
                                parsed.Add(child);
                                to_parse.Enqueue(child);
                            }
                        }

                        Vector3    translate;
                        Quaternion rotate;
                        Vector3    scale;
                        Matrix4x4.Decompose(obj.Transform, out scale, out rotate, out translate);

                        Matrix4x4 final_rot = Matrix4x4.CreateFromQuaternion(rotate);
                        final_rot.Translation = translate;

                        if (obj.Parent == null || !sb.Objects.Contains(obj.Parent))
                        {
                            Matrix4x4 fixed_obj_transform = obj.WorldTransform;
                            Matrix4x4.Decompose(fixed_obj_transform, out scale, out rotate, out translate);

                            // Fixes the head, but breaks the arms
                            // For now, leave it like this
                            //final_rot = final_rot.MultDiesel(fixed_obj_transform);
                        }

                        // If the object is not contained within the SkinBones
                        // object, it must be a locator.
                        bool locator = !sb.Objects.Contains(obj);

                        // Add the node
                        bones[obj] = new node
                        {
                            id    = "model-" + model_id + "-bone-" + bonename,
                            name  = (locator ? "locator-" : "") + bonename,
                            type  = NodeType.JOINT,
                            Items = new object[]
                            {
                                new matrix
                                {
                                    sid    = "transform", // Apparently Blender really wants this
                                    Values = MathUtil.Serialize(final_rot)
                                },
                            },
                            ItemsElementName = new ItemsChoiceType2[]
                            {
                                ItemsChoiceType2.matrix
                            }
                        };

                        i++;
                    }

                    foreach (var(obj, nod) in bones)
                    {
                        node parent = bone_root_node;

                        if (bones.ContainsKey(obj))
                        {
                            parent = bones[obj.Parent];
                        }

                        if (parent.node1 == null)
                        {
                            parent.node1 = new node[1];
                        }
                        else
                        {
                            node[] children = parent.node1;
                            Array.Resize(ref children, children.Length + 1);
                            parent.node1 = children;
                        }

                        parent.node1[parent.node1.Length - 1] = nod;
                    }
                }
            }

            libgeoms.geometry = geometries.ToArray();

            libscenes.visual_scene = new visual_scene[]
            {
                new visual_scene
                {
                    id   = "scene",
                    name = "Scene",
                    node = nodes.ToArray()
                }
            };

            using (FileStream fs = new FileStream(path, FileMode.Create, FileAccess.Write))
            {
                collada.Save(fs);

                // Do we need this?
                // fs.Close();
            }

            return(path);
        }
示例#4
0
        private static void Read(FullModelData data, string filepath)
        {
            List <SectionHeader>          sections        = data.sections;
            Dictionary <UInt32, ISection> parsed_sections = data.parsed_sections;

            byte[] bytes;

            using (FileStream fs = new FileStream(filepath, FileMode.Open, FileAccess.Read))
            {
                bytes = new byte[fs.Length];
                int res = fs.Read(bytes, 0, (int)fs.Length);
                if (res != fs.Length)
                {
                    throw new Exception($"Failed to read {filepath} all in one go!");
                }
            }

            using (var ms = new MemoryStream(bytes, 0, bytes.Length, false, true))
                using (var br = new BinaryReader(ms))
                {
                    sections.Clear();
                    sections.AddRange(ReadHeaders(br));

                    foreach (SectionHeader sh in sections)
                    {
                        ISection section;

                        ms.Position = sh.Start;

                        if (SectionMetaInfo.TryGetForTag(sh.type, out var mi))
                        {
                            section = mi.Deserialise(br, sh);
                        }
                        else
                        {
                            Log.Default.Warn("UNKNOWN Tag {2} at {0} Size: {1}", sh.offset, sh.size, sh.type);
                            ms.Position = sh.offset;

                            section = new Unknown(br, sh);
                        }

                        if (ms.Position != sh.End)
                        {
                            throw new Exception(string.Format("Section of type {2} {0} read more than its length of {1} ", sh.id, sh.size, sh.type));
                        }

                        Log.Default.Debug("Section {0} at {1} length {2}",
                                          section.GetType().Name, sh.offset, sh.size);

                        parsed_sections.Add(sh.id, section);
                    }

                    foreach (var i in parsed_sections)
                    {
                        if (i.Value is IPostLoadable pl)
                        {
                            pl.PostLoad(i.Key, parsed_sections);
                        }
                    }

                    if (ms.Position < ms.Length)
                    {
                        data.leftover_data = br.ReadBytes((int)(ms.Length - ms.Position));
                    }
                }
        }
示例#5
0
 public override void Import(FullModelData data, string path, bool createModels, Func <string, Sections.Object3D> parentFinder, IOptionReceiver options)
 => GltfImporter.Import(data, path, createModels, parentFinder, options);
示例#6
0
 public override string Export(FullModelData data, string path)
 => Exporters.GltfExporter.ExportFile(data, path, true);
示例#7
0
 public override void Import(FullModelData data, string path, bool createModels, Func <string, Sections.Object3D> parentFinder, IOptionReceiver options)
 => throw new Exception("Importing DAE files is not supported.");
示例#8
0
 public override string Export(FullModelData data, string path) => ColladaExporter.ExportFile(data, path);
示例#9
0
 public override string Export(FullModelData data, string path) => Exporters.ObjWriter.ExportFile(data, path);
示例#10
0
 public abstract void Import(FullModelData data, string path, bool createModels, Func <string, Sections.Object3D> parentFinder, IOptionReceiver options);
示例#11
0
 public abstract string Export(FullModelData data, string path);
示例#12
0
 public override string Export(FullModelData data, string path) => Exporters.AnimationExporter.ExportFile(data, path);
示例#13
0
 public override void Import(FullModelData data, string path, bool createModels, Func <string, Sections.Object3D> parentFinder, IOptionReceiver options)
 => throw new Exception("Please import animation files in the animation section.");