void ImportGeometry(Collada141.geometry geometry) { var mesh = geometry.Item as Collada141.mesh; if (mesh == null) return; var float_array = mesh.source[0].Item as Collada141.float_array; this.Coordinates = new Vector3[float_array.Values.Length / 3]; for (int i = 0; i < Coordinates.Length; i++) { Coordinates[i] = new Vector3( (float)float_array.Values[i * 3 + 0], (float)float_array.Values[i * 3 + 1], (float)float_array.Values[i * 3 + 2]); } var poly_list = mesh.Items[0] as Collada141.polylist; if (poly_list == null) return; Triangle[] triangles = new Triangle[poly_list.count]; var raw_indices = Collada141.COLLADA.ConvertIntArray(poly_list.p); for (int i = 0; i < triangles.Length; i++) { triangles[i] = new Triangle() { MaterialID = 0, Vertex1 = (ushort)raw_indices[i * (3 * 2) + (0 * 2)], Vertex2 = (ushort)raw_indices[i * (3 * 2) + (1 * 2)], Vertex3 = (ushort)raw_indices[i * (3 * 2) + (2 * 2)], }; } List<ushort> triangle_indices = new List<ushort>(triangles.Length * 3); foreach (var triangle in triangles) { triangle_indices.AddRange(triangle.ToArray()); } Adjacencies adj = new Adjacencies(triangle_indices.ToArray()); this.Indices = adj.GenerateTriangleStrip(); this.Primitives = new MeshPrimitive[] { new MeshPrimitive(0, (ushort)Indices.Length) }; }
public bool ImportFromWavefront(string filename) { Log.Info(string.Format("Loading file {0} into memory buffer", filename)); byte[] buffer = null; using (var file = File.OpenRead(filename)) { buffer = new byte[file.Length]; file.Read(buffer, 0, buffer.Length); } if (buffer == null) { Log.Error("Failed to create memory buffer"); return false; } MemoryStream stream = new MemoryStream(buffer); StreamReader reader = new StreamReader(stream); WavefrontOBJ.Object[] objects = new WavefrontOBJ.Object[1] { new WavefrontOBJ.Object() { faces_start_index = 0 } }; List<WavefrontOBJ.Face> faces = new List<WavefrontOBJ.Face>(); List<Vector3> vertex_coords = new List<Vector3>(); List<Vector2> texture_coords = new List<Vector2>(); List<Vector3> normals = new List<Vector3>(); Dictionary<string, int> material_names = new Dictionary<string, int>(); material_names.Add("default", 0); int selected_material = 0; bool default_object = true; bool default_object_processed = false; bool has_normals = false; bool has_texcoords = false; Log.Info("Begin parsing Wavefront Object data from buffer"); while (!reader.EndOfStream) { string line = reader.ReadLine().Trim(); if (line.StartsWith("# ")) { Log.Info(line); continue; } if (line.StartsWith("o ")) { // if this is the first object token, use the default object if (default_object) default_object = false; else { Log.Warn(@"Support for multiple wavefront objects per mesh not implemented. Meshes can only accept a single wavefront object. Continuing, but only using first object!"); if (!default_object_processed) { objects[0].faces_count = faces.Count; default_object_processed = true; } } } else if (line.StartsWith("v ")) { Vector3 vertex; if (!WavefrontExtensions.TryParseVector3(out vertex, line)) return false; vertex_coords.Add(vertex); } else if (line.StartsWith("vt ")) { has_texcoords = true; Vector2 texcoord; if (!WavefrontExtensions.TryParseVector2(out texcoord, line)) return false; texture_coords.Add(texcoord); } else if (line.StartsWith("vn ")) { has_normals = true; Vector3 normal; if (!WavefrontExtensions.TryParseVector3(out normal, line)) return false; normals.Add(normal); } else if (line.StartsWith("usemtl ")) { string name = line.Replace("usemtl ", "").Trim(); if (!material_names.ContainsKey(name)) material_names.Add(name, material_names.Count); selected_material = material_names[name]; } else if (line.StartsWith("f ")) { WavefrontOBJ.Face face; if (!WavefrontOBJ.Face.TryParse(line, out face)) { Log.Error(string.Format("Error parsing line: {0}", line)); return false; } else { face.material_id = selected_material; faces.Add(face); } } else Log.Warn(string.Format("Unsupported format found while parsing line: {0}", line)); } if (!default_object_processed) { objects[0].faces_count = faces.Count; default_object_processed = true; } Log.Info("Partial success... finished parsing Wavefront Object data from buffer"); List<Triangle> triangle_list = new List<Triangle>(faces.Count); List<Vector3> vertex_coordiantes = new List<Vector3>(vertex_coords.Count); List<Vector2> texture_coordinates = new List<Vector2>(vertex_coords.Count); List<Vector3> vertex_normals = new List<Vector3>(vertex_coords.Count); List<string> tokens = new List<string>(); for (int i = 0; i < faces.Count; i++) { Triangle triangle = new Triangle() { MaterialID = faces[i].material_id }; for (int token = 0; token < 3; ++token) { if (!tokens.Contains(faces[i].GetToken(token))) { triangle.Vertex1 = (ushort)vertex_coordiantes.Count; tokens.Add(faces[i].GetToken(0)); vertex_coordiantes.Add(vertex_coords[faces[i].vertex_indices[token] - 1]); texture_coordinates.Add(faces[i].has_texcoord ? texture_coords[faces[i].texcoord_indices[token] - 1] : Vector2.Zero); vertex_normals.Add(faces[i].has_normals ? normals[faces[i].normal_indices[token] - 1] : Vector3.Zero); } else { triangle.Vertex1 = (ushort)tokens.IndexOf(faces[i].GetToken(token)); } } triangle_list.Add(triangle); } List<TriangleStrip> strips = new List<TriangleStrip>(material_names.Count); foreach (var material in material_names) { var material_faces = triangle_list.Where(x => x.MaterialID == material.Value).Select(x => x.AsEnumerable<ushort>()); List<ushort> tris = new List<ushort>(material_faces.Count() * 3); foreach (var item in material_faces) { tris.AddRange(item.ToArray()); } if (tris.Count > 0) { Adjacencies stripper = new Adjacencies(tris.ToArray()); strips.Add(new TriangleStrip() { MaterialID = (ushort)material.Value, Indices = stripper.GenerateTriangleStrip() }); } } this.Coordinates = vertex_coordiantes.ToArray(); this.TextureCoordinates = texture_coordinates.ToArray(); this.Normals = vertex_normals.ToArray(); this.Primitives = new MeshPrimitive[strips.Count]; Log.Info("Parsing shader groups from triangle strips..."); TriangleStrip combined_strip = new TriangleStrip() { Indices = new ushort[0] }; ushort offset = 0; for (int i = 0; i < strips.Count; ++i) { TriangleStrip.Append(ref combined_strip, strips[i]); this.Primitives[i] = new MeshPrimitive(offset, (ushort)(combined_strip.Indices.Length - offset)) { shader_index = (ushort)i }; Log.Info(string.Format(@"ShaderGroup[ {0} ] {{ Start = {1}, Length = {2} }}", i, offset, (combined_strip.Indices.Length - offset).ToString())); offset = (ushort)combined_strip.Indices.Length; } this.Indices = combined_strip.Indices; if (!has_texcoords) { Log.Warn("No texture coordinates found while parsing Wavefront file..." + "\nGenerating uv coordinates from vertex positions (flat mapping)"); this.GenerateTexCoords(); } if (!has_normals) { Log.Warn("No normals found while parsing Wavefront file..." + "\nGenerating normals..."); this.GenerateNormals(); } Log.Info("Generating tangent space vectors..."); this.GenerateTangentSpaceVectors(); Log.Info("Success, import finished! Returning true from ImportFromWavefront();"); return true; }