M1+M2: gr2 -> Skeleton3D/ArrayMesh/Skin + libgr2-driven animation
- gr2_bridge: gr2 Mat4 (row-major) -> Godot Transform3D (4x4 transpose); build_skeleton (rest from local_transform, initial_placement folded into roots), build_skin (bind i -> bone i, pose = inverse_world), build_mesh (surface per gr2 mesh, ARRAY_BONES = skeleton idx via bone_bindings, rigid meshes bound to bone_bindings[0]). - dxt: DDS DXT1/3/5 decoder ported from xrender-poc. - Metin2Model: load_gr2 -> Skeleton3D + MeshInstance3D + StandardMaterial3D (runtime DDS albedo, face/body split by surface name). Z-up cm -> Y-up m conversion on the node transform (unit_scale, flip_z, flip_winding props). - Metin2AnimPlayer: _process samples a (separate) anim .gr2 with gr2::sample_pose(model.skeleton, anim, t) -> set_bone_global_pose per bone; Godot GPU-skins via skin_matrix = global_pose(i) * bind_pose(i) == gr2 deformer matrix. selfcheck() NaN-scans all anims. Verified: warrior_cheongrin renders (75 bones, 5 surfaces, 3324 verts, textured, upright). dance01 (dur 28.3s, 74 tracks) plays, 0 NaN over 25 samples, distinct poses at t=2/9/16/23. Screenshots in test/golden/. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WaHYEY9rwLWt21PULiYjeJ
This commit is contained in:
@@ -0,0 +1,46 @@
|
||||
#pragma once
|
||||
// gr2_bridge — libgr2 POD views -> Godot scene objects.
|
||||
//
|
||||
// Coordinate handling (the one place it lives; see docs/GODOT-POC-PLAN.md §02):
|
||||
// - gr2 Mat4 is row-major, row-vector math, translation in elements 12..14.
|
||||
// - A plain 4x4 transpose maps it to a Godot Transform3D (column-vector,
|
||||
// translation in .origin). gr2_to_godot() does exactly that.
|
||||
// - Z-up(cm) -> Y-up(m) and optional handedness flip are NOT applied here;
|
||||
// they go on the Metin2Model node transform (make_conv()).
|
||||
|
||||
#include <godot_cpp/classes/ref.hpp>
|
||||
#include <godot_cpp/variant/aabb.hpp>
|
||||
#include <godot_cpp/variant/transform3d.hpp>
|
||||
|
||||
#include <gr2/gr2.h>
|
||||
|
||||
namespace godot {
|
||||
class Skeleton3D;
|
||||
class Skin;
|
||||
class ArrayMesh;
|
||||
} // namespace godot
|
||||
|
||||
namespace mtgodot {
|
||||
|
||||
// 4x4 transpose: gr2 row-major/row-vector -> Godot Transform3D.
|
||||
godot::Transform3D gr2_to_godot(const gr2::Mat4 &m);
|
||||
|
||||
// Z-up cm -> Y-up m (+ optional Z flip for LH->RH content).
|
||||
godot::Transform3D make_conv(float unit_scale, bool flip_z);
|
||||
|
||||
// Build a Skeleton3D (rest pose from bone local transforms; initial_placement
|
||||
// folded into root bones). Returns nullptr if the skeleton has no bones.
|
||||
godot::Skeleton3D *build_skeleton(const gr2::Skeleton &sk);
|
||||
|
||||
// Skin whose bind list is parallel to the skeleton bones:
|
||||
// bind i -> bone i, pose = gr2_to_godot(bone[i].inverse_world)
|
||||
godot::Ref<godot::Skin> build_skin(const gr2::Skeleton &sk);
|
||||
|
||||
// One ArrayMesh with a surface per gr2 Mesh that has geometry.
|
||||
// ARRAY_BONES values are skeleton bone indices (mesh slot -> bone via
|
||||
// mesh.bone_bindings). Rigid meshes are bound rigidly to bone_bindings[0].
|
||||
// Fills out_bounds with the untransformed vertex AABB.
|
||||
godot::Ref<godot::ArrayMesh> build_mesh(const gr2::FileInfo &fi, bool flip_winding,
|
||||
godot::AABB &out_bounds);
|
||||
|
||||
} // namespace mtgodot
|
||||
Reference in New Issue
Block a user