1
2#pragma BLENDER_REQUIRE(common_math_lib.glsl)
3
4/* ---------------------------------------------------------------------- */
5/** \name Math intersection & projection functions.
6 * \{ */
7
8float point_plane_projection_dist(vec3 lineorigin, vec3 planeorigin, vec3 planenormal)
9{
10  return dot(planenormal, planeorigin - lineorigin);
11}
12
13float line_plane_intersect_dist(vec3 lineorigin,
14                                vec3 linedirection,
15                                vec3 planeorigin,
16                                vec3 planenormal)
17{
18  return dot(planenormal, planeorigin - lineorigin) / dot(planenormal, linedirection);
19}
20
21float line_plane_intersect_dist(vec3 lineorigin, vec3 linedirection, vec4 plane)
22{
23  vec3 plane_co = plane.xyz * (-plane.w / len_squared(plane.xyz));
24  vec3 h = lineorigin - plane_co;
25  return -dot(plane.xyz, h) / dot(plane.xyz, linedirection);
26}
27
28vec3 line_plane_intersect(vec3 lineorigin, vec3 linedirection, vec3 planeorigin, vec3 planenormal)
29{
30  float dist = line_plane_intersect_dist(lineorigin, linedirection, planeorigin, planenormal);
31  return lineorigin + linedirection * dist;
32}
33
34vec3 line_plane_intersect(vec3 lineorigin, vec3 linedirection, vec4 plane)
35{
36  float dist = line_plane_intersect_dist(lineorigin, linedirection, plane);
37  return lineorigin + linedirection * dist;
38}
39
40float line_aligned_plane_intersect_dist(vec3 lineorigin, vec3 linedirection, vec3 planeorigin)
41{
42  /* aligned plane normal */
43  vec3 L = planeorigin - lineorigin;
44  float diskdist = length(L);
45  vec3 planenormal = -normalize(L);
46  return -diskdist / dot(planenormal, linedirection);
47}
48
49vec3 line_aligned_plane_intersect(vec3 lineorigin, vec3 linedirection, vec3 planeorigin)
50{
51  float dist = line_aligned_plane_intersect_dist(lineorigin, linedirection, planeorigin);
52  if (dist < 0) {
53    /* if intersection is behind we fake the intersection to be
54     * really far and (hopefully) not inside the radius of interest */
55    dist = 1e16;
56  }
57  return lineorigin + linedirection * dist;
58}
59
60float line_unit_sphere_intersect_dist(vec3 lineorigin, vec3 linedirection)
61{
62  float a = dot(linedirection, linedirection);
63  float b = dot(linedirection, lineorigin);
64  float c = dot(lineorigin, lineorigin) - 1;
65
66  float dist = 1e15;
67  float determinant = b * b - a * c;
68  if (determinant >= 0) {
69    dist = (sqrt(determinant) - b) / a;
70  }
71
72  return dist;
73}
74
75float line_unit_box_intersect_dist(vec3 lineorigin, vec3 linedirection)
76{
77  /* https://seblagarde.wordpress.com/2012/09/29/image-based-lighting-approaches-and-parallax-corrected-cubemap/
78   */
79  vec3 firstplane = (vec3(1.0) - lineorigin) / linedirection;
80  vec3 secondplane = (vec3(-1.0) - lineorigin) / linedirection;
81  vec3 furthestplane = max(firstplane, secondplane);
82
83  return min_v3(furthestplane);
84}
85
86/** \} */
87
88/* ---------------------------------------------------------------------- */
89/** \name Other useful functions.
90 * \{ */
91
92void make_orthonormal_basis(vec3 N, out vec3 T, out vec3 B)
93{
94  vec3 UpVector = abs(N.z) < 0.99999 ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0);
95  T = normalize(cross(UpVector, N));
96  B = cross(N, T);
97}
98
99/* ---- Encode / Decode Normal buffer data ---- */
100/* From http://aras-p.info/texts/CompactNormalStorage.html
101 * Using Method #4: Spheremap Transform */
102vec2 normal_encode(vec3 n, vec3 view)
103{
104  float p = sqrt(n.z * 8.0 + 8.0);
105  return n.xy / p + 0.5;
106}
107
108vec3 normal_decode(vec2 enc, vec3 view)
109{
110  vec2 fenc = enc * 4.0 - 2.0;
111  float f = dot(fenc, fenc);
112  float g = sqrt(1.0 - f / 4.0);
113  vec3 n;
114  n.xy = fenc * g;
115  n.z = 1 - f / 2;
116  return n;
117}
118
119/** \} */
120