/
sphere.cu
82 lines (72 loc) · 1.85 KB
/
sphere.cu
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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
#include <optix_world.h>
using namespace optix;
rtDeclareVariable(float4, sphere_coor, , );
rtDeclareVariable(float3, hit_pos, attribute hit_pos, );
rtDeclareVariable(optix::Ray, ray, rtCurrentRay, );
template <bool use_robust_method>
static __device__ void intersect_sphere(void)
{
float3 center = make_float3(sphere_coor);
float3 O = ray.origin - center;
float l = 1 / length(ray.direction);
float3 D = ray.direction * l;
float radius = sphere_coor.w;
float b = dot(O, D);
float c = dot(O, O) - radius * radius;
float disc = b * b - c;
if (disc > 0.0f)
{
float sdisc = sqrtf(disc);
float root1 = (-b - sdisc);
bool do_refine = false;
float root11 = 0.0f;
if (use_robust_method && fabsf(root1) > 10.f * radius)
do_refine = true;
if (do_refine)
{
// refine root1
float3 O1 = O + root1 * D;
b = dot(O1, D);
c = dot(O1, O1) - radius * radius;
disc = b * b - c;
if (disc > 0.0f)
{
sdisc = sqrtf(disc);
root11 = (-b - sdisc);
}
}
bool check_second = true;
if (rtPotentialIntersection((root1 + root11) * l))
{
hit_pos = center;
if (rtReportIntersection(0)) //? why rtReportIntersection can fail?
check_second = false;
}
if (check_second)
{
float root2 = (-b + sdisc) + (do_refine ? root1 : 0);
if (rtPotentialIntersection(root2 * l))
{
hit_pos = center;
rtReportIntersection(0);
}
}
}
}
RT_PROGRAM void intersect(int primIdx)
{
intersect_sphere<true>();
}
RT_PROGRAM void bounds(int, float result[6])
{
const float3 cen = make_float3(sphere_coor);
const float3 rad = make_float3(sphere_coor.w);
optix::Aabb *aabb = (optix::Aabb *)result;
if (rad.x > 0.0f && !isinf(rad.x))
{
aabb->m_min = cen - rad;
aabb->m_max = cen + rad;
}
else
aabb->invalidate();
}