port 2V2-d.2: Granny runtime on libgr2, main character model animates
Implement the Granny SDK 2.11 API the client uses on top of libgr2 (platform/EterGrnLib/GrannyRuntime.cpp, shim granny.h declared from the SDK header): file sections, type-definition vertex conversion, material textures by Usage, mesh/bone bindings, deformer, control clock/loop/ease and weighted SRT sampling. Port EterGrnLib (LODController, Material, Mesh, Model, ModelInstance*, Motion, Thing, ThingInstance, Util) plus EterLib GrpObjectInstance/GrpCollisionObject/CollisionData verbatim and drop their platform skeletons and pending stand-ins; register the gr2 resource factory; vertex/index buffers are CPU-side until the 2V2-e render adapter. app.UpdateGame/RenderGame now run 40250's bodies, reaching the CPythonApplication members through their singletons (the platform has no app object); CPythonGraphic joins GameSingletons in member order, and GetMousePosition reads the host cursor. port.login_flow asserts the main instance's PART_MAIN model has meshes, its diffuse image loaded and the WAIT motion moves the bones between frames; offline and live pass, port_gate macos PASS. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
5266b00c6e
commit
668f48d6ec
@@ -12,6 +12,17 @@ namespace gr2 {
|
||||
|
||||
using Mat4 = std::array<float, 16>; // 行主序,Granny 原生。坐标约定见 docs/reference/steps/M0-gr2-reader.md「约定」
|
||||
|
||||
// granny_transform(SRT 分量原样;Flags: 1=HasPosition 2=HasOrientation 4=HasScaleShear)。
|
||||
// 动画混合要在分量上做(GrannySampleModelAnimations 累加 SRT 再归一),不能在 4x4 上做。
|
||||
struct Transform {
|
||||
uint32_t flags = 0;
|
||||
float position[3] = {0, 0, 0};
|
||||
float orientation[4] = {0, 0, 0, 1}; // x,y,z,w
|
||||
float scale_shear[9] = {1,0,0, 0,1,0, 0,0,1}; // 行主序 3x3
|
||||
};
|
||||
// BuildCompositeTransform4x4:上 3x3 = transpose(R3·SS3),平移在 elem 12..14。
|
||||
Mat4 compose(const Transform& t);
|
||||
|
||||
// ── 骨架 ──────────────────────────────────────────────────────────────
|
||||
struct Bone {
|
||||
std::string name;
|
||||
@@ -19,6 +30,7 @@ struct Bone {
|
||||
Mat4 local_transform{}; // granny_transform SRT → 4x4(组合顺序照 granny_transform.cpp)
|
||||
Mat4 inverse_world{}; // InverseWorld4x4,来自文件
|
||||
uint32_t lt_flags = 0; // granny_transform.Flags:哪部分非单位
|
||||
Transform local; // LocalTransform 的 SRT 分量(local_transform = compose(local))
|
||||
};
|
||||
|
||||
struct Skeleton {
|
||||
@@ -44,6 +56,14 @@ struct TriGroup {
|
||||
int32_t tri_count;
|
||||
};
|
||||
|
||||
// 顶点类型的一个成员(granny_data_type_definition 的平铺子集;type = granny_member_type 序数)。
|
||||
struct VertexMember {
|
||||
std::string name;
|
||||
int32_t type = 0;
|
||||
int32_t array_width = 0; // 0 => 1
|
||||
uint32_t offset = 0; // 在顶点里的字节偏移(打包)
|
||||
};
|
||||
|
||||
struct Mesh {
|
||||
struct BoneBounds {
|
||||
float min[3] = {}, max[3] = {};
|
||||
@@ -63,6 +83,12 @@ struct Mesh {
|
||||
// tri_groups[i].material_index 索引本表。
|
||||
std::vector<std::string> material_textures;
|
||||
bool rigid = false; // GrannyMeshIsRigid
|
||||
std::vector<std::string> bone_binding_names; // granny_bone_binding.BoneName,与 bone_bounds 平行
|
||||
std::vector<int32_t> material_bindings; // granny_mesh.MaterialBindings[i].Material → FileInfo::materials 索引(-1 = 空)
|
||||
// 原始顶点:文件声明的顶点类型 + 按它打包的字节(Granny 运行时按名字做布局转换用)
|
||||
std::vector<VertexMember> vertex_members;
|
||||
uint32_t vertex_stride = 0;
|
||||
std::vector<uint8_t> raw_vertices; // vertices.size() * vertex_stride
|
||||
};
|
||||
|
||||
// ── 动画 ──────────────────────────────────────────────────────────────
|
||||
@@ -82,6 +108,9 @@ struct Curve {
|
||||
void eval(float t, float* out) const;
|
||||
};
|
||||
|
||||
struct TextTrackEntry { float time_stamp = 0.0f; std::string text; };
|
||||
struct TextTrack { std::string name; std::vector<TextTrackEntry> entries; };
|
||||
|
||||
struct BoneTrack {
|
||||
std::string bone_name;
|
||||
int32_t bone_index = -1; // 映射到 skeleton(未映射 = -1)
|
||||
@@ -91,11 +120,17 @@ struct BoneTrack {
|
||||
Curve position; // dim 3
|
||||
Curve orientation; // dim 4(四元数 x,y,z,w)
|
||||
Curve scale_shear; // dim 9(3x3)或 dim 3
|
||||
// t 处的 SRT(缺的曲线取单位分量,flags 只标出有曲线的分量)。sample_local 的 4x4 = compose(这个)。
|
||||
void sample(float t, Transform& out) const;
|
||||
};
|
||||
|
||||
struct Animation {
|
||||
std::string name;
|
||||
float duration = 0.0f;
|
||||
float time_step = 0.0f;
|
||||
float oversampling = 1.0f;
|
||||
int32_t track_group_count = 0;
|
||||
std::vector<TextTrack> text_tracks; // TrackGroups[0].TextTracks
|
||||
std::vector<BoneTrack> tracks;
|
||||
// t 处每个 track 的局部 4x4(granny_transform 组合语义,行主序)。
|
||||
// out 按 tracks 顺序;bone_index 见各 track。
|
||||
@@ -103,9 +138,26 @@ struct Animation {
|
||||
};
|
||||
|
||||
// 顶层 granny_material(driven by root Materials[])。name + 解析出的漫反射贴图。
|
||||
// root Materials[] 之外、只经 Maps[] / mesh MaterialBindings 可达的子材质追加在后面。
|
||||
struct MaterialMap {
|
||||
std::string usage; // granny_material_map.Usage("Diffuse Color" 等)
|
||||
int32_t material = -1; // FileInfo::materials 索引
|
||||
};
|
||||
struct Material {
|
||||
std::string name;
|
||||
std::string diffuse_texture; // granny_texture.FromFileName 原样
|
||||
std::string texture; // 本材质自己的 Texture.FromFileName(空 = 无 Texture)
|
||||
std::vector<MaterialMap> maps; // granny_material.Maps
|
||||
int32_t two_sided = 0; // ExtendedData 的 Int32 "Two-sided"
|
||||
bool has_two_sided = false;
|
||||
};
|
||||
|
||||
// granny_model:Skeleton + InitialPlacement + MeshBindings。
|
||||
struct Model {
|
||||
std::string name;
|
||||
int32_t skeleton = -1; // FileInfo::skeletons 索引
|
||||
Transform initial_placement;
|
||||
std::vector<int32_t> mesh_bindings; // FileInfo::meshes 索引(-1 = 未解析)
|
||||
};
|
||||
|
||||
// ── FileInfo 汇总(T4)────────────────────────────────────────────────
|
||||
@@ -115,6 +167,7 @@ struct FileInfo {
|
||||
std::vector<Mesh> meshes;
|
||||
std::vector<Animation> animations;
|
||||
std::vector<Material> materials;
|
||||
std::vector<Model> models;
|
||||
uint32_t material_count = 0;
|
||||
uint32_t texture_count = 0;
|
||||
uint32_t model_count = 0;
|
||||
|
||||
Reference in New Issue
Block a user