Example #1
0
        private static void GenerateOutputInfo(FullModelData data, string path)
        {
            List <SectionHeader>          sections        = data.sections;
            Dictionary <UInt32, ISection> parsed_sections = data.parsed_sections;

            byte[] leftover_data = data.leftover_data;

            //Generate outinfo.txt - Used for research and debug purposes
            using (FileStream fs = new FileStream(path, FileMode.Create, FileAccess.Write))
            {
                using (StreamWriter sw = new StreamWriter(fs))
                {
                    foreach (SectionHeader sectionheader in sections)
                    {
                        if (sectionheader.type == passthroughGP_tag)
                        {
                            PassthroughGP passthrough_section = (PassthroughGP)parsed_sections[sectionheader.id];
                            Geometry      geometry_section    = passthrough_section.Geometry;
                            Topology      topology_section    = passthrough_section.Topology;
                            sw.WriteLine("Object ID: " + sectionheader.id);
                            sw.WriteLine("Verts (x, z, y)");
                            foreach (Vector3 vert in geometry_section.verts)
                            {
                                sw.WriteLine(vert.X.ToString("0.000000", CultureInfo.InvariantCulture) + " " + vert.Z.ToString("0.000000", CultureInfo.InvariantCulture) + " " + (-vert.Y).ToString("0.000000", CultureInfo.InvariantCulture));
                            }
                            sw.WriteLine("UV (u, -v)");
                            foreach (Vector2 uv in geometry_section.uvs)
                            {
                                sw.WriteLine(uv.X.ToString("0.000000", CultureInfo.InvariantCulture) + " " + uv.Y.ToString("0.000000", CultureInfo.InvariantCulture));
                            }
                            sw.WriteLine("Normals (i, j, k)");

                            //Testing
                            List <Vector3> norm_tangents = new List <Vector3>();
                            List <Vector3> norm_binorms  = new List <Vector3>();

                            foreach (Vector3 norm in geometry_section.normals)
                            {
                                sw.WriteLine(norm.X.ToString("0.000000", CultureInfo.InvariantCulture) + " " + norm.Y.ToString("0.000000", CultureInfo.InvariantCulture) + " " + norm.Z.ToString("0.000000", CultureInfo.InvariantCulture));


                                Vector3 norm_t;
                                Vector3 binorm;

                                Vector3 t1 = Vector3.Cross(norm, Vector3.UnitX);
                                Vector3 t2 = Vector3.Cross(norm, new Vector3(0, 0, -1));

                                if (t1.Length() > t2.Length())
                                {
                                    norm_t = t1;
                                }
                                else
                                {
                                    norm_t = t2;
                                }
                                norm_t = Vector3.Normalize(norm_t);
                                norm_tangents.Add(norm_t);

                                binorm = Vector3.Cross(norm, norm_t);
                                binorm = Vector3.Normalize(binorm * -1.0f);
                                norm_binorms.Add(binorm);
                            }

                            if (norm_binorms.Count > 0 && norm_tangents.Count > 0)
                            {
                                Vector3[] arranged_unknown20 = norm_binorms.ToArray();
                                Vector3[] arranged_unknown21 = norm_tangents.ToArray();

                                for (int fcount = 0; fcount < topology_section.facelist.Count; fcount++)
                                {
                                    Face f = topology_section.facelist[fcount];

                                    //unknown_20
                                    arranged_unknown20[f.a] = norm_binorms[topology_section.facelist[fcount].a];
                                    arranged_unknown20[f.b] = norm_binorms[topology_section.facelist[fcount].b];
                                    arranged_unknown20[f.c] = norm_binorms[topology_section.facelist[fcount].c];

                                    //unknown_21
                                    arranged_unknown21[f.a] = norm_tangents[topology_section.facelist[fcount].a];
                                    arranged_unknown21[f.b] = norm_tangents[topology_section.facelist[fcount].b];
                                    arranged_unknown21[f.c] = norm_tangents[topology_section.facelist[fcount].c];
                                }
                                norm_binorms  = arranged_unknown20.ToList();
                                norm_tangents = arranged_unknown21.ToList();
                            }

                            sw.WriteLine("Pattern UVs (u, v)");
                            foreach (Vector2 pattern_uv_entry in geometry_section.pattern_uvs)
                            {
                                sw.WriteLine(pattern_uv_entry.X.ToString("0.000000", CultureInfo.InvariantCulture) + " " + pattern_uv_entry.Y.ToString("0.000000", CultureInfo.InvariantCulture));
                            }

                            int unk20tangcount = 0;
                            int unk21tangcount = 0;
                            sw.WriteLine("Unknown 20 (float, float, float) - Normal tangents???");
                            foreach (Vector3 unknown_20_entry in geometry_section.binormals)
                            {
                                sw.WriteLine(unknown_20_entry.X.ToString("0.000000", CultureInfo.InvariantCulture) + " " + unknown_20_entry.Y.ToString("0.000000", CultureInfo.InvariantCulture) + " " + unknown_20_entry.Z.ToString("0.000000", CultureInfo.InvariantCulture));
                                Vector3 normt = norm_tangents[unk20tangcount];
                                sw.WriteLine("* " + normt.X.ToString("0.000000", CultureInfo.InvariantCulture) + " " + normt.Y.ToString("0.000000", CultureInfo.InvariantCulture) + " " + normt.Z.ToString("0.000000", CultureInfo.InvariantCulture));
                                unk20tangcount++;
                            }
                            sw.WriteLine("Unknown 21 (float, float, float) - Normal tangents???");
                            foreach (Vector3 unknown_21_entry in geometry_section.tangents)
                            {
                                sw.WriteLine(unknown_21_entry.X.ToString("0.000000", CultureInfo.InvariantCulture) + " " + unknown_21_entry.Y.ToString("0.000000", CultureInfo.InvariantCulture) + " " + unknown_21_entry.Z.ToString("0.000000", CultureInfo.InvariantCulture));
                                Vector3 normt = norm_binorms[unk21tangcount];
                                sw.WriteLine("* " + normt.X.ToString("0.000000", CultureInfo.InvariantCulture) + " " + normt.Y.ToString("0.000000", CultureInfo.InvariantCulture) + " " + normt.Z.ToString("0.000000", CultureInfo.InvariantCulture));
                                unk21tangcount++;
                            }

                            sw.WriteLine("Unknown 15 (float, float) - Weights???");
                            foreach (GeometryWeightGroups unknown_15_entry in geometry_section.weight_groups)
                            {
                                sw.WriteLine(unknown_15_entry.Bones1.ToString() + " " + unknown_15_entry.Bones2.ToString() + " " + unknown_15_entry.Bones3.ToString() + " " + unknown_15_entry.Bones4.ToString());

                                //sw.WriteLine(unknown_15_entry.X.ToString("0.000000", CultureInfo.InvariantCulture) + " " + unknown_15_entry.Y.ToString("0.000000", CultureInfo.InvariantCulture));
                            }

                            sw.WriteLine("Unknown 17 (float, float, float) - Weights???");
                            foreach (Vector3 unknown_17_entry in geometry_section.weights)
                            {
                                sw.WriteLine(unknown_17_entry.X.ToString("0.000000", CultureInfo.InvariantCulture) + " " + unknown_17_entry.Y.ToString("0.000000", CultureInfo.InvariantCulture));
                            }

                            foreach (Byte[] gunkid in geometry_section.unknown_item_data)
                            {
                                if (gunkid.Length % 8 == 0)
                                {
                                    sw.WriteLine("Unknown X (float, float)");
                                    for (int x = 0; x < gunkid.Length;)
                                    {
                                        sw.Write(BitConverter.ToSingle(gunkid, x).ToString("0.000000", CultureInfo.InvariantCulture) + " ");
                                        x += 4;
                                        sw.Write(BitConverter.ToSingle(gunkid, x).ToString("0.000000", CultureInfo.InvariantCulture));
                                        x += 4;
                                        sw.WriteLine();
                                    }
                                }
                                else if (gunkid.Length % 12 == 0)
                                {
                                    sw.WriteLine("Unknown X (float, float, float)");
                                    for (int x = 0; x < gunkid.Length;)
                                    {
                                        sw.Write(BitConverter.ToSingle(gunkid, x).ToString("0.000000", CultureInfo.InvariantCulture) + " ");
                                        x += 4;
                                        sw.Write(BitConverter.ToSingle(gunkid, x).ToString("0.000000", CultureInfo.InvariantCulture) + " ");
                                        x += 4;
                                        sw.Write(BitConverter.ToSingle(gunkid, x).ToString("0.000000", CultureInfo.InvariantCulture));
                                        x += 4;
                                        sw.WriteLine();
                                    }
                                }
                                else if (gunkid.Length % 4 == 0)
                                {
                                    sw.WriteLine("Unknown X (float)");
                                    for (int x = 0; x < gunkid.Length;)
                                    {
                                        sw.Write(BitConverter.ToSingle(gunkid, x).ToString("0.000000", CultureInfo.InvariantCulture));
                                        x += 4;
                                        sw.WriteLine();
                                    }
                                }
                                else
                                {
                                    sw.Write("Something else... [for debugging]");
                                }
                            }

                            sw.WriteLine("Faces (f1, f2, f3)");
                            foreach (Face face in topology_section.facelist)
                            {
                                sw.WriteLine((face.a + 1) + " " + (face.b + 1) + " " + (face.c + 1));
                            }

                            sw.WriteLine();
                            geometry_section.PrintDetailedOutput(sw);
                            sw.WriteLine();
                        }
                    }

                    sw.Close();
                }
                fs.Close();
            }
        }
