Skip to content

Commit

Permalink
Enable nested VoxelModifiers
Browse files Browse the repository at this point in the history
  • Loading branch information
sjkillen committed Sep 30, 2023
1 parent 02596c1 commit 2763bb8
Showing 1 changed file with 42 additions and 33 deletions.
75 changes: 42 additions & 33 deletions modifiers/godot/voxel_modifier_gd.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
namespace zylann::voxel::gd {

VoxelModifier::VoxelModifier() {
set_notify_local_transform(true);
set_notify_transform(true);
}

zylann::voxel::VoxelModifier *VoxelModifier::create(zylann::voxel::VoxelModifierStack &modifiers, uint32_t id) {
Expand Down Expand Up @@ -73,36 +73,6 @@ float VoxelModifier::get_smoothness() const {

void VoxelModifier::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_PARENTED: {
Node *parent = get_parent();
ZN_ASSERT_RETURN(parent != nullptr);
ZN_ASSERT_RETURN(_volume == nullptr);
VoxelLodTerrain *volume = Object::cast_to<VoxelLodTerrain>(parent);
_volume = volume;

if (_volume != nullptr) {
VoxelData &voxel_data = _volume->get_storage();
VoxelModifierStack &modifiers = voxel_data.get_modifiers();
const uint32_t id = modifiers.allocate_id();
zylann::voxel::VoxelModifier *modifier = create(modifiers, id);

if (modifier->is_sdf()) {
zylann::voxel::VoxelModifierSdf *sdf_modifier =
static_cast<zylann::voxel::VoxelModifierSdf *>(modifier);
sdf_modifier->set_operation(to_op(_operation));
sdf_modifier->set_smoothness(_smoothness);
}

modifier->set_transform(get_transform());
_modifier_id = id;
// TODO Optimize: on loading of a scene, this could be very bad for performance because there could be,
// a lot of modifiers on the map, but there is no distinction possible in Godot at the moment...
post_edit_modifier(*_volume, modifier->get_aabb());
}

update_configuration_warnings();
} break;

case NOTIFICATION_UNPARENTED: {
if (_volume != nullptr) {
VoxelData &voxel_data = _volume->get_storage();
Expand All @@ -115,16 +85,55 @@ void VoxelModifier::_notification(int p_what) {
_modifier_id = 0;
}
} break;
case Node3D::NOTIFICATION_TRANSFORM_CHANGED: {
if (_volume == nullptr) {
Node *parent = get_parent();
VoxelLodTerrain *volume = Object::cast_to<VoxelLodTerrain>(parent);
// Using get_parent_node_3d when terrain is immediate parent
// would be a breaking change as it returns null if node is toplevel
if (volume == nullptr) {
Node3D *grandparent = get_parent_node_3d();
volume = Object::cast_to<VoxelLodTerrain>(grandparent);
while (grandparent != nullptr && volume == nullptr) {
grandparent = grandparent->get_parent_node_3d();
volume = Object::cast_to<VoxelLodTerrain>(grandparent);
}
}
_volume = volume;


if (_volume != nullptr) {
VoxelData &voxel_data = _volume->get_storage();
VoxelModifierStack &modifiers = voxel_data.get_modifiers();
const uint32_t id = modifiers.allocate_id();
zylann::voxel::VoxelModifier *modifier = create(modifiers, id);

if (modifier->is_sdf()) {
zylann::voxel::VoxelModifierSdf *sdf_modifier =
static_cast<zylann::voxel::VoxelModifierSdf *>(modifier);
sdf_modifier->set_operation(to_op(_operation));
sdf_modifier->set_smoothness(_smoothness);
}
// This transform is wrong, but will be updated with NOTIFICATION_TRANSFORM_CHANGED
// After node enters the tree
modifier->set_transform(get_transform());
_modifier_id = id;
// TODO Optimize: on loading of a scene, this could be very bad for performance because there could be,
// a lot of modifiers on the map, but there is no distinction possible in Godot at the moment...
post_edit_modifier(*_volume, modifier->get_aabb());
}
}

case Node3D::NOTIFICATION_LOCAL_TRANSFORM_CHANGED: {
update_configuration_warnings();
if (_volume != nullptr && is_inside_tree()) {
VoxelData &voxel_data = _volume->get_storage();
VoxelModifierStack &modifiers = voxel_data.get_modifiers();
zylann::voxel::VoxelModifier *modifier = modifiers.get_modifier(_modifier_id);
ZN_ASSERT_RETURN(modifier != nullptr);

const AABB prev_aabb = modifier->get_aabb();
modifier->set_transform(get_transform());
Transform3D terrain_local = _volume->get_global_transform().affine_inverse() * get_global_transform();
modifier->set_transform(terrain_local);
const AABB aabb = modifier->get_aabb();
post_edit_modifier(*_volume, prev_aabb);
post_edit_modifier(*_volume, aabb);
Expand Down

0 comments on commit 2763bb8

Please sign in to comment.