Skip to content

Commit

Permalink
VoxelTerrain can be transformed
Browse files Browse the repository at this point in the history
  • Loading branch information
Zylann committed Oct 24, 2020
1 parent 8508748 commit 85bb3d7
Show file tree
Hide file tree
Showing 5 changed files with 55 additions and 18 deletions.
2 changes: 2 additions & 0 deletions edition/voxel_tool.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ class VoxelRaycastResult : public Reference {
static void _bind_methods();
};

// TODO Need to review VoxelTool to account for transformed volumes

// High-level generic voxel edition utility.
// Ease of use comes at cost.
// It's not a class to instantiate alone, get it from the voxel objects you want to work with
Expand Down
2 changes: 1 addition & 1 deletion terrain/voxel_block.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,7 @@ void VoxelBlock::set_shader_material(Ref<ShaderMaterial> material) {

void VoxelBlock::set_transition_mask(uint8_t m) {
CRASH_COND(m >= (1 << Cube::SIDE_COUNT));
uint8_t diff = _transition_mask ^ m;
const uint8_t diff = _transition_mask ^ m;
if (diff == 0) {
return;
}
Expand Down
27 changes: 15 additions & 12 deletions terrain/voxel_lod_terrain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,7 @@ void VoxelLodTerrain::set_view_distance(int p_distance_in_voxels) {
_view_distance_voxels = p_distance_in_voxels;
}

Spatial *VoxelLodTerrain::get_viewer() const {
const Spatial *VoxelLodTerrain::get_viewer() const {
if (!is_inside_tree()) {
return nullptr;
}
Expand Down Expand Up @@ -463,7 +463,7 @@ void VoxelLodTerrain::_notification(int p_what) {
} break;

case NOTIFICATION_VISIBILITY_CHANGED: {
bool visible = is_visible();
const bool visible = is_visible();
for (unsigned int lod_index = 0; lod_index < _lods.size(); ++lod_index) {
if (_lods[lod_index].map.is_valid()) {
_lods[lod_index].map->for_all_blocks([visible](VoxelBlock *block) {
Expand All @@ -479,13 +479,15 @@ void VoxelLodTerrain::_notification(int p_what) {
} break;

case NOTIFICATION_TRANSFORM_CHANGED: {
const Transform transform = get_global_transform();
VoxelServer::get_singleton()->set_volume_transform(_volume_id, transform);

if (!is_inside_tree()) {
// The transform and other properties can be set by the scene loader,
// before we enter the tree
return;
}

Transform transform = get_global_transform();
for (unsigned int lod_index = 0; lod_index < _lods.size(); ++lod_index) {
if (_lods[lod_index].map.is_valid()) {
_lods[lod_index].map->for_all_blocks([&transform](VoxelBlock *block) {
Expand All @@ -508,11 +510,12 @@ void VoxelLodTerrain::get_viewer_pos_and_direction(Vector3 &out_pos, Vector3 &ou

} else {
// TODO Have option to use viewport camera
Spatial *viewer = get_viewer();
const Spatial *viewer = get_viewer();
if (viewer) {
Transform gt = viewer->get_global_transform();
out_pos = gt.origin;
out_direction = -gt.basis.get_axis(Vector3::AXIS_Z);
const Transform world_to_local = get_global_transform().affine_inverse();
out_pos = world_to_local.xform(gt.origin);
out_direction = world_to_local.basis.xform(-gt.basis.get_axis(Vector3::AXIS_Z));

} else {
// TODO Just remember last viewer pos
Expand Down Expand Up @@ -623,8 +626,7 @@ void VoxelLodTerrain::_process() {
return;
}

// Get viewer location
// TODO Transform to local (Spatial Transform)
// Get viewer location in voxel space
Vector3 viewer_pos;
Vector3 viewer_direction;
get_viewer_pos_and_direction(viewer_pos, viewer_direction);
Expand Down Expand Up @@ -1550,10 +1552,11 @@ AABB VoxelLodTerrain::_b_get_voxel_bounds() const {
// DEBUG LAND

Array VoxelLodTerrain::debug_raycast_block(Vector3 world_origin, Vector3 world_direction) const {
Vector3 pos = world_origin;
Vector3 dir = world_direction;
float max_distance = 256;
float step = 2.f;
const Transform world_to_local = get_global_transform().affine_inverse();
Vector3 pos = world_to_local.xform(world_origin);
const Vector3 dir = world_to_local.basis.xform(world_direction);
const float max_distance = 256;
const float step = 2.f;
float distance = 0.f;

Array hits;
Expand Down
2 changes: 1 addition & 1 deletion terrain/voxel_lod_terrain.h
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ class VoxelLodTerrain : public Spatial {
void _process();

private:
Spatial *get_viewer() const;
const Spatial *get_viewer() const;
void immerge_block(Vector3i block_pos, int lod_index);

void start_updater();
Expand Down
40 changes: 36 additions & 4 deletions terrain/voxel_terrain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ VoxelTerrain::VoxelTerrain() {
// Godot may create and destroy dozens of instances of all node types on startup,
// due to how ClassDB gets its default values.

set_notify_transform(true);

// Infinite by default
_bounds_in_voxels = Rect3i::from_center_extents(Vector3i(0), Vector3i(VoxelConstants::MAX_VOLUME_EXTENT));

Expand Down Expand Up @@ -743,7 +745,21 @@ void VoxelTerrain::_notification(int p_what) {
_map->for_all_blocks(SetParentVisibilityAction(is_visible()));
break;

// TODO Listen for transform changes
case NOTIFICATION_TRANSFORM_CHANGED: {
const Transform transform = get_global_transform();
VoxelServer::get_singleton()->set_volume_transform(_volume_id, transform);

if (!is_inside_tree()) {
// The transform and other properties can be set by the scene loader,
// before we enter the tree
return;
}

_map->for_all_blocks([&transform](VoxelBlock *block) {
block->set_parent_transform(transform);
});

} break;

default:
break;
Expand Down Expand Up @@ -819,6 +835,7 @@ void VoxelTerrain::_process() {
std::vector<size_t> unpaired_viewer_indexes;
{
// Our node doesn't have bounds yet, so for now viewers are always paired.
// TODO Update: the node has bounds now, need to change this

// Destroyed viewers
for (size_t i = 0; i < _paired_viewers.size(); ++i) {
Expand All @@ -830,8 +847,16 @@ void VoxelTerrain::_process() {
}
}

const Transform local_to_world_transform = get_global_transform();
const Transform world_to_local_transform = local_to_world_transform.affine_inverse();

// Note, this does not support non-uniform scaling
// TODO There is probably a better way to do this
const float view_distance_scale = world_to_local_transform.basis.xform(Vector3(1, 0, 0)).length();

// New viewers and updates
VoxelServer::get_singleton()->for_each_viewer([this](const VoxelServer::Viewer &viewer, uint32_t viewer_id) {
VoxelServer::get_singleton()->for_each_viewer([this, view_distance_scale, world_to_local_transform](
const VoxelServer::Viewer &viewer, uint32_t viewer_id) {
size_t i;
if (!try_get_paired_viewer_index(viewer_id, i)) {
PairedViewer p;
Expand All @@ -844,9 +869,13 @@ void VoxelTerrain::_process() {

p.prev_state = p.state;

const unsigned int view_distance_voxels =
static_cast<unsigned int>(static_cast<float>(viewer.view_distance) * view_distance_scale);
const Vector3 local_position = world_to_local_transform.xform(viewer.world_position);

p.state.view_distance_blocks =
min(viewer.view_distance >> get_block_size_pow2(), _max_view_distance_blocks);
p.state.block_position = _map->voxel_to_block(Vector3i(viewer.world_position));
min(view_distance_voxels >> get_block_size_pow2(), _max_view_distance_blocks);
p.state.block_position = _map->voxel_to_block(Vector3i(local_position));
p.state.requires_collisions = VoxelServer::get_singleton()->is_viewer_requiring_collisions(viewer_id);
p.state.requires_meshes = VoxelServer::get_singleton()->is_viewer_requiring_visuals(viewer_id);
});
Expand Down Expand Up @@ -1152,6 +1181,8 @@ void VoxelTerrain::_process() {
const uint32_t timeout = os.get_ticks_msec() + VoxelConstants::MAIN_THREAD_MESHING_BUDGET_MS;
size_t queue_index = 0;

const Transform local_to_world_transform = get_global_transform();

// The following is done on the main thread because Godot doesn't really support multithreaded Mesh allocation.
// This also proved to be very slow compared to the meshing process itself...
// hopefully Vulkan will allow us to upload graphical resources without stalling rendering as they upload?
Expand Down Expand Up @@ -1233,6 +1264,7 @@ void VoxelTerrain::_process() {
block->set_collision_mesh(collidable_surfaces, get_tree()->is_debugging_collisions_hint(), this);
}
block->set_parent_visible(is_visible());
block->set_parent_transform(local_to_world_transform);
}

shift_up(_reception_buffers.mesh_output, queue_index);
Expand Down

0 comments on commit 85bb3d7

Please sign in to comment.