// Metin2 -> Godot 坐标 / 单位统一转换(纯数学,无 godot 依赖)。 // BACKLOG I5 · SHINSOO §6。extension 侧的 mtgodot::coord 薄封装应直接调用这里, // 不得另写公式。 // // Metin2:厘米,Z-up(左手) Godot:米,Y-up(右手) // Godot.x = Metin2.x * 0.01 // Godot.y = Metin2.z * 0.01 // Godot.z = -Metin2.y * 0.01 // 等价于 make_conv 的 rotate(-90°,X) + scale(0.01)。 #pragma once #include #include namespace fmt::m2coord { struct Vec3 { double x = 0, y = 0, z = 0; }; constexpr double CM_TO_M = 0.01; constexpr int CELLSCALE = 200; // PRTerrainLib TerrainType.h constexpr int TERRAIN_SIZE = 128; constexpr int CHUNK_CM = CELLSCALE * TERRAIN_SIZE; // 25600 —— 一个区块的边长(cm) // 位置:厘米 Z-up -> 米 Y-up。 inline Vec3 position_to_godot(double x_cm, double y_cm, double z_cm) { return { x_cm * CM_TO_M, z_cm * CM_TO_M, -y_cm * CM_TO_M }; } inline Vec3 position_to_godot(const Vec3& v) { return position_to_godot(v.x, v.y, v.z); } // 方向:只做轴转换,不缩放、不平移。 inline Vec3 direction_to_godot(double x, double y, double z) { return { x, z, -y }; } // 区块目录编号:tile_id = tile_x*1000 + tile_y,目录名 = 6 位十进制。 inline uint32_t tile_id(int tile_x, int tile_y) { return uint32_t(tile_x) * 1000u + uint32_t(tile_y); } std::string tile_dir(int tile_x, int tile_y); // "000000" / "001003" bool parse_tile_dir(const std::string& name, int& tile_x, int& tile_y); // 区块原点(该区块 (0,0) 格在地图内的厘米坐标,未做轴转换)。 inline Vec3 chunk_origin_cm(int tile_x, int tile_y) { return { double(tile_x) * CHUNK_CM, double(tile_y) * CHUNK_CM, 0.0 }; } // height.raw 采样值 -> 厘米高度:raw * HeightScale。 inline double height_raw_to_cm(uint16_t raw, double height_scale) { return double(raw) * height_scale; } struct Mat3 { double m[9]; }; // row-major: m[r*3+c] // AreaData 的 yaw#pitch#roll(度)-> **Metin2 Z-up 空间**的旋转(行主序 3×3)。 // 忠实移植原客户端 `CGraphicObjectInstance::SetRotation` 的 // `D3DXMatrixRotationYawPitchRoll(yaw, pitch, roll)`(列向量约定下 = Ry(yaw)·Rx(pitch)·Rz(roll))。 // 注意 Metin2 世界是 Z-up:yaw 绕 Y、pitch 绕 X、**roll 绕 Z = 竖直轴 = 朝向**。 // areadata 单值旋转 → roll(`Area.cpp:820`)。这一版**未**做 Z-up→Y-up 轴转换, // 直接塞进 Godot Basis 会把「朝向」错当成绕 Godot Z 的翻滚 —— 放置物体请用 object_basis_godot()。 Mat3 ypr_basis(double yaw_deg, double pitch_deg, double roll_deg); // 同上,但已把旋转共轭到 **Godot Y-up 空间**(R_godot = C · R_m2 · C⁻¹,C = rotate(-90°,X))。 // 可直接作为 Godot Basis 使用:物体的 Godot 变换 = Transform3D(object_basis_godot(...), g) * make_conv()。 // roll(朝向)→ 绕 Godot +Y 的 heading,不再翻滚。行主序 3×3。 Mat3 object_basis_godot(double yaw_deg, double pitch_deg, double roll_deg); } // namespace fmt::m2coord