Example #2
0
        // Please don't ask what this does
        private static void ExportPatternUVObj(FullModelData data, string path)
        {
            List <SectionHeader>          sections        = data.sections;
            Dictionary <UInt32, ISection> parsed_sections = data.parsed_sections;

            byte[] leftover_data = data.leftover_data;

            //Generate obj
            ushort maxfaces    = 0;
            UInt32 uvcount     = 0;
            UInt32 normalcount = 0;

            Directory.CreateDirectory(Path.GetDirectoryName(path));

            using (FileStream fs = new FileStream(path, FileMode.Create, FileAccess.Write))
            {
                using (StreamWriter sw = new StreamWriter(fs))
                {
                    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;
                            }
                            PassthroughGP passthrough_section = model_data.PassthroughGP;
                            Geometry      geometry_section    = passthrough_section.Geometry;
                            Topology      topology_section    = passthrough_section.Topology;

                            sw.WriteLine("#");
                            sw.WriteLine("# object " + model_data.Name);
                            sw.WriteLine("#");
                            sw.WriteLine();
                            sw.WriteLine("o " + model_data.Name);
                            foreach (Vector3 vert in geometry_section.verts)
                            {
                                sw.WriteLine("v " + vert.X.ToString("0.000000", CultureInfo.InvariantCulture) + " " + vert.Y.ToString("0.000000", CultureInfo.InvariantCulture) + " " + vert.Z.ToString("0.000000", CultureInfo.InvariantCulture));
                            }
                            sw.WriteLine("# " + geometry_section.verts.Count + " vertices");
                            sw.WriteLine();

                            foreach (Vector2 uv in geometry_section.pattern_uvs)
                            {
                                sw.WriteLine("vt " + uv.X.ToString("0.000000", CultureInfo.InvariantCulture) + " " + (-uv.Y).ToString("0.000000", CultureInfo.InvariantCulture));
                            }
                            sw.WriteLine("# " + geometry_section.pattern_uvs.Count + " UVs");
                            sw.WriteLine();

                            foreach (Vector3 norm in geometry_section.normals)
                            {
                                sw.WriteLine("vn " + norm.X.ToString("0.000000", CultureInfo.InvariantCulture) + " " + norm.Y.ToString("0.000000", CultureInfo.InvariantCulture) + " " + norm.Z.ToString("0.000000", CultureInfo.InvariantCulture));
                            }
                            sw.WriteLine("# " + geometry_section.normals.Count + " Normals");
                            sw.WriteLine();

                            sw.WriteLine("g " + model_data.Name);
                            foreach (Face face in topology_section.facelist)
                            {
                                //x
                                sw.Write("f " + (maxfaces + face.a + 1));
                                sw.Write('/');
                                if (geometry_section.pattern_uvs.Count > 0)
                                {
                                    sw.Write((uvcount + face.a + 1));
                                }
                                sw.Write('/');
                                if (geometry_section.normals.Count > 0)
                                {
                                    sw.Write((normalcount + face.a + 1));
                                }

                                //y
                                sw.Write(" " + (maxfaces + face.b + 1));
                                sw.Write('/');
                                if (geometry_section.pattern_uvs.Count > 0)
                                {
                                    sw.Write((uvcount + face.b + 1));
                                }
                                sw.Write('/');
                                if (geometry_section.normals.Count > 0)
                                {
                                    sw.Write((normalcount + face.b + 1));
                                }

                                //z
                                sw.Write(" " + (maxfaces + face.c + 1));
                                sw.Write('/');
                                if (geometry_section.pattern_uvs.Count > 0)
                                {
                                    sw.Write((uvcount + face.c + 1));
                                }
                                sw.Write('/');
                                if (geometry_section.normals.Count > 0)
                                {
                                    sw.Write((normalcount + face.c + 1));
                                }

                                sw.WriteLine();
                            }
                            sw.WriteLine("# " + topology_section.facelist.Count + " Faces");
                            sw.WriteLine();

                            maxfaces    += (ushort)geometry_section.verts.Count;
                            uvcount     += (ushort)geometry_section.pattern_uvs.Count;
                            normalcount += (ushort)geometry_section.normals.Count;
                        }
                    }

                    sw.Close();
                }
                fs.Close();
            }
        }
        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);
        }
        public static bool ImportNewObjPatternUV(FullModelData fm, string filepath)
        {
            Log.Default.Info("Importing new obj with file for UV patterns: {0}", filepath);

            //Preload the .obj
            List <obj_data> objects = new List <obj_data>();

            try
            {
                using (FileStream fs = new FileStream(filepath, FileMode.Open, FileAccess.Read))
                {
                    using (StreamReader sr = new StreamReader(fs))
                    {
                        string   line;
                        obj_data obj           = new obj_data();
                        bool     reading_faces = false;
                        int      prevMaxVerts  = 0;
                        int      prevMaxUvs    = 0;
                        int      prevMaxNorms  = 0;


                        while ((line = sr.ReadLine()) != null)
                        {
                            //preloading objects
                            if (line.StartsWith("#"))
                            {
                                continue;
                            }
                            else if (line.StartsWith("o ") || line.StartsWith("g "))
                            {
                                if (reading_faces)
                                {
                                    reading_faces = false;
                                    prevMaxVerts += obj.verts.Count;
                                    prevMaxUvs   += obj.uv.Count;
                                    prevMaxNorms += obj.normals.Count;

                                    objects.Add(obj);
                                    obj = new obj_data();
                                }

                                obj.object_name = line.Substring(2);
                            }
                            else if (line.StartsWith("usemtl "))
                            {
                                obj.material_name = line.Substring(2);
                            }
                            else if (line.StartsWith("v "))
                            {
                                if (reading_faces)
                                {
                                    reading_faces = false;
                                    prevMaxVerts += obj.verts.Count;
                                    prevMaxUvs   += obj.uv.Count;
                                    prevMaxNorms += obj.normals.Count;

                                    objects.Add(obj);
                                    obj = new obj_data();
                                }

                                String[] verts = line.Replace("  ", " ").Split(' ');
                                Vector3  vert  = new Vector3();
                                vert.X = Convert.ToSingle(verts[1], CultureInfo.InvariantCulture);
                                vert.Y = Convert.ToSingle(verts[2], CultureInfo.InvariantCulture);
                                vert.Z = Convert.ToSingle(verts[3], CultureInfo.InvariantCulture);

                                obj.verts.Add(vert);
                            }
                            else if (line.StartsWith("vt "))
                            {
                                if (reading_faces)
                                {
                                    reading_faces = false;
                                    prevMaxVerts += obj.verts.Count;
                                    prevMaxUvs   += obj.uv.Count;
                                    prevMaxNorms += obj.normals.Count;

                                    objects.Add(obj);
                                    obj = new obj_data();
                                }

                                String[] uvs = line.Split(' ');
                                Vector2  uv  = new Vector2();
                                uv.X = Convert.ToSingle(uvs[1], CultureInfo.InvariantCulture);
                                uv.Y = Convert.ToSingle(uvs[2], CultureInfo.InvariantCulture);

                                obj.uv.Add(uv);
                            }
                            else if (line.StartsWith("vn "))
                            {
                                if (reading_faces)
                                {
                                    reading_faces = false;
                                    prevMaxVerts += obj.verts.Count;
                                    prevMaxUvs   += obj.uv.Count;
                                    prevMaxNorms += obj.normals.Count;

                                    objects.Add(obj);
                                    obj = new obj_data();
                                }

                                String[] norms = line.Split(' ');
                                Vector3  norm  = new Vector3();
                                norm.X = Convert.ToSingle(norms[1], CultureInfo.InvariantCulture);
                                norm.Y = Convert.ToSingle(norms[2], CultureInfo.InvariantCulture);
                                norm.Z = Convert.ToSingle(norms[3], CultureInfo.InvariantCulture);

                                obj.normals.Add(norm);
                            }
                            else if (line.StartsWith("f "))
                            {
                                reading_faces = true;
                                String[] faces = line.Substring(2).Split(' ');
                                for (int x = 0; x < 3; x++)
                                {
                                    ushort fa = 0, fb = 0, fc = 0;
                                    if (obj.verts.Count > 0)
                                    {
                                        fa = (ushort)(Convert.ToUInt16(faces[x].Split('/')[0]) - prevMaxVerts - 1);
                                    }
                                    if (obj.uv.Count > 0)
                                    {
                                        fb = (ushort)(Convert.ToUInt16(faces[x].Split('/')[1]) - prevMaxUvs - 1);
                                    }
                                    if (obj.normals.Count > 0)
                                    {
                                        fc = (ushort)(Convert.ToUInt16(faces[x].Split('/')[2]) - prevMaxNorms - 1);
                                    }
                                    if (fa < 0 || fb < 0 || fc < 0)
                                    {
                                        throw new Exception("What the actual flapjack, something is *VERY* wrong");
                                    }
                                    obj.faces.Add(new Face(fa, fb, fc));
                                }
                            }
                        }

                        if (!objects.Contains(obj))
                        {
                            objects.Add(obj);
                        }
                    }
                }



                //Read each object
                foreach (obj_data obj in objects)
                {
                    //Locate the proper model
                    uint modelSectionid = 0;
                    foreach (KeyValuePair <uint, ISection> pair in fm.parsed_sections)
                    {
                        if (modelSectionid != 0)
                        {
                            break;
                        }

                        if (pair.Value is Model)
                        {
                            UInt64 tryp;
                            if (UInt64.TryParse(obj.object_name, out tryp))
                            {
                                if (tryp == ((Model)pair.Value).HashName.Hash)
                                {
                                    modelSectionid = pair.Key;
                                }
                            }
                            else
                            {
                                if (Hash64.HashString(obj.object_name) == ((Model)pair.Value).HashName.Hash)
                                {
                                    modelSectionid = pair.Key;
                                }
                            }
                        }
                    }

                    //Apply new changes
                    if (modelSectionid == 0)
                    {
                        continue;
                    }

                    Model         model_data_section  = (Model)fm.parsed_sections[modelSectionid];
                    PassthroughGP passthrough_section = model_data_section.PassthroughGP;
                    Geometry      geometry_section    = passthrough_section.Geometry;
                    Topology      topology_section    = passthrough_section.Topology;

                    //Arrange UV and Normals
                    Vector2[] new_arranged_UV = new Vector2[geometry_section.verts.Count];
                    for (int x = 0; x < new_arranged_UV.Length; x++)
                    {
                        new_arranged_UV[x] = new Vector2(100f, 100f);
                    }
                    Vector2 sentinel = new Vector2(100f, 100f);

                    if (topology_section.facelist.Count != obj.faces.Count / 3)
                    {
                        return(false);
                    }

                    for (int fcount = 0; fcount < topology_section.facelist.Count; fcount += 3)
                    {
                        Face f1 = obj.faces[fcount + 0];
                        Face f2 = obj.faces[fcount + 1];
                        Face f3 = obj.faces[fcount + 2];

                        //UV
                        if (obj.uv.Count > 0)
                        {
                            if (new_arranged_UV[topology_section.facelist[fcount / 3 + 0].a].Equals(sentinel))
                            {
                                new_arranged_UV[topology_section.facelist[fcount / 3 + 0].a] = obj.uv[f1.b];
                            }
                            if (new_arranged_UV[topology_section.facelist[fcount / 3 + 0].b].Equals(sentinel))
                            {
                                new_arranged_UV[topology_section.facelist[fcount / 3 + 0].b] = obj.uv[f2.b];
                            }
                            if (new_arranged_UV[topology_section.facelist[fcount / 3 + 0].c].Equals(sentinel))
                            {
                                new_arranged_UV[topology_section.facelist[fcount / 3 + 0].c] = obj.uv[f3.b];
                            }
                        }
                    }



                    geometry_section.UVs[1] = new_arranged_UV.ToList();

                    passthrough_section.Geometry.UVs[1] = new_arranged_UV.ToList();
                }
            }
            catch (Exception exc)
            {
                System.Windows.Forms.MessageBox.Show(exc.ToString());
                return(false);
            }
            return(true);
        }
        private static void AddObject(bool is_new, obj_data obj,
                                      Model model_data_section, PassthroughGP passthrough_section,
                                      Geometry geometry_section, Topology topology_section)
        {
            List <Face>            called_faces    = new List <Face>();
            List <int>             duplicate_verts = new List <int>();
            Dictionary <int, Face> dup_faces       = new Dictionary <int, Face>();

            bool broken = false;

            for (int x_f = 0; x_f < obj.faces.Count; x_f++)
            {
                Face f = obj.faces[x_f];
                broken = false;

                foreach (Face called_f in called_faces)
                {
                    if (called_f.a == f.a && called_f.b != f.b)
                    {
                        duplicate_verts.Add(x_f);
                        broken = true;
                        break;
                    }
                }

                if (!broken)
                {
                    called_faces.Add(f);
                }
            }

            Dictionary <int, Face> done_faces = new Dictionary <int, Face>();

            foreach (int dupe in duplicate_verts)
            {
                int replacedF = -1;
                foreach (KeyValuePair <int, Face> pair in done_faces)
                {
                    Face f = pair.Value;
                    if (f.a == obj.faces[dupe].a && f.b == obj.faces[dupe].b)
                    {
                        replacedF = pair.Key;
                    }
                }

                Face new_face;
                if (replacedF > -1)
                {
                    new_face = new Face(obj.faces[replacedF].a, obj.faces[replacedF].b, obj.faces[dupe].c);
                }
                else
                {
                    new_face = new Face((ushort)obj.verts.Count, obj.faces[dupe].b, obj.faces[dupe].c);
                    obj.verts.Add(obj.verts[obj.faces[dupe].a]);

                    done_faces.Add(dupe, obj.faces[dupe]);
                }

                obj.faces[dupe] = new_face;
            }

            Vector3 new_Model_data_bounds_min = new Vector3(); // Z (max), X (low), Y (low)
            Vector3 new_Model_data_bounds_max = new Vector3(); // Z (low), X (max), Y (max)

            foreach (Vector3 vert in obj.verts)
            {
                //Z
                // Note these were previously broken
                if (vert.Z < new_Model_data_bounds_min.Z)
                {
                    new_Model_data_bounds_min.Z = vert.Z;
                }

                if (vert.Z > new_Model_data_bounds_max.Z)
                {
                    new_Model_data_bounds_max.Z = vert.Z;
                }

                //X
                if (vert.X < new_Model_data_bounds_min.X)
                {
                    new_Model_data_bounds_min.X = vert.X;
                }
                if (vert.X > new_Model_data_bounds_max.X)
                {
                    new_Model_data_bounds_max.X = vert.X;
                }

                //Y
                if (vert.Y < new_Model_data_bounds_min.Y)
                {
                    new_Model_data_bounds_min.Y = vert.Y;
                }

                if (vert.Y > new_Model_data_bounds_max.Y)
                {
                    new_Model_data_bounds_max.Y = vert.Y;
                }
            }

            //Arrange UV and Normals
            List <Vector3> new_arranged_Geometry_normals   = new List <Vector3>();
            List <Vector3> new_arranged_Geometry_unknown20 = new List <Vector3>();
            List <Vector3> new_arranged_Geometry_unknown21 = new List <Vector3>();
            List <int>     added_uvs     = new List <int>();
            List <int>     added_normals = new List <int>();

            Vector2[] new_arranged_UV = new Vector2[obj.verts.Count];
            for (int x = 0; x < new_arranged_UV.Length; x++)
            {
                new_arranged_UV[x] = new Vector2(100f, 100f);
            }
            Vector2 sentinel = new Vector2(100f, 100f);

            Vector3[] new_arranged_Normals = new Vector3[obj.verts.Count];
            for (int x = 0; x < new_arranged_Normals.Length; x++)
            {
                new_arranged_Normals[x] = new Vector3(0f, 0f, 0f);
            }
            Vector3[] new_arranged_unknown20 = new Vector3[obj.verts.Count];
            Vector3[] new_arranged_unknown21 = new Vector3[obj.verts.Count];

            List <Face> new_faces = new List <Face>();

            for (int fcount = 0; fcount < obj.faces.Count; fcount += 3)
            {
                Face f1 = obj.faces[fcount + 0];
                Face f2 = obj.faces[fcount + 1];
                Face f3 = obj.faces[fcount + 2];

                //UV
                if (obj.uv.Count > 0)
                {
                    if (new_arranged_UV[f1.a].Equals(sentinel))
                    {
                        new_arranged_UV[f1.a] = obj.uv[f1.b];
                    }
                    if (new_arranged_UV[f2.a].Equals(sentinel))
                    {
                        new_arranged_UV[f2.a] = obj.uv[f2.b];
                    }
                    if (new_arranged_UV[f3.a].Equals(sentinel))
                    {
                        new_arranged_UV[f3.a] = obj.uv[f3.b];
                    }
                }

                //normal
                if (obj.normals.Count > 0)
                {
                    new_arranged_Normals[f1.a] = obj.normals[f1.c];
                    new_arranged_Normals[f2.a] = obj.normals[f2.c];
                    new_arranged_Normals[f3.a] = obj.normals[f3.c];
                }

                Face new_f = new Face(f1.a, f2.a, f3.a);

                new_faces.Add(new_f);
            }

            for (int x = 0; x < new_arranged_Normals.Length; x++)
            {
                new_arranged_Normals[x] = Vector3.Normalize(new_arranged_Normals[x]);
            }

            List <Vector3> obj_verts = obj.verts;

            ComputeTangentBasis(ref new_faces, ref obj_verts, ref new_arranged_UV, ref new_arranged_Normals, ref new_arranged_unknown20, ref new_arranged_unknown21);

            List <RenderAtom> new_Model_items2 = new List <RenderAtom>();

            foreach (RenderAtom modelitem in model_data_section.RenderAtoms)
            {
                RenderAtom new_model_item = new RenderAtom();
                new_model_item.BaseVertex          = modelitem.BaseVertex;
                new_model_item.TriangleCount       = (uint)new_faces.Count;
                new_model_item.BaseIndex           = modelitem.BaseIndex;
                new_model_item.GeometrySliceLength = (uint)obj.verts.Count;
                new_model_item.MaterialId          = modelitem.MaterialId;

                new_Model_items2.Add(new_model_item);
            }

            model_data_section.RenderAtoms = new_Model_items2;

            if (model_data_section.version != 6)
            {
                model_data_section.BoundsMin      = new_Model_data_bounds_min;
                model_data_section.BoundsMax      = new_Model_data_bounds_max;
                model_data_section.BoundingRadius = obj.verts.Select(i => i.Length()).Max();
            }

            geometry_section.vert_count = (uint)obj.verts.Count;
            geometry_section.verts      = obj.verts;
            geometry_section.normals    = new_arranged_Normals.ToList();
            geometry_section.UVs[0]     = new_arranged_UV.ToList();
            geometry_section.binormals  = new_arranged_unknown20.ToList();
            geometry_section.tangents   = new_arranged_unknown21.ToList();

            topology_section.facelist = new_faces;
        }
        public static void ImportNewObj(FullModelData fmd, String filepath, bool addNew, Func <string, Object3D> root_point, Importers.IOptionReceiver _)
        {
            Log.Default.Info("Importing new obj with file: {0}", filepath);

            //Preload the .obj
            List <obj_data> objects      = new List <obj_data>();
            List <obj_data> toAddObjects = new List <obj_data>();

            using (FileStream fs = new FileStream(filepath, FileMode.Open, FileAccess.Read))
            {
                using (StreamReader sr = new StreamReader(fs))
                {
                    string   line;
                    obj_data obj                 = new obj_data();
                    bool     reading_faces       = false;
                    int      prevMaxVerts        = 0;
                    int      prevMaxUvs          = 0;
                    int      prevMaxNorms        = 0;
                    string   current_shade_group = null;

                    while ((line = sr.ReadLine()) != null)
                    {
                        //preloading objects
                        if (line.StartsWith("#"))
                        {
                            continue;
                        }
                        else if (line.StartsWith("o ") || line.StartsWith("g "))
                        {
                            if (reading_faces)
                            {
                                reading_faces = false;
                                prevMaxVerts += obj.verts.Count;
                                prevMaxUvs   += obj.uv.Count;
                                prevMaxNorms += obj.normals.Count;

                                objects.Add(obj);
                                obj = new obj_data();
                                current_shade_group = null;
                            }

                            if (String.IsNullOrEmpty(obj.object_name))
                            {
                                obj.object_name = line.Substring(2);
                                Log.Default.Debug("Object {0} named: {1}", objects.Count + 1, obj.object_name);
                            }
                        }
                        else if (line.StartsWith("usemtl "))
                        {
                            obj.material_name = line.Substring(7);
                        }
                        else if (line.StartsWith("v "))
                        {
                            if (reading_faces)
                            {
                                reading_faces = false;
                                prevMaxVerts += obj.verts.Count;
                                prevMaxUvs   += obj.uv.Count;
                                prevMaxNorms += obj.normals.Count;

                                objects.Add(obj);
                                obj = new obj_data();
                            }

                            String[] verts = line.Replace("  ", " ").Split(' ');
                            Vector3  vert  = new Vector3();
                            vert.X = Convert.ToSingle(verts[1], CultureInfo.InvariantCulture);
                            vert.Y = Convert.ToSingle(verts[2], CultureInfo.InvariantCulture);
                            vert.Z = Convert.ToSingle(verts[3], CultureInfo.InvariantCulture);

                            obj.verts.Add(vert);
                        }
                        else if (line.StartsWith("vt "))
                        {
                            if (reading_faces)
                            {
                                reading_faces = false;
                                prevMaxVerts += obj.verts.Count;
                                prevMaxUvs   += obj.uv.Count;
                                prevMaxNorms += obj.normals.Count;

                                objects.Add(obj);
                                obj = new obj_data();
                            }

                            String[] uvs = line.Split(' ');
                            Vector2  uv  = new Vector2();
                            uv.X = Convert.ToSingle(uvs[1], CultureInfo.InvariantCulture);
                            uv.Y = Convert.ToSingle(uvs[2], CultureInfo.InvariantCulture);

                            obj.uv.Add(uv);
                        }
                        else if (line.StartsWith("vn "))
                        {
                            if (reading_faces)
                            {
                                reading_faces = false;
                                prevMaxVerts += obj.verts.Count;
                                prevMaxUvs   += obj.uv.Count;
                                prevMaxNorms += obj.normals.Count;

                                objects.Add(obj);
                                obj = new obj_data();
                            }

                            String[] norms = line.Split(' ');
                            Vector3  norm  = new Vector3();
                            norm.X = Convert.ToSingle(norms[1], CultureInfo.InvariantCulture);
                            norm.Y = Convert.ToSingle(norms[2], CultureInfo.InvariantCulture);
                            norm.Z = Convert.ToSingle(norms[3], CultureInfo.InvariantCulture);

                            obj.normals.Add(norm);
                        }
                        else if (line.StartsWith("s "))
                        {
                            current_shade_group = line.Substring(2);
                        }
                        else if (line.StartsWith("f "))
                        {
                            reading_faces = true;

                            if (current_shade_group != null)
                            {
                                if (obj.shading_groups.ContainsKey(current_shade_group))
                                {
                                    obj.shading_groups[current_shade_group].Add(obj.faces.Count);
                                }
                                else
                                {
                                    List <int> newfaces = new List <int>();
                                    newfaces.Add(obj.faces.Count);
                                    obj.shading_groups.Add(current_shade_group, newfaces);
                                }
                            }

                            String[] faces = line.Substring(2).Split(' ');
                            for (int x = 0; x < 3; x++)
                            {
                                ushort fa = 0, fb = 0, fc = 0;
                                if (obj.verts.Count > 0)
                                {
                                    fa = (ushort)(Convert.ToUInt16(faces[x].Split('/')[0]) - prevMaxVerts - 1);
                                }
                                if (obj.uv.Count > 0)
                                {
                                    fb = (ushort)(Convert.ToUInt16(faces[x].Split('/')[1]) - prevMaxUvs - 1);
                                }
                                if (obj.normals.Count > 0)
                                {
                                    fc = (ushort)(Convert.ToUInt16(faces[x].Split('/')[2]) - prevMaxNorms - 1);
                                }
                                if (fa < 0 || fb < 0 || fc < 0)
                                {
                                    throw new Exception("What the actual flapjack, something is *VERY* wrong");
                                }
                                obj.faces.Add(new Face(fa, fb, fc));
                            }
                        }
                    }

                    if (!objects.Contains(obj))
                    {
                        objects.Add(obj);
                    }
                }
            }


            //Read each object
            foreach (obj_data obj in objects)
            {
                //One would fix Tatsuto's broken shading here.

                //Locate the proper model
                var   hashname     = HashName.FromNumberOrString(obj.object_name);
                Model modelSection = fmd.parsed_sections
                                     .Where(i => i.Value is Model mod && hashname.Hash == mod.HashName.Hash)
                                     .Select(i => i.Value as Model)
                                     .FirstOrDefault();

                //Apply new changes
                if (modelSection == null)
                {
                    toAddObjects.Add(obj);
                    continue;
                }

                PassthroughGP passthrough_section = modelSection.PassthroughGP;
                Geometry      geometry_section    = passthrough_section.Geometry;
                Topology      topology_section    = passthrough_section.Topology;

                AddObject(false, obj,
                          modelSection, passthrough_section,
                          geometry_section, topology_section);
            }


            //Add new objects
            if (addNew)
            {
                foreach (obj_data obj in toAddObjects)
                {
                    //create new Model
                    Material newMat = new Material(obj.material_name);
                    fmd.AddSection(newMat);
                    MaterialGroup newMatG = new MaterialGroup(newMat);
                    fmd.AddSection(newMatG);
                    Geometry newGeom = new Geometry(obj);
                    fmd.AddSection(newGeom);
                    Topology newTopo = new Topology(obj);
                    fmd.AddSection(newTopo);

                    PassthroughGP newPassGP = new PassthroughGP(newGeom, newTopo);
                    fmd.AddSection(newPassGP);
                    TopologyIP newTopoIP = new TopologyIP(newTopo);
                    fmd.AddSection(newTopoIP);

                    Object3D parent   = root_point.Invoke(obj.object_name);
                    Model    newModel = new Model(obj, newPassGP, newTopoIP, newMatG, parent);
                    fmd.AddSection(newModel);

                    AddObject(true, obj,
                              newModel, newPassGP, newGeom, newTopo);

                    //Add new sections
                }
            }
        }
        public byte[] Parse(List <SectionHeader> sections, Dictionary <uint, Section> parsedSections)
        {
            ushort       num7   = 0;
            uint         num8   = 0;
            uint         num9   = 0;
            MemoryStream result = new MemoryStream();

            using (StreamWriter streamWriter1 = new StreamWriter(result))
            {
                foreach (SectionHeader section in sections)
                {
                    if ((int)section.type == (int)FileManager.model_data_tag)
                    {
                        Model parsedSection1 = (Model)parsedSections[section.id];
                        if (parsedSection1.version != 6U)
                        {
                            PassthroughGP parsedSection2 =
                                (PassthroughGP)parsedSections[parsedSection1.passthroughGP_ID];
                            Geometry parsedSection3 = (Geometry)parsedSections[parsedSection2.geometry_section];
                            Topology parsedSection4 = (Topology)parsedSections[parsedSection2.topology_section];
                            streamWriter1.WriteLine("#");
                            streamWriter1.WriteLine("# object " +
                                                    StaticStorage.hashindex.GetString(parsedSection1.object3D
                                                                                      .hashname));
                            streamWriter1.WriteLine("#");
                            streamWriter1.WriteLine();
                            streamWriter1.WriteLine(
                                "o " + StaticStorage.hashindex.GetString(parsedSection1.object3D.hashname));
                            foreach (Vector3D vert in parsedSection3.verts)
                            {
                                StreamWriter streamWriter2 = streamWriter1;
                                string[]     strArray1     = new string[6];
                                strArray1[0] = "v ";
                                string[] strArray2 = strArray1;
                                int      index1    = 1;
                                float    num2      = vert.X;
                                string   str1      = num2.ToString("0.000000", CultureInfo.InvariantCulture);
                                strArray2[index1] = str1;
                                strArray1[2]      = " ";
                                string[] strArray3 = strArray1;
                                int      index2    = 3;
                                num2 = vert.Y;
                                string str2 = num2.ToString("0.000000", CultureInfo.InvariantCulture);
                                strArray3[index2] = str2;
                                strArray1[4]      = " ";
                                string[] strArray4 = strArray1;
                                int      index3    = 5;
                                num2 = vert.Z;
                                string str3 = num2.ToString("0.000000", CultureInfo.InvariantCulture);
                                strArray4[index3] = str3;
                                string str5 = string.Concat(strArray1);
                                streamWriter2.WriteLine(str5);
                            }

                            streamWriter1.WriteLine("# " + parsedSection3.verts.Count + " vertices");
                            streamWriter1.WriteLine();
                            foreach (Vector2D uv in parsedSection3.uvs)
                            {
                                StreamWriter streamWriter2 = streamWriter1;
                                string       str1          = "vt ";
                                float        num2          = uv.X;
                                string       str2          = num2.ToString("0.000000", CultureInfo.InvariantCulture);
                                string       str3          = " ";
                                num2 = uv.Y;
                                string str5 = num2.ToString("0.000000", CultureInfo.InvariantCulture);
                                string str6 = str1 + str2 + str3 + str5;
                                streamWriter2.WriteLine(str6);
                            }

                            streamWriter1.WriteLine("# " + parsedSection3.uvs.Count + " UVs");
                            streamWriter1.WriteLine();
                            foreach (Vector3D normal in parsedSection3.normals)
                            {
                                StreamWriter streamWriter2 = streamWriter1;
                                string[]     strArray1     = new string[6];
                                strArray1[0] = "vn ";
                                string[] strArray2 = strArray1;
                                int      index1    = 1;
                                float    num2      = normal.X;
                                string   str1      = num2.ToString("0.000000", CultureInfo.InvariantCulture);
                                strArray2[index1] = str1;
                                strArray1[2]      = " ";
                                string[] strArray3 = strArray1;
                                int      index2    = 3;
                                num2 = normal.Y;
                                string str2 = num2.ToString("0.000000", CultureInfo.InvariantCulture);
                                strArray3[index2] = str2;
                                strArray1[4]      = " ";
                                string[] strArray4 = strArray1;
                                int      index3    = 5;
                                num2 = normal.Z;
                                string str3 = num2.ToString("0.000000", CultureInfo.InvariantCulture);
                                strArray4[index3] = str3;
                                string str5 = string.Concat(strArray1);
                                streamWriter2.WriteLine(str5);
                            }

                            streamWriter1.WriteLine("# " + parsedSection3.normals.Count + " Normals");
                            streamWriter1.WriteLine();
                            streamWriter1.WriteLine(
                                "g " + StaticStorage.hashindex.GetString(parsedSection1.object3D.hashname));
                            foreach (Face face in parsedSection4.facelist)
                            {
                                streamWriter1.Write("f " + (num7 + face.x + 1));
                                streamWriter1.Write('/');
                                if (parsedSection3.uvs.Count > 0)
                                {
                                    streamWriter1.Write((uint)((int)num8 + face.x + 1));
                                }
                                streamWriter1.Write('/');
                                if (parsedSection3.normals.Count > 0)
                                {
                                    streamWriter1.Write((uint)((int)num9 + face.x + 1));
                                }
                                streamWriter1.Write(" " + (num7 + face.y + 1));
                                streamWriter1.Write('/');
                                if (parsedSection3.uvs.Count > 0)
                                {
                                    streamWriter1.Write((uint)((int)num8 + face.y + 1));
                                }
                                streamWriter1.Write('/');
                                if (parsedSection3.normals.Count > 0)
                                {
                                    streamWriter1.Write((uint)((int)num9 + face.y + 1));
                                }
                                streamWriter1.Write(" " + (num7 + face.z + 1));
                                streamWriter1.Write('/');
                                if (parsedSection3.uvs.Count > 0)
                                {
                                    streamWriter1.Write((uint)((int)num8 + face.z + 1));
                                }
                                streamWriter1.Write('/');
                                if (parsedSection3.normals.Count > 0)
                                {
                                    streamWriter1.Write((uint)((int)num9 + face.z + 1));
                                }
                                streamWriter1.WriteLine();
                            }

                            streamWriter1.WriteLine("# " + parsedSection4.facelist.Count + " Faces");
                            streamWriter1.WriteLine();
                            num7 += (ushort)parsedSection3.verts.Count;
                            num8 += (ushort)parsedSection3.uvs.Count;
                            num9 += (ushort)parsedSection3.normals.Count;
                        }
                    }
                }
            }

            return(result.ToArray());
        }