diff --git a/CHANGELOG.md b/CHANGELOG.md index 334df3a5727..e1f513b6e5e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ - Show DataInspector tooltip on NaN values if `nan_color` has been set to other than `:transparent` [#4310](https://github.com/MakieOrg/Makie.jl/pull/4310) - Fix `linestyle` not being used in `triplot` [#4332](https://github.com/MakieOrg/Makie.jl/pull/4332) +- Fix voxel clipping not being based on voxel centers [#4397](https://github.com/MakieOrg/Makie.jl/pull/4397) ## [0.21.11] - 2024-09-13 diff --git a/CairoMakie/src/primitives.jl b/CairoMakie/src/primitives.jl index f25a58f0213..4048a346b67 100644 --- a/CairoMakie/src/primitives.jl +++ b/CairoMakie/src/primitives.jl @@ -1253,7 +1253,14 @@ function draw_atomic(scene::Scene, screen::Screen, @nospecialize(primitive::Maki pos = Makie.voxel_positions(primitive) scale = Makie.voxel_size(primitive) colors = Makie.voxel_colors(primitive) - marker = normal_mesh(Rect3f(Point3f(-0.5), Vec3f(1))) + marker = GeometryBasics.normal_mesh(Rect3f(Point3f(-0.5), Vec3f(1))) + + # Face culling + if !isempty(primitive.clip_planes[]) && Makie.is_data_space(primitive.space[]) + valid = [is_visible(primitive.clip_planes[], p) for p in pos] + pos = pos[valid] + colors = colors[valid] + end # For correct z-ordering we need to be in view/camera or screen space model = copy(primitive.model[]) @@ -1271,7 +1278,7 @@ function draw_atomic(scene::Scene, screen::Screen, @nospecialize(primitive::Maki specular = primitive.specular, shininess = primitive.shininess, faceculling = get(primitive, :faceculling, -10), transformation = Makie.transformation(primitive), - clip_planes = primitive.clip_planes + clip_planes = Plane3f[] ) for i in zorder diff --git a/GLMakie/assets/shader/voxel.frag b/GLMakie/assets/shader/voxel.frag index 71f11e2c356..c9c6873210e 100644 --- a/GLMakie/assets/shader/voxel.frag +++ b/GLMakie/assets/shader/voxel.frag @@ -85,18 +85,16 @@ vec4 get_color(sampler2D color, Nothing color_map, int id) { bool is_clipped() { - float d1, d2; + float d; + // Center of voxel ivec3 size = ivec3(textureSize(voxel_id, 0).xyz); - vec3 xyz = vec3(ivec3(o_uvw * size)); + vec3 xyz = vec3(ivec3(o_uvw * size)) + vec3(0.5); for (int i = 0; i < _num_clip_planes; i++) { - // distance from clip planes with negative clipped - d1 = dot(xyz, clip_planes[i].xyz) - clip_planes[i].w; - d2 = dot(xyz, clip_planes[i].xyz) - clip_planes[i].w; + // distance between clip plane and center + d = dot(xyz, clip_planes[i].xyz) - clip_planes[i].w; - // both outside - clip everything - if (d1 < 0.0 || d2 < 0.0) { + if (d < 0.0) return true; - } } return false; diff --git a/ReferenceTests/src/tests/examples3d.jl b/ReferenceTests/src/tests/examples3d.jl index 494f2fe95f5..949ce6932bf 100644 --- a/ReferenceTests/src/tests/examples3d.jl +++ b/ReferenceTests/src/tests/examples3d.jl @@ -682,7 +682,7 @@ end @reference_test "Clip planes - voxel" begin f = Figure() a = LScene(f[1, 1]) - a.scene.theme[:clip_planes][] = [Plane3f(Vec3f(-2, -1, -0.5), 0.0), Plane3f(Vec3f(-0.5, -1, -2), 0.0)] + a.scene.theme[:clip_planes][] = [Plane3f(Vec3f(-2, -1, -0.5), 0.1), Plane3f(Vec3f(-0.5, -1, -2), 0.1)] r = -10:10 p = voxels!(a, [cos(sin(x+y)+z) for x in r, y in r, z in r]) f diff --git a/WGLMakie/assets/voxel.frag b/WGLMakie/assets/voxel.frag index 3fe7a6dfeee..4e095306341 100644 --- a/WGLMakie/assets/voxel.frag +++ b/WGLMakie/assets/voxel.frag @@ -85,18 +85,15 @@ vec3 blinnphong(vec3 N, vec3 V, vec3 L, vec3 color){ bool is_clipped() { - float d1, d2; + float d; + // get center pos of this voxel vec3 size = vec3(textureSize(voxel_id, 0).xyz); - vec3 xyz = vec3(ivec3(o_uvw * size)); + vec3 xyz = vec3(ivec3(o_uvw * size)) + vec3(0.5); for (int i = 0; i < num_clip_planes; i++) { - // distance from clip planes with negative clipped - d1 = dot(xyz, clip_planes[i].xyz) - clip_planes[i].w; - d2 = dot(xyz, clip_planes[i].xyz) - clip_planes[i].w; - - // both outside - clip everything - if (d1 < 0.0 || d2 < 0.0) { + // distance between clip plane and voxel center + d = dot(xyz, clip_planes[i].xyz) - clip_planes[i].w; + if (d < 0.0) return true; - } } return false;