diff options
Diffstat (limited to 'source/blender/draw/intern/shaders/common_math_geom_lib.glsl')
-rw-r--r-- | source/blender/draw/intern/shaders/common_math_geom_lib.glsl | 144 |
1 files changed, 105 insertions, 39 deletions
diff --git a/source/blender/draw/intern/shaders/common_math_geom_lib.glsl b/source/blender/draw/intern/shaders/common_math_geom_lib.glsl index 6d4452c18c8..71460c39285 100644 --- a/source/blender/draw/intern/shaders/common_math_geom_lib.glsl +++ b/source/blender/draw/intern/shaders/common_math_geom_lib.glsl @@ -5,63 +5,88 @@ /** \name Math intersection & projection functions. * \{ */ -float point_plane_projection_dist(vec3 lineorigin, vec3 planeorigin, vec3 planenormal) +vec4 plane_from_quad(vec3 v0, vec3 v1, vec3 v2, vec3 v3) { - return dot(planenormal, planeorigin - lineorigin); + vec3 nor = normalize(cross(v2 - v1, v0 - v1) + cross(v0 - v3, v2 - v3)); + return vec4(nor, -dot(nor, v2)); } -float line_plane_intersect_dist(vec3 lineorigin, - vec3 linedirection, - vec3 planeorigin, - vec3 planenormal) +vec4 plane_from_tri(vec3 v0, vec3 v1, vec3 v2) { - return dot(planenormal, planeorigin - lineorigin) / dot(planenormal, linedirection); + vec3 nor = normalize(cross(v2 - v1, v0 - v1)); + return vec4(nor, -dot(nor, v2)); } -float line_plane_intersect_dist(vec3 lineorigin, vec3 linedirection, vec4 plane) +float point_plane_projection_dist(vec3 line_origin, vec3 plane_origin, vec3 plane_normal) +{ + return dot(plane_normal, plane_origin - line_origin); +} + +float point_line_projection_dist(vec2 point, vec2 line_origin, vec2 line_normal) +{ + return dot(line_normal, line_origin - point); +} + +float line_plane_intersect_dist(vec3 line_origin, + vec3 line_direction, + vec3 plane_origin, + vec3 plane_normal) +{ + return dot(plane_normal, plane_origin - line_origin) / dot(plane_normal, line_direction); +} + +float line_plane_intersect_dist(vec3 line_origin, vec3 line_direction, vec4 plane) { vec3 plane_co = plane.xyz * (-plane.w / len_squared(plane.xyz)); - vec3 h = lineorigin - plane_co; - return -dot(plane.xyz, h) / dot(plane.xyz, linedirection); + vec3 h = line_origin - plane_co; + return -dot(plane.xyz, h) / dot(plane.xyz, line_direction); } -vec3 line_plane_intersect(vec3 lineorigin, vec3 linedirection, vec3 planeorigin, vec3 planenormal) +vec3 line_plane_intersect(vec3 line_origin, + vec3 line_direction, + vec3 plane_origin, + vec3 plane_normal) { - float dist = line_plane_intersect_dist(lineorigin, linedirection, planeorigin, planenormal); - return lineorigin + linedirection * dist; + float dist = line_plane_intersect_dist(line_origin, line_direction, plane_origin, plane_normal); + return line_origin + line_direction * dist; } -vec3 line_plane_intersect(vec3 lineorigin, vec3 linedirection, vec4 plane) +vec3 line_plane_intersect(vec3 line_origin, vec3 line_direction, vec4 plane) { - float dist = line_plane_intersect_dist(lineorigin, linedirection, plane); - return lineorigin + linedirection * dist; + float dist = line_plane_intersect_dist(line_origin, line_direction, plane); + return line_origin + line_direction * dist; } -float line_aligned_plane_intersect_dist(vec3 lineorigin, vec3 linedirection, vec3 planeorigin) +float line_aligned_plane_intersect_dist(vec3 line_origin, vec3 line_direction, vec3 plane_origin) { /* aligned plane normal */ - vec3 L = planeorigin - lineorigin; - float diskdist = length(L); - vec3 planenormal = -normalize(L); - return -diskdist / dot(planenormal, linedirection); + vec3 L = plane_origin - line_origin; + float disk_dist = length(L); + vec3 plane_normal = -normalize(L); + return -disk_dist / dot(plane_normal, line_direction); } -vec3 line_aligned_plane_intersect(vec3 lineorigin, vec3 linedirection, vec3 planeorigin) +vec3 line_aligned_plane_intersect(vec3 line_origin, vec3 line_direction, vec3 plane_origin) { - float dist = line_aligned_plane_intersect_dist(lineorigin, linedirection, planeorigin); + float dist = line_aligned_plane_intersect_dist(line_origin, line_direction, plane_origin); if (dist < 0) { /* if intersection is behind we fake the intersection to be * really far and (hopefully) not inside the radius of interest */ dist = 1e16; } - return lineorigin + linedirection * dist; + return line_origin + line_direction * dist; } -float line_unit_sphere_intersect_dist(vec3 lineorigin, vec3 linedirection) +/** + * Returns intersection distance between the unit sphere and the line + * with the assumption that \a line_origin is contained in the unit sphere. + * It will always returns the farthest intersection. + */ +float line_unit_sphere_intersect_dist(vec3 line_origin, vec3 line_direction) { - float a = dot(linedirection, linedirection); - float b = dot(linedirection, lineorigin); - float c = dot(lineorigin, lineorigin) - 1; + float a = dot(line_direction, line_direction); + float b = dot(line_direction, line_origin); + float c = dot(line_origin, line_origin) - 1; float dist = 1e15; float determinant = b * b - a * c; @@ -72,22 +97,63 @@ float line_unit_sphere_intersect_dist(vec3 lineorigin, vec3 linedirection) return dist; } -float line_unit_box_intersect_dist(vec3 lineorigin, vec3 linedirection) +/** + * Returns minimum intersection distance between the unit box and the line + * with the assumption that \a line_origin is contained in the unit box. + * In other words, it will always returns the farthest intersection. + */ +float line_unit_box_intersect_dist(vec3 line_origin, vec3 line_direction) { /* https://seblagarde.wordpress.com/2012/09/29/image-based-lighting-approaches-and-parallax-corrected-cubemap/ */ - vec3 firstplane = (vec3(1.0) - lineorigin) / linedirection; - vec3 secondplane = (vec3(-1.0) - lineorigin) / linedirection; - vec3 furthestplane = max(firstplane, secondplane); + vec3 first_plane = (vec3(1.0) - line_origin) / line_direction; + vec3 second_plane = (vec3(-1.0) - line_origin) / line_direction; + vec3 farthest_plane = max(first_plane, second_plane); + + return min_v3(farthest_plane); +} + +float line_unit_box_intersect_dist_safe(vec3 line_origin, vec3 line_direction) +{ + vec3 safe_line_direction = max(vec3(1e-8), abs(line_direction)) * + select(vec3(1.0), -vec3(1.0), lessThan(line_direction, vec3(0.0))); + return line_unit_box_intersect_dist(line_origin, safe_line_direction); +} + +/** + * Same as line_unit_box_intersect_dist but for 2D case. + */ +float line_unit_square_intersect_dist(vec2 line_origin, vec2 line_direction) +{ + vec2 first_plane = (vec2(1.0) - line_origin) / line_direction; + vec2 second_plane = (vec2(-1.0) - line_origin) / line_direction; + vec2 farthest_plane = max(first_plane, second_plane); - return min_v3(furthestplane); + return min_v2(farthest_plane); } -float line_unit_box_intersect_dist_safe(vec3 lineorigin, vec3 linedirection) +float line_unit_square_intersect_dist_safe(vec2 line_origin, vec2 line_direction) { - vec3 safe_linedirection = max(vec3(1e-8), abs(linedirection)) * - select(vec3(1.0), -vec3(1.0), lessThan(linedirection, vec3(0.0))); - return line_unit_box_intersect_dist(lineorigin, safe_linedirection); + vec2 safe_line_direction = max(vec2(1e-8), abs(line_direction)) * + select(vec2(1.0), -vec2(1.0), lessThan(line_direction, vec2(0.0))); + return line_unit_square_intersect_dist(line_origin, safe_line_direction); +} + +/** + * Returns clipping distance (intersection with the nearest plane) with the given axis-aligned + * bound box along \a line_direction. + * Safe even if \a line_direction is degenerate. + * It assumes that an intersection exists (i.e: that \a line_direction points towards the AABB). + */ +float line_aabb_clipping_dist(vec3 line_origin, vec3 line_direction, vec3 aabb_min, vec3 aabb_max) +{ + vec3 safe_dir = select(line_direction, vec3(1e-5), lessThan(abs(line_direction), vec3(1e-5))); + vec3 dir_inv = 1.0 / safe_dir; + + vec3 first_plane = (aabb_min - line_origin) * dir_inv; + vec3 second_plane = (aabb_max - line_origin) * dir_inv; + vec3 nearest_plane = min(first_plane, second_plane); + return max_v3(nearest_plane); } /** \} */ @@ -98,8 +164,8 @@ float line_unit_box_intersect_dist_safe(vec3 lineorigin, vec3 linedirection) void make_orthonormal_basis(vec3 N, out vec3 T, out vec3 B) { - vec3 UpVector = abs(N.z) < 0.99999 ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0); - T = normalize(cross(UpVector, N)); + vec3 up_vector = abs(N.z) < 0.99999 ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0); + T = normalize(cross(up_vector, N)); B = cross(N, T); } |