// libgr2 内部。SDK struct 镜像从 granny_file_format.h / granny_data_type_definition.h 抄。 #pragma once #include "gr2/gr2.h" #include #include #include #include namespace gr2 { namespace detail { // ── granny_file_format.h 镜像 ────────────────────────────────────────── #pragma pack(push, 1) struct GrnFileMagic { // grn_file_magic_value uint32_t magic[4]; uint32_t header_size; uint32_t header_format; uint32_t reserved[2]; }; struct GrnReference { uint32_t section; uint32_t offset; }; struct GrnPointerFixup { uint32_t from_offset; GrnReference to; }; // 12B struct GrnSection { // grn_section —— 44B uint32_t compression; uint32_t data_offset, data_size; uint32_t expanded_data_size; uint32_t internal_alignment; uint32_t first16bit, first8bit; uint32_t pointer_fixup_off, pointer_fixup_count; uint32_t mixed_fixup_off, mixed_fixup_count; }; #pragma pack(pop) struct Section { std::vector data; // 展开后 SectionInfo info; }; // section 内的位置。不物化指针(文件是 32 位指针,本进程 64 位), // 全程用 (section, offset) + fixup 表按需解引用。 struct Ref { int32_t section = -1; uint32_t offset = 0; bool valid() const { return section >= 0; } }; // ── granny_data_type_definition.h:member_type 枚举(序数不可变)──────── enum MemberType { MT_End = 0, MT_Inline, MT_Reference, MT_RefToArray, MT_ArrayOfRefs, MT_VariantRef, MT_Removed, MT_RefToVariantArray, MT_String, MT_Transform, MT_Real32, MT_Int8, MT_UInt8, MT_BinormInt8, MT_NormUInt8, MT_Int16, MT_UInt16, MT_BinormInt16, MT_NormUInt16, MT_Int32, MT_UInt32, MT_Real16, MT_EmptyRef, MT_OnePastLast }; // data_type_definition 在文件里的字节数(32 位指针): // Type(4) Name(ptr4) ReferenceType(ptr4) ArrayWidth(4) Extra[3](12) Ignored(ptr4) constexpr uint32_t kTypeDefEntrySize = 32; struct TypeMember { std::string name; int32_t type = MT_End; int32_t array_width = 0; // 0 => 1 Ref ref_type; // Inline/Reference/... 的元素类型 uint32_t offset = 0; // 在对象实例里的字节偏移(打包,无对齐 pad) uint32_t size = 0; // 本 member 的总字节数 }; } // namespace detail struct File::Impl { std::vector sections; // 展开后数据 + info std::vector raw; // 原始 section 头(fixup 用) using Ref = detail::Ref; using TypeMember = detail::TypeMember; using GrnSection = detail::GrnSection; // (section<<32 | from_offset) -> 目标 Ref std::unordered_map fixups; Ref root_obj; // grn_file_header.RootObject Ref root_type; // grn_file_header.RootObjectTypeDefinition bool typetree_ready = false; // 类型解析缓存:typedef 的 Ref -> 成员列表 std::unordered_map> type_cache; // ── T2 / T1 ── bool decompress_section(const GrnSection&, const uint8_t* src, detail::Section& out, LoadError*); void build_fixups(const uint8_t* file, size_t file_len); // T1 // ── T3 ── const uint8_t* at(Ref r, size_t need = 0) const; // section 内指针 + 边界检查 Ref follow(Ref slot) const; // 解一个"指针槽" const std::vector& parse_type(Ref type_ref); // 走 data_type_definition 数组 uint32_t object_size(Ref type_ref); uint32_t member_unit_size(const TypeMember&); const TypeMember* find_member(const std::vector& ms, const char* name) const; // 便捷读取 uint32_t rd_u32(Ref r) const; int32_t rd_i32(Ref r) const { return (int32_t)rd_u32(r); } float rd_f32(Ref r) const; std::string rd_str(Ref slot) const; // 解引用一个 String 槽 // 成员访问(obj = 对象实例的 Ref,m = 其类型的某个成员) Ref member_slot(Ref obj, const TypeMember& m) const { return {obj.section, obj.offset + m.offset}; } Ref read_reference(Ref obj, const TypeMember& m) const { return follow(member_slot(obj, m)); } // ArrayOfReferences: {int32 count; ptr → [count] 个指针槽 → 各自的对象} std::vector read_array_of_refs(Ref obj, const TypeMember& m) const; // ReferenceToArray: {int32 count; ptr → [count] 个连续对象(elem_type)} bool read_ref_to_array(Ref obj, const TypeMember& m, Ref& base, uint32_t& count, uint32_t& stride); // ── T4/T5/T6/T7a ── bool build_fileinfo(FileInfo& out, LoadError*); bool extract_skeleton(Ref skel_obj, Ref skel_type, Skeleton& out); bool extract_mesh(Ref mesh_obj, Ref mesh_type, const std::vector& skels, Mesh& out); // granny_material 链:直接 .Texture.FromFileName,或递归 .Maps[].Material。返回 dds 文件名(原样)。 std::string material_texture_name(Ref mat_obj, Ref mat_type, int depth); bool extract_animation(Ref anim_obj, Ref anim_type, const Skeleton* skel, Animation& out); // 曲线子类型分类(T7a)。curve_obj 指向 inline 曲线对象本体,curve_type 是它的类型。 std::string classify_curve_obj(Ref curve_obj, Ref curve_type); void read_old_curve(Ref curve_obj, Ref curve_type, Curve& out); // T7b double skeleton_self_check(int skeleton) const; // granny_transform (68B) → 行主序 4x4(BuildCompositeTransform4x4 语义) void transform_to_composite(Ref tf, Mat4& out, uint32_t& flags) const; void read_transform(Ref tf, Transform& out) const; // 68B → SRT 分量 // granny_material 图:按对象 Ref 去重,缺的追加到 mats_out(子材质 / 只经 mesh 可达的材质)。 // 返回 FileInfo::materials 索引;无效 / 递归太深 = -1。 int32_t intern_material(Ref mat_obj, Ref mat_type, int depth = 0); std::vector* mats_out = nullptr; std::vector mat_refs; // 与 *mats_out 平行 // ExtendedData(VariantRef = {type ptr; object ptr})里取名为 name 的 Int32。 bool extended_i32(Ref variant_slot, const char* name, int32_t& out); std::vector skels_cache; // self-check 复用 std::vector skel_refs; // 与 skels_cache 平行:各 skeleton 对象的 Ref(model 关联用) mutable FileInfo* info_cache = nullptr; // 指向 File::info_ }; } // namespace gr2