Allow to use collision mask when raycasting blocky voxels

master
Marc Gilleron 2020-08-06 19:58:36 +01:00
parent 47a6426a12
commit 1c6404efa5
4 changed files with 26 additions and 14 deletions

View File

@ -54,7 +54,7 @@ VoxelTool::Mode VoxelTool::get_mode() const {
return _mode;
}
Ref<VoxelRaycastResult> VoxelTool::raycast(Vector3 pos, Vector3 dir, float max_distance) {
Ref<VoxelRaycastResult> VoxelTool::raycast(Vector3 pos, Vector3 dir, float max_distance, uint32_t collision_mask) {
ERR_PRINT("Not implemented");
return Ref<VoxelRaycastResult>();
}
@ -226,7 +226,8 @@ void VoxelTool::_bind_methods() {
ClassDB::bind_method(D_METHOD("paste", "dst_pos", "src_buffer", "src_mask_value"), &VoxelTool::_b_paste);
ClassDB::bind_method(D_METHOD("raycast", "origin", "direction", "max_distance"), &VoxelTool::_b_raycast, DEFVAL(10.0));
ClassDB::bind_method(D_METHOD("raycast", "origin", "direction", "max_distance", "collision_mask"),
&VoxelTool::_b_raycast, DEFVAL(10.0), DEFVAL(0xffffffff));
ADD_PROPERTY(PropertyInfo(Variant::INT, "value"), "set_value", "get_value");
ADD_PROPERTY(PropertyInfo(Variant::INT, "channel", PROPERTY_HINT_ENUM, VoxelBuffer::CHANNEL_ID_HINT_STRING), "set_channel", "get_channel");

View File

@ -59,7 +59,7 @@ public:
virtual void paste(Vector3i pos, Ref<VoxelBuffer> p_voxels, uint64_t mask_value);
virtual Ref<VoxelRaycastResult> raycast(Vector3 pos, Vector3 dir, float max_distance);
virtual Ref<VoxelRaycastResult> raycast(Vector3 pos, Vector3 dir, float max_distance, uint32_t collision_mask);
// Checks if an edit affecting the given box can be applied, fully or partially
virtual bool is_area_editable(const Rect3i &box) const;
@ -81,7 +81,9 @@ private:
float _b_get_voxel_f(Vector3 pos) { return get_voxel_f(Vector3i(pos)); }
void _b_set_voxel(Vector3 pos, uint64_t v) { set_voxel(Vector3i(pos), v); }
void _b_set_voxel_f(Vector3 pos, float v) { set_voxel_f(Vector3i(pos), v); }
Ref<VoxelRaycastResult> _b_raycast(Vector3 pos, Vector3 dir, float max_distance) { return raycast(pos, dir, max_distance); }
Ref<VoxelRaycastResult> _b_raycast(Vector3 pos, Vector3 dir, float max_distance, uint32_t collision_mask) {
return raycast(pos, dir, max_distance, collision_mask);
}
void _b_do_point(Vector3 pos) { do_point(Vector3i(pos)); }
void _b_do_line(Vector3i begin, Vector3i end) { do_line(Vector3i(begin), Vector3i(end)); }
void _b_do_circle(Vector3 pos, float radius, Vector3 direction) { do_circle(Vector3i(pos), radius, Vector3i(direction)); }

View File

@ -19,11 +19,12 @@ bool VoxelToolTerrain::is_area_editable(const Rect3i &box) const {
return _map->is_area_fully_loaded(box.padded(1));
}
Ref<VoxelRaycastResult> VoxelToolTerrain::raycast(Vector3 pos, Vector3 dir, float max_distance) {
Ref<VoxelRaycastResult> VoxelToolTerrain::raycast(Vector3 pos, Vector3 dir, float max_distance, uint32_t collision_mask) {
// TODO Transform input if the terrain is rotated (in the future it can be made a Spatial node)
struct RaycastPredicate {
const VoxelTerrain &terrain;
const uint32_t collision_mask;
bool operator()(Vector3i pos) {
//unsigned int channel = context->channel;
@ -32,22 +33,31 @@ Ref<VoxelRaycastResult> VoxelToolTerrain::raycast(Vector3 pos, Vector3 dir, floa
int v0 = map->get_voxel(pos, VoxelBuffer::CHANNEL_TYPE);
Ref<VoxelLibrary> lib_ref = terrain.get_voxel_library();
if (lib_ref.is_null())
if (lib_ref.is_null()) {
return false;
}
const VoxelLibrary &lib = **lib_ref;
if (lib.has_voxel(v0) == false)
if (lib.has_voxel(v0) == false) {
return false;
}
const Voxel &voxel = lib.get_voxel_const(v0);
if (voxel.get_geometry_type() == voxel.GEOMETRY_NONE)
if (voxel.is_empty()) {
return false;
}
if (voxel.is_transparent() == false)
return true;
if ((voxel.get_collision_mask() & collision_mask) == 0) {
return false;
}
if (voxel.is_transparent() && voxel.get_collision_aabbs().empty() == false)
if (voxel.is_transparent() == false) {
return true;
}
if (voxel.is_transparent() && voxel.get_collision_aabbs().empty() == false) {
return true;
}
float v1 = map->get_voxel_f(pos, VoxelBuffer::CHANNEL_SDF);
return v1 < 0;
@ -58,9 +68,8 @@ Ref<VoxelRaycastResult> VoxelToolTerrain::raycast(Vector3 pos, Vector3 dir, floa
Vector3i prev_pos;
Ref<VoxelRaycastResult> res;
RaycastPredicate predicate = { *_terrain };
RaycastPredicate predicate = { *_terrain, collision_mask };
if (voxel_raycast(pos, dir, predicate, max_distance, hit_pos, prev_pos)) {
res.instance();
res->position = hit_pos;
res->previous_position = prev_pos;

View File

@ -14,7 +14,7 @@ public:
VoxelToolTerrain(VoxelTerrain *terrain, Ref<VoxelMap> map);
bool is_area_editable(const Rect3i &box) const override;
Ref<VoxelRaycastResult> raycast(Vector3 pos, Vector3 dir, float max_distance) override;
Ref<VoxelRaycastResult> raycast(Vector3 pos, Vector3 dir, float max_distance, uint32_t collision_mask) override;
void run_blocky_random_tick(AABB voxel_area, int voxel_count, Ref<FuncRef> callback, int block_batch_count) const;