MeshAsset IUnityMeshConvert.Convert(string path) { var mesh = new MeshAsset(); var unity_mesh = JObject.Parse(File.ReadAllText(path)); var vertices = ((JArray)unity_mesh["vertices"]).ToObject <float3[]>(); using (var stream = new MemoryStream()) using (var bw = new BinaryWriter(stream)) { foreach (var vertex in vertices) { bw.Write(vertex.x); bw.Write(vertex.y); bw.Write(vertex.z); } bw.Flush(); var pos_element = new leo.Platform.Render.Vertex.Element(); pos_element.Format = EFormat.EF_BGR32F; pos_element.Usage = leo.Platform.Render.Vertex.Usage.Position; pos_element.UsageIndex = 0; mesh.AddVertexStream(pos_element, stream.ToArray()); } var normals = ((JArray)unity_mesh["normals"]).ToObject <float3[]>(); using (var stream = new MemoryStream()) using (var bw = new BinaryWriter(stream)) { foreach (var normal in normals) { bw.Write(normal.x); bw.Write(normal.y); bw.Write(normal.z); } bw.Flush(); var normal_element = new leo.Platform.Render.Vertex.Element(); normal_element.Format = EFormat.EF_BGR32F; normal_element.Usage = leo.Platform.Render.Vertex.Usage.Normal; normal_element.UsageIndex = 0; mesh.AddVertexStream(normal_element, stream.ToArray()); } var triangles = ((JArray)unity_mesh["triangles"]).ToObject <uint[]>(); var index_format = EFormat.EF_R16UI; if (triangles.Length > short.MaxValue) { index_format = EFormat.EF_R32UI; } var use_16 = index_format == EFormat.EF_R16UI; using (var stream = new MemoryStream()) using (var bw = new BinaryWriter(stream)) { foreach (var index in triangles) { if (use_16) { bw.Write((ushort)index); } else { bw.Write(index); } } bw.Flush(); mesh.SetIndexStream(index_format, stream.ToArray()); } mesh.IndexCount = (uint)triangles.Length; mesh.VertexCount = (uint)vertices.Length; var submesh = new MeshAsset.SubMeshDescrption() { MaterialIndex = 0, }; submesh.AddLodDesciption(new MeshAsset.SubMeshDescrption.LodDescription() { IndexBase = 0, IndexNum = mesh.IndexCount, VertexBase = 0, VertexNum = mesh.VertexCount }); mesh.AddSubMeshDescrption(submesh); return(mesh); }
public void Convert(string path) { var KlayGE_meshml = XDocument.Load(path); var dir = Path.GetDirectoryName(path); if (KlayGE_meshml.Root.Attribute("version").Value != "6") { throw new NotSupportedException(); } //material pass output /* * (material * (effect Shading) * (albedo (float3)) * (albedo_tex)~macro * (smoothness) * (metaless) * (normal) * ) */ var materials = new List <Tuple <string, MaterialAsset> >(); foreach (var material_node in KlayGE_meshml.XPathSelectElements("//material")) { var material = new MaterialAsset(); var material_name = materials.Count.ToString(); material.EffectName = "ForwardPointLightDiffuseShading"; var albedo_node = material_node.Element("albedo"); { var albedo_float4 = albedo_node?.Attribute("color"); if (albedo_float4 != null) { var albedo = albedo_float4.Value; var albedo_array = albedo.Substring(0, albedo.LastIndexOf(' ')).Split(' ').Select(component => component + 'f'); material["albedo"] = $"(float3 {string.Join(' ',albedo_array)})"; } var albedo_texture = albedo_node?.Attribute("texture"); if (albedo_texture != null) { var albedo_tex = albedo_texture.Value; material["albedo_tex"] = $"\"{albedo_tex}\""; material_name = $"{material_name}_{Path.GetFileNameWithoutExtension(albedo_tex)}"; } } var metalness_node = material_node.Element("metalness"); { var metalness = metalness_node?.Attribute("value"); if (metalness != null) { material["metalness"] = $"(float2 {metalness.Value}f 0)"; } } var glossiness_node = material_node.Element("glossiness"); { var glossiness = glossiness_node?.Attribute("value"); var glossiness_texture = glossiness_node?.Attribute("texture"); if (glossiness != null) { var value = double.Parse(glossiness.Value); material["glossiness"] = $"(float2 {value}f {(glossiness_texture != null ? 1 : 0)})"; } if (glossiness_texture != null) { var glossiness_tex = glossiness_texture.Value; material["glossiness_tex"] = $"\"{glossiness_tex}\""; material_name = $"{material_name}_{Path.GetFileNameWithoutExtension(glossiness_tex)}"; } } //todo support normal map var material_tuple = Tuple.Create(material_name, material); materials.Add(material_tuple); var material_file = material_name + ".mat.lsl"; X.SaveMaterialAsset(Path.Combine(dir, material_file), material); } var meshes = new List <Tuple <string, string> >(); foreach (var mesh_node in KlayGE_meshml.XPathSelectElements("//mesh")) { var mesh = new MeshAsset(); var vertices_node = mesh_node.XPathSelectElements("vertices_chunk/vertex"); var vertices = vertices_node.Select(vertex_node => { var pos_array = vertex_node.Attribute("v").Value.Split(' ').Select(component => float.Parse(component)).ToArray(); var pos = new float3(pos_array[0], pos_array[1], pos_array[2]); var tangent_quat_array = vertex_node.Element("tangent_quat").Attribute("v").Value.Split(' ').Select(component => float.Parse(component)).ToArray(); var tangnet_quat = new float4(tangent_quat_array[0], tangent_quat_array[1], tangent_quat_array[2], tangent_quat_array[3]); var tangent = transform_quat(new float3(1, 0, 0), tangnet_quat); var binormal = transform_quat(new float3(0, 1, 0), tangnet_quat) * (tangnet_quat.w < 0?-1.0f:1.0f); var normal = transform_quat(new float3(0, 0, 1), tangnet_quat); var tex_coord_array = vertex_node.Element("tex_coord").Attribute("v").Value.Split(' ').Select(component => float.Parse(component)).ToArray(); var tex_coord = new float2(tex_coord_array[0], tex_coord_array[1]); return(Tuple.Create(pos, normal, tex_coord)); }).ToList(); using (var stream = new MemoryStream()) using (var bw = new BinaryWriter(stream)) { foreach (var vertex in vertices) { var pos = vertex.Item1; bw.Write(pos.x); bw.Write(pos.y); bw.Write(pos.z); } bw.Flush(); var pos_element = new leo.Platform.Render.Vertex.Element(); pos_element.Format = EFormat.EF_BGR32F; pos_element.Usage = leo.Platform.Render.Vertex.Usage.Position; pos_element.UsageIndex = 0; mesh.AddVertexStream(pos_element, stream.ToArray()); } using (var stream = new MemoryStream()) using (var bw = new BinaryWriter(stream)) { foreach (var vertex in vertices) { var normal = vertex.Item2; bw.Write(normal.x); bw.Write(normal.y); bw.Write(normal.z); } bw.Flush(); var normal_element = new leo.Platform.Render.Vertex.Element(); normal_element.Format = EFormat.EF_BGR32F; normal_element.Usage = leo.Platform.Render.Vertex.Usage.Normal; normal_element.UsageIndex = 0; mesh.AddVertexStream(normal_element, stream.ToArray()); } using (var stream = new MemoryStream()) using (var bw = new BinaryWriter(stream)) { foreach (var vertex in vertices) { var tex_coord = vertex.Item3; bw.Write(tex_coord.x); bw.Write(tex_coord.y); } bw.Flush(); var texcoord_element = new leo.Platform.Render.Vertex.Element(); texcoord_element.Format = EFormat.EF_GR32F; texcoord_element.Usage = leo.Platform.Render.Vertex.Usage.TextureCoord; texcoord_element.UsageIndex = 0; mesh.AddVertexStream(texcoord_element, stream.ToArray()); } var triangles_node = mesh_node.XPathSelectElements("triangles_chunk/triangle"); var triangles = triangles_node.Select(triangle_node => triangle_node.Attribute("index").Value.Split(' ') .Select(index => uint.Parse(index))) .SelectMany(triangle => triangle) .ToList(); var index_format = EFormat.EF_R16UI; if (triangles.Count > short.MaxValue) { index_format = EFormat.EF_R32UI; } var use_16 = index_format == EFormat.EF_R16UI; using (var stream = new MemoryStream()) using (var bw = new BinaryWriter(stream)) { foreach (var index in triangles) { if (use_16) { bw.Write((ushort)index); } else { bw.Write(index); } } bw.Flush(); mesh.SetIndexStream(index_format, stream.ToArray()); } mesh.IndexCount = (uint)triangles.Count; mesh.VertexCount = (uint)vertices.Count; var submesh = new MeshAsset.SubMeshDescrption() { MaterialIndex = 0, }; submesh.AddLodDesciption(new MeshAsset.SubMeshDescrption.LodDescription() { IndexBase = 0, IndexNum = mesh.IndexCount, VertexBase = 0, VertexNum = mesh.VertexCount }); mesh.AddSubMeshDescrption(submesh); var mesh_name = mesh_node.Attribute("name").Value; X.SaveMeshAsset(Path.Combine(dir, mesh_name + ".asset"), mesh); var mtl_id = int.Parse(mesh_node.Attribute("mtl_id").Value); var material_name = materials[mtl_id].Item1; var mesh_tuple = Tuple.Create(mesh_name, material_name); meshes.Add(mesh_tuple); } var filename = Path.Combine(dir, Path.GetFileNameWithoutExtension(path) + ".entities.lsl"); using (var stream = File.OpenWrite(filename)) using (var writer = new StreamWriter(stream)) { writer.WriteLine("(entities"); foreach (var mesh_tuple in meshes) { writer.WriteLine($"\t(entity (mesh {mesh_tuple.Item1}) (material {mesh_tuple.Item2}))"); } writer.WriteLine(")"); } }