ccl_device void barycentric const float3 tri_a const float3 tri_b cons

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
ccl_device void barycentric(const float3 tri_a, const float3 tri_b, const float3 tri_c, const float3 p, float &u, float &v)
{
const float3 v0 = tri_a - tri_c, v1 = tri_b - tri_c, v2 = p - tri_c;
const float d00 = dot(v0, v0);
const float d01 = dot(v0, v1);
const float d11 = dot(v1, v1);
const float d20 = dot(v2, v0);
const float d21 = dot(v2, v1);
const float denom = d00 * d11 - d01 * d01;
u = (d11 * d20 - d01 * d21) / denom;
v = (d00 * d21 - d01 * d20) / denom;
}
ccl_device float3 prism_point_uvw_coords(const float3 tri_a, const float3 tri_b, const float3 tri_c,
const float3 tri_n_a, const float3 tri_n_b, const float3 tri_n_c,
const float3 point, const float EPS) {
float w = 0;
float left = 0;
float right = 1.0;
float3 T_a, T_b, T_c, n;
// usually 12 iterations are enough
float d = 0.0f;
for (int i = 0; i < 40; ++i) {
w = 0.5f * (left + right);
T_a = tri_a + w * tri_n_a;
T_b = tri_b + w * tri_n_b;
T_c = tri_c + w * tri_n_c;
n = normalize(cross(T_c - T_b, T_a - T_c));
float A = n.x;
float B = n.y;
float C = n.z;
float D = -dot(T_c, n);
d = A * point.x + B * point.y + C * point.z + D;
if ((signf(d) * d) < EPS) {
break;
}
float sign = signf(dot(n, point - T_a));
if (sign == 0) {
break;
}
if (sign > 0) {
left = w;
} else {
right = w;
}
}
if (signf(d)*d > 0.01f) {
printf("%f %f %f dist %f\n", (double)point.x, (double)point.y, (double)point.z, (double)d);
}
float3 v0 = point - T_c;
float3 proj = point - dot(n, v0) * n;
float u, v;
barycentric(T_a, T_b, T_c, proj, u, v);
return {u, v , w};
}