diff --git a/dq8chr2glb/Converter/MDSConverter.cs b/dq8chr2glb/Converter/GLTF/MDSConverter.cs similarity index 95% rename from dq8chr2glb/Converter/MDSConverter.cs rename to dq8chr2glb/Converter/GLTF/MDSConverter.cs index df0916d..15f41af 100644 --- a/dq8chr2glb/Converter/MDSConverter.cs +++ b/dq8chr2glb/Converter/GLTF/MDSConverter.cs @@ -14,7 +14,7 @@ using SixLabors.ImageSharp; using Node = SharpGLTF.Schema2.Node; using Texture = dq8chr2glb.TM2Format.Texture; -namespace dq8chr2glb.Converter; +namespace dq8chr2glb.Converter.GLTF; public class MDSConverter { @@ -291,10 +291,7 @@ public class MDSConverter var hasWeights = node.Mesh.Primitives.All(i => i.VertexAccessors.ContainsKey("WEIGHTS_0")); if (hasWeights) { - if (Quaternion.Dot(node.LocalTransform.GetDecomposed().Rotation, Quaternion.Identity) >= 0.999f) - { - node.LocalTransform = Matrix4x4.Identity; - } + MeshUtils.ApplyTransform(node); try { @@ -302,13 +299,21 @@ public class MDSConverter } catch (Exception e) { - Log.Line(e.TargetSite.Name); + Context.current.errors.Add(new Error(name, "Can't set Skin", e)); } } } } } + private string DebugMatrix(Matrix4x4 mat) + { + return $"{mat.M11:F}, {mat.M12:F}, {mat.M13:F}, {mat.M14:F}\n" + + $"{mat.M21:F}, {mat.M22:F}, {mat.M23:F}, {mat.M24:F}\n" + + $"{mat.M31:F}, {mat.M32:F}, {mat.M33:F}, {mat.M34:F}\n" + + $"{mat.M41:F}, {mat.M42:F}, {mat.M43:F}, {mat.M44:F}\n"; + } + private Matrix4x4 ToNumericsMatrix4x4(MDSMatrix m) { return new Matrix4x4( diff --git a/dq8chr2glb/Converter/GLTF/MeshUtils.cs b/dq8chr2glb/Converter/GLTF/MeshUtils.cs new file mode 100644 index 0000000..3de25a0 --- /dev/null +++ b/dq8chr2glb/Converter/GLTF/MeshUtils.cs @@ -0,0 +1,110 @@ +using System; +using System.Collections.Generic; +using System.Numerics; +using SharpGLTF.Schema2; +using System.Runtime.InteropServices; + +namespace dq8chr2glb.Converter.GLTF; + +public static class MeshUtils +{ + public static void ComputeNormals(List positions, int[] triangles, List normals) + { + for (var i = 0; i < normals.Count; i++) + { + normals[i] = Vector3.Zero; + } + + for (var i = 0; i < triangles.Length; i += 3) + { + var idx1 = triangles[i]; + var idx2 = triangles[i + 1]; + var idx3 = triangles[i + 2]; + + var p1 = positions[idx1]; + var p2 = positions[idx2]; + var p3 = positions[idx3]; + + var edge1 = p2 - p1; + var edge2 = p3 - p1; + + var normal = Vector3.Cross(edge1, edge2); + normal = Vector3.Normalize(normal); + + normals[idx1] += normal; + normals[idx2] += normal; + normals[idx3] += normal; + } + + for (var i = 0; i < normals.Count; i++) + { + normals[i] = Vector3.Normalize(normals[i]); + } + } + + public static void ApplyTransform(Node node) + { + Matrix4x4.Invert(node.LocalMatrix, out var invTransform); + var normalMatrix = Matrix4x4.Transpose(invTransform); + + foreach (var primitive in node.Mesh.Primitives) + { + var positionAccessor = primitive.GetVertexAccessor("POSITION"); + var positions = positionAccessor.AsVector3Array(); + var newPositions = new Vector3[positions.Count]; + + for (var i = 0; i < positions.Count; i++) + { + newPositions[i] = Vector3.Transform(positions[i], node.LocalMatrix); + } + + var count = positionAccessor.Count; + var format = positionAccessor.Format; + + var positionBytes = MemoryMarshal.AsBytes(newPositions.AsSpan()).ToArray(); + var newPositionBufferView = primitive.LogicalParent.LogicalParent.UseBufferView( + positionBytes + ); + + var newAccessor = primitive.LogicalParent.LogicalParent.CreateAccessor(); + newAccessor.SetVertexData( + newPositionBufferView, + 0, + count, + format + ); + + primitive.SetVertexAccessor("POSITION", newAccessor); + + var normalAccessor = primitive.GetVertexAccessor("NORMAL"); + if (normalAccessor != null) + { + var normals = normalAccessor.AsVector3Array(); + var newNormals = new Vector3[normals.Count]; + + for (var i = 0; i < normals.Count; i++) + { + var transformedNormal = Vector3.TransformNormal(normals[i], normalMatrix); + newNormals[i] = Vector3.Normalize(transformedNormal); + } + + var normalBytes = MemoryMarshal.AsBytes(newNormals.AsSpan()).ToArray(); + var newNormalBufferView = primitive.LogicalParent.LogicalParent.UseBufferView( + normalBytes + ); + + var newNormalAccessor = primitive.LogicalParent.LogicalParent.CreateAccessor(); + newNormalAccessor.SetVertexData( + newNormalBufferView, + 0, + normalAccessor.Count, + normalAccessor.Format + ); + + primitive.SetVertexAccessor("NORMAL", newNormalAccessor); + } + } + + node.LocalMatrix = Matrix4x4.Identity; + } +} diff --git a/dq8chr2glb/Converter/UniversalMeshBuilder.cs b/dq8chr2glb/Converter/GLTF/UniversalMeshBuilder.cs similarity index 89% rename from dq8chr2glb/Converter/UniversalMeshBuilder.cs rename to dq8chr2glb/Converter/GLTF/UniversalMeshBuilder.cs index 8c9312d..f54c444 100644 --- a/dq8chr2glb/Converter/UniversalMeshBuilder.cs +++ b/dq8chr2glb/Converter/GLTF/UniversalMeshBuilder.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Numerics; using dq8chr2glb.Core.MDSFormat; using dq8chr2glb.Logger; @@ -8,9 +7,8 @@ using SharpGLTF.Geometry; using SharpGLTF.Geometry.VertexTypes; using SharpGLTF.Materials; using SharpGLTF.Schema2; -using Node = SharpGLTF.Schema2.Node; -namespace dq8chr2glb.Converter +namespace dq8chr2glb.Converter.GLTF { public static class UniversalMeshBuilder { @@ -137,7 +135,7 @@ namespace dq8chr2glb.Converter } } - ComputeNormals(positions, mdsMesh.triangles, normals); + MeshUtils.ComputeNormals(positions, mdsMesh.triangles, normals); foreach (var submesh in mdsMesh.submeshes) { @@ -250,39 +248,5 @@ namespace dq8chr2glb.Converter return new VertexBuilder(geometry, material, skinning); } - - private static void ComputeNormals(List positions, int[] triangles, List normals) - { - for (var i = 0; i < normals.Count; i++) - { - normals[i] = Vector3.Zero; - } - - for (var i = 0; i < triangles.Length; i += 3) - { - var idx1 = triangles[i]; - var idx2 = triangles[i + 1]; - var idx3 = triangles[i + 2]; - - var p1 = positions[idx1]; - var p2 = positions[idx2]; - var p3 = positions[idx3]; - - var edge1 = p2 - p1; - var edge2 = p3 - p1; - - var normal = Vector3.Cross(edge1, edge2); - normal = Vector3.Normalize(normal); - - normals[idx1] += normal; - normals[idx2] += normal; - normals[idx3] += normal; - } - - for (var i = 0; i < normals.Count; i++) - { - normals[i] = Vector3.Normalize(normals[i]); - } - } } } \ No newline at end of file