add: Bake transform for skinned mesh
This commit is contained in:
@@ -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(
|
||||
@@ -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<Vector3> positions, int[] triangles, List<Vector3> 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;
|
||||
}
|
||||
}
|
||||
+2
-38
@@ -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<TvG, TvM, TvS>(geometry, material, skinning);
|
||||
}
|
||||
|
||||
private static void ComputeNormals(List<Vector3> positions, int[] triangles, List<Vector3> 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]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user