Implement playable Mac client and rendering validation
This commit is contained in:
@@ -9,6 +9,13 @@
|
||||
|
||||
#include <godot_cpp/classes/image.hpp>
|
||||
#include <godot_cpp/classes/image_texture.hpp>
|
||||
#include <godot_cpp/classes/file_access.hpp>
|
||||
#include <godot_cpp/classes/json.hpp>
|
||||
#include <godot_cpp/classes/gltf_document.hpp>
|
||||
#include <godot_cpp/classes/gltf_state.hpp>
|
||||
#include <godot_cpp/classes/gltf_mesh.hpp>
|
||||
#include <godot_cpp/classes/importer_mesh.hpp>
|
||||
#include <godot_cpp/variant/utility_functions.hpp>
|
||||
#include <godot_cpp/classes/shader.hpp>
|
||||
#include <godot_cpp/classes/shader_material.hpp>
|
||||
#include <godot_cpp/classes/standard_material3d.hpp>
|
||||
@@ -477,15 +484,57 @@ Ref<ArrayMesh> build_placeholder_tree(const String &species_hint, float height_m
|
||||
return build_proxy_impl(std::string(species_hint.utf8().get_data()), height_m, empty);
|
||||
}
|
||||
|
||||
Ref<ArrayMesh> get_tree_proxy_mesh(const std::string &treefile,
|
||||
static Ref<ArrayMesh> load_native_tree(const std::string &treefile, const fmt::AssetResolver &resolver) {
|
||||
const String source(resolver.resolve(treefile, nullptr).c_str());
|
||||
if (source.is_empty()) return {};
|
||||
const String directory = String(resolver.assets_root.c_str()).path_join("TreeGeometry");
|
||||
const String manifest_path = directory.path_join("manifest.json");
|
||||
if (!FileAccess::file_exists(manifest_path)) return {};
|
||||
const Variant parsed = JSON::parse_string(FileAccess::get_file_as_string(manifest_path));
|
||||
if (parsed.get_type() != Variant::DICTIONARY) return {};
|
||||
const Dictionary manifest = parsed;
|
||||
if (int(manifest.get("schema_version", 0)) != 1 || String(manifest.get("coordinates", "")) != "godot_y_up_meters") return {};
|
||||
const Dictionary trees = manifest.get("trees", Dictionary());
|
||||
const String source_hash = FileAccess::get_sha256(source);
|
||||
if (!trees.has(source_hash)) return {};
|
||||
const Dictionary record = trees[source_hash];
|
||||
const String filename = record.get("glb", "");
|
||||
if (filename != source_hash + String(".glb")) return {};
|
||||
const String path = directory.path_join(filename);
|
||||
if (!FileAccess::file_exists(path) || FileAccess::get_sha256(path) != String(record.get("glb_sha256", ""))) return {};
|
||||
Ref<GLTFDocument> document;
|
||||
document.instantiate();
|
||||
Ref<GLTFState> state;
|
||||
state.instantiate();
|
||||
if (document->append_from_file(path, state) != OK || state->get_meshes().size() != 1) return {};
|
||||
Ref<GLTFMesh> gltf_mesh = state->get_meshes()[0];
|
||||
if (gltf_mesh.is_null() || gltf_mesh->get_mesh().is_null()) return {};
|
||||
Ref<ArrayMesh> mesh = gltf_mesh->get_mesh()->get_mesh();
|
||||
if (mesh.is_null() || mesh->get_surface_count() == 0) return {};
|
||||
mesh->set_meta("tree_geometry", "native_spt");
|
||||
mesh->set_meta("source_sha256", source_hash);
|
||||
mesh->set_meta("glb_sha256", record.get("glb_sha256", ""));
|
||||
mesh->set_meta("leaf_mode", "static_extracted_cards");
|
||||
// GLB vertices already use Godot metres. Never impose the proxy's 12m height.
|
||||
return mesh;
|
||||
}
|
||||
|
||||
Ref<ArrayMesh> get_tree_mesh(const std::string &treefile,
|
||||
const fmt::AssetResolver &resolver, float height_m) {
|
||||
const std::string key = resolver.assets_root + "|" + fmt::AssetResolver::normalize(treefile) +
|
||||
"#" + std::to_string(height_m);
|
||||
auto found = g_tree_mesh_cache.find(key);
|
||||
if (found != g_tree_mesh_cache.end())
|
||||
return found->second;
|
||||
Ref<ArrayMesh> native = load_native_tree(treefile, resolver);
|
||||
if (native.is_valid()) {
|
||||
g_tree_mesh_cache.emplace(key, native);
|
||||
return native;
|
||||
}
|
||||
UtilityFunctions::push_warning(String("Tree native geometry unavailable or hash mismatch; proxy: ") + String(treefile.c_str()));
|
||||
const TreeTextures textures = resolve_tree_textures(treefile, resolver);
|
||||
Ref<ArrayMesh> mesh = build_proxy_impl(treefile, height_m, textures);
|
||||
mesh->set_meta("tree_geometry", "proxy");
|
||||
g_tree_mesh_cache.emplace(key, mesh);
|
||||
return mesh;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user