summaryrefslogtreecommitdiff
path: root/servers/visual/visual_server_scene.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'servers/visual/visual_server_scene.cpp')
-rw-r--r--servers/visual/visual_server_scene.cpp109
1 files changed, 84 insertions, 25 deletions
diff --git a/servers/visual/visual_server_scene.cpp b/servers/visual/visual_server_scene.cpp
index e49baf0763..eef4720d22 100644
--- a/servers/visual/visual_server_scene.cpp
+++ b/servers/visual/visual_server_scene.cpp
@@ -303,6 +303,23 @@ void VisualServerScene::instance_set_base(RID p_instance, RID p_base) {
VSG::storage->instance_remove_dependency(instance->base, instance);
+ if (instance->base_type == VS::INSTANCE_GI_PROBE) {
+ //if gi probe is baking, wait until done baking, else race condition may happen when removing it
+ //from octree
+ InstanceGIProbeData *gi_probe = static_cast<InstanceGIProbeData *>(instance->base_data);
+
+ //make sure probes are done baking
+ while (!probe_bake_list.empty()) {
+ OS::get_singleton()->delay_usec(1);
+ }
+ //make sure this one is done baking
+
+ while (gi_probe->dynamic.updating_stage == GI_UPDATE_STAGE_LIGHTING) {
+ //wait until bake is done if it's baking
+ OS::get_singleton()->delay_usec(1);
+ }
+ }
+
if (scenario && instance->octree_id) {
scenario->octree.erase(instance->octree_id); //make dependencies generated by the octree go away
instance->octree_id = 0;
@@ -331,10 +348,6 @@ void VisualServerScene::instance_set_base(RID p_instance, RID p_base) {
InstanceGIProbeData *gi_probe = static_cast<InstanceGIProbeData *>(instance->base_data);
- while (gi_probe->dynamic.updating_stage == GI_UPDATE_STAGE_LIGHTING) {
- //wait until bake is done if it's baking
- OS::get_singleton()->delay_usec(1);
- }
if (gi_probe->update_element.in_list()) {
gi_probe_update_list.remove(&gi_probe->update_element);
}
@@ -587,6 +600,36 @@ void VisualServerScene::instance_set_visible(RID p_instance, bool p_visible) {
}
}
+inline bool is_geometry_instance(VisualServer::InstanceType p_type) {
+ return p_type == VS::INSTANCE_MESH || p_type == VS::INSTANCE_MULTIMESH || p_type == VS::INSTANCE_PARTICLES || p_type == VS::INSTANCE_IMMEDIATE;
+}
+
+void VisualServerScene::instance_set_custom_aabb(RID p_instance, AABB p_aabb) {
+
+ Instance *instance = instance_owner.get(p_instance);
+ ERR_FAIL_COND(!instance);
+ ERR_FAIL_COND(!is_geometry_instance(instance->base_type));
+
+ if (p_aabb != AABB()) {
+
+ // Set custom AABB
+ if (instance->custom_aabb == NULL)
+ instance->custom_aabb = memnew(AABB);
+ *instance->custom_aabb = p_aabb;
+
+ } else {
+
+ // Clear custom AABB
+ if (instance->custom_aabb != NULL) {
+ memdelete(instance->custom_aabb);
+ instance->custom_aabb = NULL;
+ }
+ }
+
+ if (instance->scenario)
+ _instance_queue_update(instance, true, false);
+}
+
void VisualServerScene::instance_attach_skeleton(RID p_instance, RID p_skeleton) {
Instance *instance = instance_owner.get(p_instance);
@@ -614,7 +657,7 @@ void VisualServerScene::instance_set_exterior(RID p_instance, bool p_enabled) {
void VisualServerScene::instance_set_extra_visibility_margin(RID p_instance, real_t p_margin) {
}
-Vector<ObjectID> VisualServerScene::instances_cull_aabb(const Rect3 &p_aabb, RID p_scenario) const {
+Vector<ObjectID> VisualServerScene::instances_cull_aabb(const AABB &p_aabb, RID p_scenario) const {
Vector<ObjectID> instances;
Scenario *scenario = scenario_owner.get(p_scenario);
@@ -647,7 +690,7 @@ Vector<ObjectID> VisualServerScene::instances_cull_ray(const Vector3 &p_from, co
int culled = 0;
Instance *cull[1024];
- culled = scenario->octree.cull_segment(p_from, p_to * 10000, cull, 1024);
+ culled = scenario->octree.cull_segment(p_from, p_from + p_to * 10000, cull, 1024);
for (int i = 0; i < culled; i++) {
Instance *instance = cull[i];
@@ -772,7 +815,7 @@ void VisualServerScene::_update_instance(Instance *p_instance) {
p_instance->mirror = p_instance->transform.basis.determinant() < 0.0;
- Rect3 new_aabb;
+ AABB new_aabb;
new_aabb = p_instance->transform.xform(p_instance->aabb);
@@ -817,7 +860,7 @@ void VisualServerScene::_update_instance(Instance *p_instance) {
void VisualServerScene::_update_instance_aabb(Instance *p_instance) {
- Rect3 new_aabb;
+ AABB new_aabb;
ERR_FAIL_COND(p_instance->base_type != VS::INSTANCE_NONE && !p_instance->base.is_valid());
@@ -828,23 +871,35 @@ void VisualServerScene::_update_instance_aabb(Instance *p_instance) {
} break;
case VisualServer::INSTANCE_MESH: {
- new_aabb = VSG::storage->mesh_get_aabb(p_instance->base, p_instance->skeleton);
+ if (p_instance->custom_aabb)
+ new_aabb = *p_instance->custom_aabb;
+ else
+ new_aabb = VSG::storage->mesh_get_aabb(p_instance->base, p_instance->skeleton);
} break;
case VisualServer::INSTANCE_MULTIMESH: {
- new_aabb = VSG::storage->multimesh_get_aabb(p_instance->base);
+ if (p_instance->custom_aabb)
+ new_aabb = *p_instance->custom_aabb;
+ else
+ new_aabb = VSG::storage->multimesh_get_aabb(p_instance->base);
} break;
case VisualServer::INSTANCE_IMMEDIATE: {
- new_aabb = VSG::storage->immediate_get_aabb(p_instance->base);
+ if (p_instance->custom_aabb)
+ new_aabb = *p_instance->custom_aabb;
+ else
+ new_aabb = VSG::storage->immediate_get_aabb(p_instance->base);
} break;
case VisualServer::INSTANCE_PARTICLES: {
- new_aabb = VSG::storage->particles_get_aabb(p_instance->base);
+ if (p_instance->custom_aabb)
+ new_aabb = *p_instance->custom_aabb;
+ else
+ new_aabb = VSG::storage->particles_get_aabb(p_instance->base);
} break;
case VisualServer::INSTANCE_LIGHT: {
@@ -866,6 +921,7 @@ void VisualServerScene::_update_instance_aabb(Instance *p_instance) {
default: {}
}
+ // <Zylann> This is why I didn't re-use Instance::aabb to implement custom AABBs
if (p_instance->extra_margin)
new_aabb.grow_by(p_instance->extra_margin);
@@ -1277,9 +1333,7 @@ void VisualServerScene::render_camera(RID p_camera, RID p_scenario, Size2 p_view
p_viewport_size.width / (float)p_viewport_size.height,
camera->znear,
camera->zfar,
- camera->vaspect
-
- );
+ camera->vaspect);
ortho = true;
} break;
case Camera::PERSPECTIVE: {
@@ -1289,9 +1343,7 @@ void VisualServerScene::render_camera(RID p_camera, RID p_scenario, Size2 p_view
p_viewport_size.width / (float)p_viewport_size.height,
camera->znear,
camera->zfar,
- camera->vaspect
-
- );
+ camera->vaspect);
ortho = false;
} break;
@@ -1812,7 +1864,7 @@ void VisualServerScene::_setup_gi_probe(Instance *p_instance) {
probe->dynamic.level_cell_lists.resize(header->cell_subdiv);
- _gi_probe_fill_local_data(0, 0, 0, 0, 0, cells, header, ldw.ptr(), probe->dynamic.level_cell_lists.ptr());
+ _gi_probe_fill_local_data(0, 0, 0, 0, 0, cells, header, ldw.ptr(), probe->dynamic.level_cell_lists.ptrw());
bool compress = VSG::storage->gi_probe_is_compressed(p_instance->base);
@@ -1863,7 +1915,7 @@ void VisualServerScene::_setup_gi_probe(Instance *p_instance) {
probe->dynamic.enabled = true;
Transform cell_to_xform = VSG::storage->gi_probe_get_to_cell_xform(p_instance->base);
- Rect3 bounds = VSG::storage->gi_probe_get_bounds(p_instance->base);
+ AABB bounds = VSG::storage->gi_probe_get_bounds(p_instance->base);
float cell_size = VSG::storage->gi_probe_get_cell_size(p_instance->base);
probe->dynamic.light_to_cell_xform = cell_to_xform * p_instance->transform.affine_inverse();
@@ -2546,7 +2598,15 @@ void VisualServerScene::_bake_gi_probe(Instance *p_gi_probe) {
}
//send back to main thread to update un little chunks
+ if (probe_bake_mutex) {
+ probe_bake_mutex->lock();
+ }
+
probe_data->dynamic.updating_stage = GI_UPDATE_STAGE_UPLOADING;
+
+ if (probe_bake_mutex) {
+ probe_bake_mutex->unlock();
+ }
}
bool VisualServerScene::_check_gi_probe(Instance *p_gi_probe) {
@@ -2562,7 +2622,7 @@ bool VisualServerScene::_check_gi_probe(Instance *p_gi_probe) {
InstanceGIProbeData::LightCache lc;
lc.type = VSG::storage->light_get_type(E->get()->base);
lc.color = VSG::storage->light_get_color(E->get()->base);
- lc.energy = VSG::storage->light_get_param(E->get()->base, VS::LIGHT_PARAM_ENERGY);
+ lc.energy = VSG::storage->light_get_param(E->get()->base, VS::LIGHT_PARAM_ENERGY) * VSG::storage->light_get_param(E->get()->base, VS::LIGHT_PARAM_INDIRECT_ENERGY);
lc.radius = VSG::storage->light_get_param(E->get()->base, VS::LIGHT_PARAM_RANGE);
lc.attenuation = VSG::storage->light_get_param(E->get()->base, VS::LIGHT_PARAM_ATTENUATION);
lc.spot_angle = VSG::storage->light_get_param(E->get()->base, VS::LIGHT_PARAM_SPOT_ANGLE);
@@ -2582,7 +2642,7 @@ bool VisualServerScene::_check_gi_probe(Instance *p_gi_probe) {
InstanceGIProbeData::LightCache lc;
lc.type = VSG::storage->light_get_type(E->get()->base);
lc.color = VSG::storage->light_get_color(E->get()->base);
- lc.energy = VSG::storage->light_get_param(E->get()->base, VS::LIGHT_PARAM_ENERGY);
+ lc.energy = VSG::storage->light_get_param(E->get()->base, VS::LIGHT_PARAM_ENERGY) * VSG::storage->light_get_param(E->get()->base, VS::LIGHT_PARAM_INDIRECT_ENERGY);
lc.radius = VSG::storage->light_get_param(E->get()->base, VS::LIGHT_PARAM_RANGE);
lc.attenuation = VSG::storage->light_get_param(E->get()->base, VS::LIGHT_PARAM_ATTENUATION);
lc.spot_angle = VSG::storage->light_get_param(E->get()->base, VS::LIGHT_PARAM_SPOT_ANGLE);
@@ -2678,12 +2738,11 @@ void VisualServerScene::render_probes() {
switch (probe->dynamic.updating_stage) {
case GI_UPDATE_STAGE_CHECK: {
- if (_check_gi_probe(instance_probe) || force_lighting) {
- //send to lighting thread
- probe->dynamic.updating_stage = GI_UPDATE_STAGE_LIGHTING;
+ if (_check_gi_probe(instance_probe) || force_lighting) { //send to lighting thread
#ifndef NO_THREADS
probe_bake_mutex->lock();
+ probe->dynamic.updating_stage = GI_UPDATE_STAGE_LIGHTING;
probe_bake_list.push_back(instance_probe);
probe_bake_mutex->unlock();
probe_bake_sem->post();