2V2-e.4: render 40250 pack terrain with map lighting
This commit is contained in:
@@ -166,7 +166,19 @@ Ref<ImageTexture> load_texture(const std::string &name, const fmt::AssetResolver
|
||||
image = godot::Image::create_from_data(decoded.w, decoded.h, false,
|
||||
godot::Image::FORMAT_RGBA8, pixels);
|
||||
} else {
|
||||
image = godot::Image::load_from_file(godot_path);
|
||||
// Image::load_from_file cannot open the pack:// virtual filesystem.
|
||||
if (godot_path.begins_with("pack://")) {
|
||||
PackedByteArray bytes = mtgodot::read_file(godot_path);
|
||||
image.instantiate();
|
||||
if (godot_path.get_extension().to_lower() == "tga")
|
||||
image->load_tga_from_buffer(bytes);
|
||||
else if (godot_path.get_extension().to_lower() == "png")
|
||||
image->load_png_from_buffer(bytes);
|
||||
else if (godot_path.get_extension().to_lower() == "jpg")
|
||||
image->load_jpg_from_buffer(bytes);
|
||||
} else {
|
||||
image = godot::Image::load_from_file(godot_path);
|
||||
}
|
||||
}
|
||||
if (image.is_null() || image->is_empty())
|
||||
return Ref<ImageTexture>();
|
||||
|
||||
@@ -278,6 +278,7 @@ void Metin2World::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("set_load_radius_tiles", "r"), &Metin2World::set_load_radius_tiles);
|
||||
ClassDB::bind_method(D_METHOD("get_load_radius_tiles"), &Metin2World::get_load_radius_tiles);
|
||||
ClassDB::bind_method(D_METHOD("set_focus_tile", "t"), &Metin2World::set_focus_tile);
|
||||
ClassDB::bind_method(D_METHOD("set_initial_focus_cm", "position"), &Metin2World::set_initial_focus_cm);
|
||||
ClassDB::bind_method(D_METHOD("get_focus_tile"), &Metin2World::get_focus_tile);
|
||||
ClassDB::bind_method(D_METHOD("set_auto_load", "v"), &Metin2World::set_auto_load);
|
||||
ClassDB::bind_method(D_METHOD("get_auto_load"), &Metin2World::get_auto_load);
|
||||
@@ -290,6 +291,7 @@ void Metin2World::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("set_env_enabled", "v"), &Metin2World::set_env_enabled);
|
||||
ClassDB::bind_method(D_METHOD("get_env_enabled"), &Metin2World::get_env_enabled);
|
||||
ClassDB::bind_method(D_METHOD("set_water_enabled", "v"), &Metin2World::set_water_enabled);
|
||||
ClassDB::bind_method(D_METHOD("set_collision_enabled", "v"), &Metin2World::set_collision_enabled);
|
||||
ClassDB::bind_method(D_METHOD("get_water_enabled"), &Metin2World::get_water_enabled);
|
||||
ClassDB::bind_method(D_METHOD("set_tree_shadows", "v"), &Metin2World::set_tree_shadows);
|
||||
ClassDB::bind_method(D_METHOD("get_tree_shadows"), &Metin2World::get_tree_shadows);
|
||||
@@ -401,7 +403,7 @@ bool Metin2World::build_chunk(int tx, int ty) {
|
||||
if (!ss.layers.empty()) {
|
||||
String smpath;
|
||||
String sm = String(dir.c_str()) + "/shadowmap.dds";
|
||||
if (FileAccess::file_exists(sm))
|
||||
if (mtgodot::file_exists(sm))
|
||||
smpath = sm;
|
||||
Ref<ShaderMaterial> tm = build_chunk_terrain_material(
|
||||
ss, texture_set, *resolver, smpath);
|
||||
@@ -766,6 +768,12 @@ bool Metin2World::load_map() {
|
||||
return false;
|
||||
}
|
||||
setting_ok = true;
|
||||
if (load_radius >= 0 && initial_focus_cm != Vector2()) {
|
||||
focus_tx = (int)std::floor((initial_focus_cm.x - setting.base_position_x) /
|
||||
fmt::m2coord::CHUNK_CM);
|
||||
focus_ty = (int)std::floor((initial_focus_cm.y - setting.base_position_y) /
|
||||
fmt::m2coord::CHUNK_CM);
|
||||
}
|
||||
|
||||
// AssetResolver 是地图对象、环境声属性和 splat 共用的资源索引。
|
||||
// 即使关闭 splat,也要保留这条链路,避免环境声依赖渲染开关。
|
||||
@@ -785,16 +793,23 @@ bool Metin2World::load_map() {
|
||||
c = '/';
|
||||
c = (char)std::tolower((unsigned char)c);
|
||||
}
|
||||
// Setting.txt may already name the textureset/ directory. The pack
|
||||
// virtual root ends in '/', while a loose asset root does not.
|
||||
if (ts_rel.rfind("textureset/", 0) == 0)
|
||||
ts_rel.erase(0, sizeof("textureset/") - 1);
|
||||
std::string tse;
|
||||
if (fmt::parse_texture_set_file(root + "/textureset/" + ts_rel, texture_set, &tse))
|
||||
const std::string texture_path = root == "pack://"
|
||||
? root + "textureset/" + ts_rel : root + "/textureset/" + ts_rel;
|
||||
if (fmt::parse_texture_set_file(texture_path, texture_set, &tse))
|
||||
splat_ready = true;
|
||||
else
|
||||
UtilityFunctions::push_warning(String("[Metin2World] TextureSet: ") + tse.c_str());
|
||||
}
|
||||
|
||||
// Property CRC 注册表(对象和环境声共用;不依赖 objects_enabled)。
|
||||
// A 40250 pack is a virtual filesystem, not a directory to scan. The terrain
|
||||
// and its textures resolve by pack path; property objects are a later port.
|
||||
registry_ok = false;
|
||||
{
|
||||
if (root != "pack://") {
|
||||
// resolver 已建:用它的文件清单,避免再 std::filesystem 扫盘(PCK 里扫不了)。
|
||||
bool ok = resolver
|
||||
? registry.scan_list(root, resolver->all_rel(), &re)
|
||||
@@ -1108,6 +1123,13 @@ Dictionary Metin2World::get_load_report() const {
|
||||
d["registry_ok"] = registry_ok;
|
||||
d["registry_crcs"] = (int)registry.by_crc.size();
|
||||
d["env_ok"] = env_ok;
|
||||
d["character_light_enabled"] = env.dir_light.ch_enable;
|
||||
d["character_light_direction"] = Vector3(env.dir_light.direction[0],
|
||||
env.dir_light.direction[1], env.dir_light.direction[2]);
|
||||
d["character_light_diffuse"] = Color(env.dir_light.ch_diffuse[0],
|
||||
env.dir_light.ch_diffuse[1], env.dir_light.ch_diffuse[2], env.dir_light.ch_diffuse[3]);
|
||||
d["character_light_ambient"] = Color(env.dir_light.ch_ambient[0],
|
||||
env.dir_light.ch_ambient[1], env.dir_light.ch_ambient[2], env.dir_light.ch_ambient[3]);
|
||||
d["fog_level"] = env.fog.fog_level;
|
||||
d["objects_placed"] = objects_placed;
|
||||
d["objects_skipped"] = objects_skipped;
|
||||
|
||||
@@ -60,6 +60,7 @@ public:
|
||||
void set_load_radius_tiles(int r) { load_radius = r; }
|
||||
int get_load_radius_tiles() const { return load_radius; }
|
||||
void set_focus_tile(godot::Vector2i t);
|
||||
void set_initial_focus_cm(godot::Vector2 position) { initial_focus_cm = position; }
|
||||
godot::Vector2i get_focus_tile() const { return godot::Vector2i(focus_tx, focus_ty); }
|
||||
void set_auto_load(bool v) { auto_load = v; }
|
||||
bool get_auto_load() const { return auto_load; }
|
||||
@@ -72,6 +73,7 @@ public:
|
||||
void set_env_enabled(bool v) { env_enabled = v; }
|
||||
bool get_env_enabled() const { return env_enabled; }
|
||||
void set_water_enabled(bool v) { water_enabled = v; }
|
||||
void set_collision_enabled(bool v) { collision_enabled = v; }
|
||||
bool get_water_enabled() const { return water_enabled; }
|
||||
// §3.3: static building/tree shadows are already baked into shadowmap.dds, so
|
||||
// they don't cast realtime sun shadows by default (avoids double-darkening).
|
||||
@@ -123,6 +125,7 @@ private:
|
||||
godot::String map_path = "OutdoorA1/metin2_map_a1";
|
||||
int load_radius = -1; // <0 = 全图
|
||||
int focus_tx = 0, focus_ty = 0;
|
||||
godot::Vector2 initial_focus_cm;
|
||||
bool auto_load = true;
|
||||
bool splat_enabled = true;
|
||||
// §3.5: 每区块地形拆成 N×N patch(各自 MeshInstance),启用逐 patch 视锥剔除 +
|
||||
|
||||
Reference in New Issue
Block a user