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(); } }
// 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()); }