Allow to use collision mask when raycasting blocky voxels
parent
47a6426a12
commit
1c6404efa5
|
@ -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");
|
||||
|
|
|
@ -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)); }
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
Loading…
Reference in New Issue