harfang3d/harfang/engine/scene_load_json.cpp
2021-12-31 16:59:26 +01:00

924 lines
28 KiB
C++

// HARFANG(R) Copyright (C) 2021 Emmanuel Julien, NWNC HARFANG. Released under GPL/LGPL/Commercial Licence, see licence.txt for details.
#include "engine/file_format.h"
#include "engine/render_pipeline.h"
#include "engine/scene.h"
#include "engine/to_json.h"
#include "foundation/format.h"
#include "foundation/log.h"
#include <foundation/string.h>
#include <json/json.hpp>
#include <set>
namespace hg {
void SaveComponent(const Scene::Transform_ *data_, json &js) {
js["pos"] = data_->TRS.pos;
js["rot"] = RadianToDegree(data_->TRS.rot);
js["scl"] = data_->TRS.scl;
js["parent"] = data_->parent;
}
void SaveComponent(const Scene::Camera_ *data_, json &js) {
js["zrange"] = data_->zrange;
js["fov"] = data_->fov;
js["ortho"] = data_->ortho;
js["size"] = data_->size;
}
void SaveComponent(const Scene::Object_ *data_, json &js, const PipelineResources &resources) {
js["name"] = resources.models.GetName(data_->model);
const auto mat_count = uint16_t(data_->materials.size());
std::vector<json> materials(mat_count);
for (size_t j = 0; j < mat_count; ++j)
SaveMaterial(data_->materials[j], materials[j], resources);
js["materials"] = materials;
std::vector<json> material_infos(mat_count);
for (size_t j = 0; j < mat_count; j++)
if (j < data_->material_infos.size()) {
material_infos[j]["name"] = data_->material_infos[j].name;
} else {
material_infos[j]["name"] = std::string();
}
js["material_infos"] = material_infos;
json bones = json::array();
for (auto bone : data_->bones)
bones.push_back(bone);
js["bones"] = bones;
}
void SaveComponent(const Scene::Light_ *data_, json &js) {
js["type"] = data_->type;
js["shadow_type"] = data_->shadow_type;
js["diffuse"] = data_->diffuse;
js["diffuse_intensity"] = data_->diffuse_intensity;
js["specular"] = data_->specular;
js["specular_intensity"] = data_->specular_intensity;
js["radius"] = data_->radius;
js["inner_angle"] = data_->inner_angle;
js["outer_angle"] = data_->outer_angle;
js["pssm_split"] = data_->pssm_split;
js["priority"] = data_->priority;
js["shadow_bias"] = data_->shadow_bias;
}
void SaveComponent(const Scene::RigidBody_ *data_, json &js) {
js["type"] = data_->type;
js["world"] = data_->cur;
js["scale"] = data_->scl;
js["linear_damping"] = data_->linear_damping;
js["angular_damping"] = data_->angular_damping;
js["restitution"] = data_->restitution;
js["friction"] = data_->friction;
js["rolling_friction"] = data_->rolling_friction;
}
void SaveComponent(const Scene::Script_ *data_, json &js) {
js["path"] = data_->path;
for (auto &i : data_->params) {
if (i.second.type == SPT_Bool)
js["parameters"][i.first] = {{"type", "bool"}, {"value", i.second.bv}};
else if (i.second.type == SPT_Int)
js["parameters"][i.first] = {{"type", "int"}, {"value", i.second.iv}};
else if (i.second.type == SPT_Float)
js["parameters"][i.first] = {{"type", "float"}, {"value", i.second.fv}};
else if (i.second.type == SPT_String)
js["parameters"][i.first] = {{"type", "string"}, {"value", i.second.sv}};
}
}
void SaveComponent(const Scene::Instance_ *data_, json &js) {
js["name"] = data_->name;
if (!data_->anim.empty()) {
js["anim"] = data_->anim;
js["loop_mode"] = data_->loop_mode;
}
}
void SaveComponent(const Scene::Collision_ *data_, json &js) {
js["type"] = data_->type;
js["mass"] = data_->mass;
js["size"] = data_->size;
js["path"] = data_->resource_path;
js["m"] = data_->m;
}
//
void LoadComponent(Scene::Transform_ *data_, const json &js) {
data_->TRS.pos = js.at("pos");
data_->TRS.rot = DegreeToRadian(js.at("rot").get<Vec3>());
data_->TRS.scl = js.at("scl");
data_->parent = js.at("parent");
}
void LoadComponent(Scene::Camera_ *data_, const json &js) {
js_at_safe(js, "zrange", data_->zrange);
js_at_safe(js, "fov", data_->fov);
js_at_safe(js, "ortho", data_->ortho);
js_at_safe(js, "size", data_->size);
}
void LoadComponent(Scene::Object_ *data_, const json &js, const Reader &deps_ir, const ReadProvider &deps_ip, PipelineResources &resources,
const PipelineInfo &pipeline, bool queue_texture_loads, bool do_not_load_resources) {
const std::string name = js.at("name");
if (!name.empty()) {
if (do_not_load_resources)
data_->model = resources.models.Add(name.c_str(), {});
else
data_->model = LoadModel(deps_ir, deps_ip, name.c_str(), resources);
}
const auto i_mats = js.find("materials");
if (i_mats != std::end(js)) {
const auto &mats = *i_mats;
const auto mat_count = mats.size();
data_->materials.resize(mat_count);
for (size_t i = 0; i < mat_count; ++i)
data_->materials[i] = LoadMaterial(mats[i], deps_ir, deps_ip, resources, pipeline, queue_texture_loads, do_not_load_resources);
}
const auto i_mat_infos = js.find("material_infos");
if (i_mat_infos != std::end(js)) {
const auto &mat_infos = *i_mat_infos;
const auto mat_count = data_->materials.size();
data_->material_infos.resize(mat_count);
for (size_t i = 0; i < mat_count; ++i) {
if (i == mat_infos.size())
break;
mat_infos[i]["name"].get_to(data_->material_infos[i].name);
}
}
const auto i_bones = js.find("bones");
if (i_bones != std::end(js)) {
const auto &bones = *i_bones;
const auto bone_count = bones.size();
data_->bones.resize(bone_count);
for (size_t i = 0; i < bone_count; ++i)
data_->bones[i] = bones[i];
}
}
void LoadComponent(Scene::Light_ *data_, const json &js) {
data_->type = js["type"];
if (js.find("shadow_type") != std::end(js))
data_->shadow_type = js["shadow_type"];
data_->diffuse = js["diffuse"];
if (js.contains("diffuse_intensity"))
data_->diffuse_intensity = js["diffuse_intensity"];
data_->specular = js["specular"];
if (js.contains("specular_intensity"))
data_->specular_intensity = js["specular_intensity"];
data_->radius = js["radius"];
data_->inner_angle = js["inner_angle"];
data_->outer_angle = js["outer_angle"];
if (js.find("pssm_split") != std::end(js))
data_->pssm_split = js["pssm_split"];
data_->priority = js["priority"];
if (js.find("shadow_bias") != std::end(js))
data_->shadow_bias = js["shadow_bias"];
}
void LoadComponent(Scene::RigidBody_ *data_, const json &js) {
data_->type = js.at("type");
data_->cur = js.at("world");
if (js.find("scale") != std::end(js))
data_->scl = js.at("scale");
if (js.find("linear_damping") != std::end(js))
data_->linear_damping = js.at("linear_damping");
if (js.find("angular_damping") != std::end(js))
data_->angular_damping = js.at("angular_damping");
if (js.find("restitution") != std::end(js))
data_->restitution = js.at("restitution");
if (js.find("friction") != std::end(js))
data_->friction = js.at("friction");
if (js.find("rolling_friction") != std::end(js))
data_->rolling_friction = js.at("rolling_friction");
}
void LoadComponent(Scene::Script_ *data_, const json &js) {
data_->path = js["path"].get<std::string>();
const auto j = js.find("parameters");
if (j != std::end(js))
for (auto i : j->items()) {
auto &v = i.value();
const auto type = v["type"].get<std::string>();
ScriptParam parm{};
if (type == "bool") {
parm.type = SPT_Bool;
parm.bv = v["value"].get<bool>();
} else if (type == "int") {
parm.type = SPT_Int;
parm.iv = v["value"].get<int>();
} else if (type == "float") {
parm.type = SPT_Float;
parm.fv = v["value"].get<float>();
} else if (type == "string") {
parm.type = SPT_String;
parm.sv = v["value"].get<std::string>();
}
data_->params[i.key()] = std::move(parm);
}
}
void LoadComponent(Scene::Instance_ *data_, const json &js) {
js["name"].get_to(data_->name);
if (js.find("anim") != std::end(js)) {
js["anim"].get_to(data_->anim);
data_->loop_mode = js["loop_mode"];
}
}
void LoadComponent(Scene::Collision_ *data_, const json &js) {
data_->type = js["type"];
data_->mass = js["mass"];
data_->size = js["size"];
data_->resource_path = js["path"].get<std::string>();
data_->m = js["m"];
}
//
bool Scene::Save_json(json &js, const PipelineResources &resources, uint32_t save_flags, const std::vector<NodeRef> *nodes_to_save) const {
// prepare list of nodes to save
std::vector<NodeRef> node_refs;
if (save_flags & LSSF_Nodes) {
if (nodes_to_save) {
node_refs = *nodes_to_save;
} else {
node_refs.reserve(nodes.size());
for (auto ref = nodes.first_ref(); ref != InvalidNodeRef; ref = nodes.next_ref(ref))
node_refs.push_back(ref);
}
}
// [EJ-10082019] do not save instantiated nodes
node_refs.erase(std::remove_if(std::begin(node_refs), std::end(node_refs),
[&](const NodeRef &ref) {
if (const auto *node_ = GetNode_(ref))
if (node_->flags & NF_Instantiated)
return true;
return false;
}),
std::end(node_refs));
//
std::array<std::set<ComponentRef>, 5> used_component_refs;
std::set<ComponentRef> used_script_refs, used_instance_refs;
if (save_flags & LSSF_Nodes)
for (const auto ref : node_refs)
if (const auto *node_ = GetNode_(ref)) {
if (transforms.is_valid(node_->components[NCI_Transform]))
used_component_refs[NCI_Transform].insert(node_->components[NCI_Transform]);
if (cameras.is_valid(node_->components[NCI_Camera]))
used_component_refs[NCI_Camera].insert(node_->components[NCI_Camera]);
if (objects.is_valid(node_->components[NCI_Object]))
used_component_refs[NCI_Object].insert(node_->components[NCI_Object]);
if (lights.is_valid(node_->components[NCI_Light]))
used_component_refs[NCI_Light].insert(node_->components[NCI_Light]);
if (rigid_bodies.is_valid(node_->components[NCI_RigidBody]))
used_component_refs[NCI_RigidBody].insert(node_->components[NCI_RigidBody]);
{
const auto &i = node_scripts.find(ref);
if (i != std::end(node_scripts))
for (const auto script_ref : i->second)
used_script_refs.insert(script_ref);
}
{
const auto &i = node_instance.find(ref);
if (i != std::end(node_instance))
used_instance_refs.insert(i->second);
}
}
if (save_flags & LSSF_Scene)
for (auto ref : scene_scripts)
used_script_refs.insert(ref); // flag scene scripts as in-use
//
if (!used_component_refs[NCI_Transform].empty()) {
auto &js_trsf = js["transforms"];
for (const auto ref : used_component_refs[NCI_Transform]) {
if (transforms.is_valid(ref)) {
json js_comp;
SaveComponent(&transforms[ref.idx], js_comp);
js_trsf.push_back(js_comp);
}
}
}
if (!used_component_refs[NCI_Camera].empty()) {
auto &js_cams = js["cameras"];
for (const auto ref : used_component_refs[NCI_Camera]) {
if (cameras.is_valid(ref)) {
json js_comp;
SaveComponent(&cameras[ref.idx], js_comp);
js_cams.push_back(js_comp);
}
}
}
if (!used_component_refs[NCI_Object].empty()) {
auto &js_objs = js["objects"];
for (const auto ref : used_component_refs[NCI_Object]) {
if (objects.is_valid(ref)) {
json js_comp;
SaveComponent(&objects[ref.idx], js_comp, resources);
js_objs.push_back(js_comp);
}
}
}
if (!used_component_refs[NCI_Light].empty()) {
auto &js_lgts = js["lights"];
for (const auto ref : used_component_refs[NCI_Light]) {
if (lights.is_valid(ref)) {
json js_comp;
SaveComponent(&lights[ref.idx], js_comp);
js_lgts.push_back(js_comp);
}
}
}
if (!used_component_refs[NCI_RigidBody].empty()) {
auto &js_bodies = js["rigid_bodies"];
for (const auto ref : used_component_refs[NCI_RigidBody]) {
if (rigid_bodies.is_valid(ref)) {
json js_comp;
SaveComponent(&rigid_bodies[ref.idx], js_comp);
js_bodies.push_back(js_comp);
}
}
}
if (!used_script_refs.empty()) {
auto &js_scripts = js["scripts"];
for (const auto ref : used_script_refs) {
if (scripts.is_valid(ref)) {
json js_comp;
SaveComponent(&scripts[ref.idx], js_comp);
js_scripts.push_back(js_comp);
}
}
}
if (!used_instance_refs.empty()) {
auto &js_inss = js["instances"];
for (const auto ref : used_instance_refs) {
if (instances.is_valid(ref)) {
json js_comp;
SaveComponent(&instances[ref.idx], js_comp);
js_inss.push_back(js_comp);
}
}
}
//
if (save_flags & LSSF_Nodes) {
auto &js_nodes = js["nodes"];
for (const auto ref : node_refs)
if (const auto *node_ = GetNode_(ref)) {
json js_node;
js_node["idx"] = ref;
js_node["name"] = node_->name;
js_node["disabled"] = node_->flags & NF_Disabled ? true : false;
std::array<uint32_t, 5> idxs = {0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff};
if (transforms.is_valid(node_->components[NCI_Transform])) {
const auto i = used_component_refs[NCI_Transform].find(node_->components[NCI_Transform]);
idxs[NCI_Transform] = numeric_cast<uint32_t>(std::distance(std::begin(used_component_refs[NCI_Transform]), i));
}
if (cameras.is_valid(node_->components[NCI_Camera])) {
const auto i = used_component_refs[NCI_Camera].find(node_->components[NCI_Camera]);
idxs[NCI_Camera] = numeric_cast<uint32_t>(std::distance(std::begin(used_component_refs[NCI_Camera]), i));
}
if (objects.is_valid(node_->components[NCI_Object])) {
const auto i = used_component_refs[NCI_Object].find(node_->components[NCI_Object]);
idxs[NCI_Object] = numeric_cast<uint32_t>(std::distance(std::begin(used_component_refs[NCI_Object]), i));
}
if (lights.is_valid(node_->components[NCI_Light])) {
const auto i = used_component_refs[NCI_Light].find(node_->components[NCI_Light]);
idxs[NCI_Light] = numeric_cast<uint32_t>(std::distance(std::begin(used_component_refs[NCI_Light]), i));
}
if (rigid_bodies.is_valid(node_->components[NCI_RigidBody])) {
const auto i = used_component_refs[NCI_RigidBody].find(node_->components[NCI_RigidBody]);
idxs[NCI_RigidBody] = numeric_cast<uint32_t>(std::distance(std::begin(used_component_refs[NCI_RigidBody]), i));
}
js_node["components"] = idxs;
{
const auto &c = node_scripts.find(ref);
if (c != std::end(node_scripts)) {
auto &js_node_scripts = js_node["scripts"];
for (const auto script_ref : c->second) {
const auto i = used_script_refs.find(script_ref);
json script;
script["idx"] = std::distance(std::begin(used_script_refs), i);
js_node_scripts.push_back(script);
}
}
}
{
const auto &c = node_instance.find(ref);
if (c != std::end(node_instance)) {
const auto i = used_instance_refs.find(c->second);
js_node["instance"] = std::distance(std::begin(used_instance_refs), i);
}
}
js_nodes.push_back(js_node);
}
}
if (save_flags & LSSF_Scene) {
auto &env = js["environment"];
if (save_flags & LSSF_Nodes)
env["current_camera"] = current_camera;
env["ambient"] = environment.ambient;
env["fog_near"] = environment.fog_near;
env["fog_far"] = environment.fog_far;
env["fog_color"] = environment.fog_color;
if (environment.irradiance_map != InvalidTextureRef)
env["irradiance_map"] = resources.textures.GetName(environment.irradiance_map);
if (environment.radiance_map != InvalidTextureRef)
env["radiance_map"] = resources.textures.GetName(environment.radiance_map);
if (environment.brdf_map != InvalidTextureRef)
env["brdf_map"] = resources.textures.GetName(environment.brdf_map);
auto &cvs = js["canvas"];
cvs["clear_z"] = canvas.clear_z;
cvs["clear_color"] = canvas.clear_color;
cvs["color"] = canvas.color;
}
if (save_flags & LSSF_Anims) {
{
json anims_js;
for (auto ref = anims.first_ref(); ref != InvalidAnimRef; ref = anims.next_ref(ref)) {
const auto &anim = anims[ref.idx];
if (anim.flags & AF_Instantiated)
continue;
json anim_js = {{"idx", ref.idx}};
SaveAnimToJson(anim_js["anim"], anim);
anims_js.push_back(std::move(anim_js));
}
if (!anims_js.empty())
js["anims"] = std::move(anims_js);
}
{
json scene_anims_js;
for (auto ref = scene_anims.first_ref(); ref != InvalidAnimRef; ref = scene_anims.next_ref(ref)) {
const auto &scene_anim = scene_anims[ref.idx];
if (scene_anim.flags & SAF_Instantiated)
continue;
json scene_anim_js = {
{"name", scene_anim.name},
{"t_start", scene_anim.t_start},
{"t_end", scene_anim.t_end},
{"anim", scene_anim.scene_anim},
{"frame_duration", scene_anim.frame_duration},
};
{
auto &node_anims_js = scene_anim_js["node_anims"];
for (const auto &node_anim : scene_anim.node_anims)
node_anims_js.push_back({
{"node", node_anim.node.idx},
{"anim", node_anim.anim.idx},
});
}
scene_anims_js.push_back(std::move(scene_anim_js));
}
if (!scene_anims_js.empty())
js["scene_anims"] = std::move(scene_anims_js);
}
}
if (save_flags & LSSF_KeyValues) {
auto &kv = js["key_values"];
for (auto i : key_values)
kv[i.first] = i.second;
}
return true;
}
bool Scene::Load_json(const json &js, const char *name, const Reader &deps_ir, const ReadProvider &deps_ip, PipelineResources &resources,
const PipelineInfo &pipeline, LoadSceneContext &ctx, uint32_t load_flags) {
if (js.empty()) {
error(format("Cannot load scene '%1', empty JSON").arg(name));
return false;
}
const auto t_start = time_now();
//
std::vector<ComponentRef> transform_refs;
{
const auto &i = js.find("transforms");
if (i != std::end(js)) {
const auto transform_count = i->size();
transform_refs.resize(transform_count);
int n = 0;
for (const auto &j : *i) {
const auto ref = transform_refs[n++] = CreateTransform().ref;
LoadComponent(&transforms[ref.idx], j);
}
}
}
std::vector<ComponentRef> camera_refs;
{
const auto &i = js.find("cameras");
if (i != std::end(js)) {
const auto camera_count = i->size();
camera_refs.resize(camera_count);
int n = 0;
for (const auto &j : *i) {
const auto ref = camera_refs[n++] = CreateCamera().ref;
LoadComponent(&cameras[ref.idx], j);
}
}
}
std::vector<ComponentRef> object_refs;
{
const auto &i = js.find("objects");
if (i != std::end(js)) {
const auto object_count = i->size();
object_refs.resize(object_count);
int n = 0;
for (const auto &j : *i) {
const auto ref = object_refs[n++] = CreateObject().ref;
LoadComponent(
&objects[ref.idx], j, deps_ir, deps_ip, resources, pipeline, load_flags & LSSF_QueueTextureLoads, load_flags & LSSF_DoNotLoadResources);
}
}
}
std::vector<ComponentRef> light_refs;
{
const auto &i = js.find("lights");
if (i != std::end(js)) {
const auto light_count = i->size();
light_refs.resize(light_count);
int n = 0;
for (const auto &j : *i) {
const auto ref = light_refs[n++] = CreateLight().ref;
LoadComponent(&lights[ref.idx], j);
}
}
}
std::vector<ComponentRef> rigid_body_refs;
{
const auto &i = js.find("rigid_bodies");
if (i != std::end(js)) {
const auto rigid_body_count = i->size();
rigid_body_refs.resize(rigid_body_count);
int n = 0;
for (const auto &j : *i) {
const auto ref = rigid_body_refs[n++] = CreateRigidBody().ref;
LoadComponent(&rigid_bodies[ref.idx], j);
}
}
}
std::vector<ComponentRef> script_refs;
{
const auto &i = js.find("scripts");
if (i != std::end(js)) {
const auto scripts_count = i->size();
script_refs.resize(scripts_count);
int n = 0;
for (const auto &j : *i) {
const auto ref = script_refs[n++] = CreateScript().ref;
LoadComponent(&scripts[ref.idx], j);
}
}
}
std::vector<ComponentRef> instance_refs;
{
const auto &i = js.find("instances");
if (i != std::end(js)) {
const auto instance_count = i->size();
instance_refs.resize(instance_count);
int n = 0;
for (const auto &j : *i) {
const auto ref = instance_refs[n++] = CreateInstance().ref;
LoadComponent(&instances[ref.idx], j);
}
}
}
//
std::vector<NodeRef> nodes_to_disable;
const auto &js_nodes = js.find("nodes");
if (js_nodes != std::end(js)) {
std::vector<NodeRef> node_with_instance_to_setup;
node_with_instance_to_setup.reserve(64);
const auto node_count = js_nodes->size();
for (const auto &js_node : *js_nodes) {
auto node = CreateNode();
auto node_ = nodes[node.ref.idx];
ctx.node_refs[js_node["idx"].get<uint32_t>()] = node.ref;
ctx.view.nodes.push_back(node.ref);
node.SetName(js_node["name"].get<std::string>());
{
const auto &i = js_node.find("disabled");
if ((i != std::end(js_node)) && (i->get<bool>() == true))
nodes_to_disable.push_back(node.ref);
}
{
const auto &js_node_components = js_node["components"];
const auto transform_idx = js_node_components[NCI_Transform].get<ComponentRef>().idx;
if (transform_idx != 0xffffffff)
nodes[node.ref.idx].components[NCI_Transform] = transform_refs[transform_idx];
const auto camera_idx = js_node_components[NCI_Camera].get<ComponentRef>().idx;
if (camera_idx != 0xffffffff)
nodes[node.ref.idx].components[NCI_Camera] = camera_refs[camera_idx];
const auto object_idx = js_node_components[NCI_Object].get<ComponentRef>().idx;
if (object_idx != 0xffffffff)
nodes[node.ref.idx].components[NCI_Object] = object_refs[object_idx];
const auto light_idx = js_node_components[NCI_Light].get<ComponentRef>().idx;
if (light_idx != 0xffffffff)
nodes[node.ref.idx].components[NCI_Light] = light_refs[light_idx];
const auto rigid_body_idx = js_node_components[NCI_RigidBody].get<ComponentRef>().idx;
if (rigid_body_idx != 0xffffffff)
nodes[node.ref.idx].components[NCI_RigidBody] = rigid_body_refs[rigid_body_idx];
}
{
const auto &js_scripts = js_node.find("scripts");
if (js_scripts != std::end(js_node)) {
const auto node_script_count = js_scripts->size();
node_scripts[node.ref].reserve(node_script_count);
for (auto &js_script : *js_scripts) {
const auto script_idx = js_script["idx"].get<ComponentRef>().idx;
if (script_idx != 0xffffffff) {
const auto script_ref = script_refs[script_idx];
node_scripts[node.ref].push_back(script_ref);
} else {
node_scripts[node.ref].push_back(InvalidComponentRef);
}
}
}
}
{
const auto &js_node_instance = js_node.find("instance");
if (js_node_instance != std::end(js_node)) {
const auto instance_idx = js_node_instance->get<ComponentRef>().idx;
if (instance_idx != 0xffffffff) {
node_instance[node.ref] = instance_refs[instance_idx];
node_with_instance_to_setup.push_back(node.ref);
}
}
}
}
// setup instances
if (!(load_flags & LSSF_DoNotLoadResources))
for (const auto ref : node_with_instance_to_setup) {
NodeSetupInstance(ref, deps_ir, deps_ip, resources, pipeline, LSSF_AllNodeFeatures, ctx.recursion_level + 1);
NodeStartOnInstantiateAnim(ref);
}
// fix parent references
for (const auto ref : transform_refs) {
auto &c = transforms[ref.idx];
if (c.parent != InvalidNodeRef) {
const auto &i = ctx.node_refs.find(c.parent.idx);
c.parent = i != std::end(ctx.node_refs) ? i->second : InvalidNodeRef;
}
}
// fix bone references
for (const auto ref : object_refs) {
auto &c = objects[ref.idx];
for (auto &ref : c.bones)
if (ref != InvalidNodeRef) {
const auto &i = ctx.node_refs.find(ref.idx);
ref = i != std::end(ctx.node_refs) ? i->second : InvalidNodeRef;
}
}
}
if (load_flags & LSSF_Scene) {
{
const auto &js_env = js.find("environment");
if (js_env != std::end(js)) {
const auto &js_current_camera = js_env->find("current_camera");
if (js_current_camera != std::end(*js_env)) {
const auto current_camera_idx = js_current_camera->get<NodeRef>().idx;
current_camera = ctx.node_refs[current_camera_idx];
}
environment.ambient = (*js_env)["ambient"];
environment.fog_near = (*js_env)["fog_near"];
environment.fog_far = (*js_env)["fog_far"];
environment.fog_color = (*js_env)["fog_color"];
{
auto i = js_env->find("irradiance_map");
if (i != std::end(*js_env)) {
if (load_flags & LSSF_DoNotLoadResources) {
environment.irradiance_map = resources.textures.Add(i->get<std::string>().c_str(), {});
} else {
if (load_flags & LSSF_QueueTextureLoads)
environment.irradiance_map = QueueLoadTexture(deps_ir, deps_ip, i->get<std::string>().c_str(), BGFX_SAMPLER_NONE, resources);
else
environment.irradiance_map = LoadTexture(deps_ir, deps_ip, i->get<std::string>().c_str(), BGFX_SAMPLER_NONE, resources);
}
}
i = js_env->find("radiance_map");
if (i != std::end(*js_env)) {
if (load_flags & LSSF_DoNotLoadResources) {
environment.radiance_map = resources.textures.Add(i->get<std::string>().c_str(), {});
} else {
if (load_flags & LSSF_QueueTextureLoads)
environment.radiance_map = QueueLoadTexture(deps_ir, deps_ip, i->get<std::string>().c_str(), BGFX_SAMPLER_NONE, resources);
else
environment.radiance_map = LoadTexture(deps_ir, deps_ip, i->get<std::string>().c_str(), BGFX_SAMPLER_NONE, resources);
}
}
i = js_env->find("brdf_map");
if (i != std::end(*js_env)) {
if (load_flags & LSSF_DoNotLoadResources) {
environment.brdf_map = resources.textures.Add(i->get<std::string>().c_str(), {});
} else {
if (load_flags & LSSF_QueueTextureLoads)
environment.brdf_map = QueueLoadTexture(deps_ir, deps_ip, i->get<std::string>().c_str(), BGFX_SAMPLER_NONE, resources);
else
environment.brdf_map = LoadTexture(deps_ir, deps_ip, i->get<std::string>().c_str(), BGFX_SAMPLER_NONE, resources);
}
}
}
}
}
{
const auto &js_cvs = js.find("canvas");
if (js_cvs != std::end(js)) {
canvas.clear_z = (*js_cvs)["clear_z"];
canvas.clear_color = (*js_cvs)["clear_color"];
canvas.color = (*js_cvs)["color"];
}
}
}
if (load_flags & LSSF_Anims) {
std::map<uint32_t, AnimRef> anim_refs;
{
const auto &js_anims = js.find("anims");
if (js_anims != std::end(js))
for (const auto &js_anim : *js_anims) {
Anim anim;
LoadAnimFromJson(js_anim["anim"], anim);
const auto anim_ref = AddAnim(anim);
ctx.view.anims.push_back(anim_ref);
const uint32_t idx = js_anim["idx"];
anim_refs[idx] = anim_ref;
}
}
{
const auto &js_scene_anims = js.find("scene_anims");
if (js_scene_anims != std::end(js)) {
for (const auto &js_scene_anim : *js_scene_anims) {
SceneAnim scene_anim;
js_scene_anim.at("name").get_to(scene_anim.name);
scene_anim.t_start = js_scene_anim.at("t_start");
scene_anim.t_end = js_scene_anim.at("t_end");
scene_anim.scene_anim = js_scene_anim.at("anim");
scene_anim.frame_duration = js_scene_anim.at("frame_duration");
const auto &i_scene_anim = anim_refs.find(scene_anim.scene_anim.idx);
if (i_scene_anim != std::end(anim_refs))
scene_anim.scene_anim = i_scene_anim->second;
const auto &js_node_anims = js_scene_anim.find("node_anims");
if (js_node_anims != std::end(js_scene_anim))
for (const auto js_node_anim : *js_node_anims) {
const uint32_t node_idx = js_node_anim["node"];
const uint32_t anim_idx = js_node_anim["anim"];
const auto &i_node_ref = ctx.node_refs.find(node_idx); // remap node
const auto &i_anim_ref = anim_refs.find(anim_idx); // remap anim
if (i_node_ref != std::end(ctx.node_refs) && i_anim_ref != std::end(anim_refs))
scene_anim.node_anims.push_back({i_node_ref->second, i_anim_ref->second});
}
const auto scene_anim_ref = AddSceneAnim(scene_anim);
ctx.view.scene_anims.push_back(scene_anim_ref);
}
}
}
}
if (load_flags & LSSF_KeyValues) {
const auto &js_key_values = js.find("key_values");
if (js_key_values != std::end(js))
for (auto i : js_key_values->items())
key_values[i.key()] = i.value().get<std::string>();
}
//
for (const auto &ref : nodes_to_disable)
DisableNode(ref);
//
ReadyWorldMatrices();
ComputeWorldMatrices();
//
debug(format("Load scene '%1' took %2 ms").arg(name).arg(time_to_ms(time_now() - t_start)));
return true;
}
} // namespace hg