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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
|
implementing fcpw;
__include ray;
__include interaction;
__include bounding_volumes;
__include transform;
public interface IBranchTraversalWeight
{
// computes the traversal weight for a given squared distance
float compute(float r2);
};
public struct ConstantBranchTraversalWeight : IBranchTraversalWeight
{
// computes the traversal weight for a given squared distance
public float compute(float r2)
{
return 1.0;
}
};
public interface IAggregate
{
// updates the bounding volume of an aggregate node
[mutating]
void refit(uint nodeIndex);
// intersects aggregate geometry with ray
bool intersect(inout Ray r, bool checkForOcclusion, inout Interaction i);
// intersects aggregate geometry with sphere
bool intersect<T : IBranchTraversalWeight>(BoundingSphere s, float3 randNums,
T branchTraversalWeight,
inout Interaction i);
// finds closest point on aggregate geometry from sphere center
bool findClosestPoint(inout BoundingSphere s, inout Interaction i,
bool recordNormal = false);
// finds closest silhouette point on aggregate geometry from sphere center
bool findClosestSilhouettePoint(inout BoundingSphere s, bool flipNormalOrientation,
float squaredMinRadius, float precision,
inout Interaction i);
};
public struct TransformedAggregate<A : IAggregate> : IAggregate
{
public A aggregate;
public float3x4 t;
public float3x4 tInv;
// updates the bounding volume of an aggregate node
// NOTE: refitting of transformed aggregates is currently quite inefficient, since the
// shared aggregate is refit every time this function is called
[mutating]
public void refit(uint nodeIndex)
{
aggregate.refit(nodeIndex);
}
// intersects aggregate geometry with ray
public bool intersect(inout Ray r, bool checkForOcclusion, inout Interaction i)
{
// apply inverse transform to ray
Ray rInv = transformRay(tInv, r);
// intersect
bool didIntersect = aggregate.intersect(rInv, checkForOcclusion, i);
// apply transform to ray and interaction
r.tMax = transformRay(t, rInv).tMax;
if (didIntersect)
{
transformInteraction(t, tInv, r.o, true, i);
return true;
}
return false;
}
// intersects aggregate geometry with sphere
public bool intersect<T : IBranchTraversalWeight>(BoundingSphere s, float3 randNums,
T branchTraversalWeight,
inout Interaction i)
{
// apply inverse transform to sphere
BoundingSphere sInv = transformSphere(tInv, s);
// intersect
bool didIntersect = aggregate.intersect(sInv, randNums, branchTraversalWeight, i);
// apply transform to interaction
if (didIntersect)
{
transformInteraction(t, tInv, s.c, false, i);
return true;
}
return false;
}
// finds closest point on aggregate geometry from sphere center
public bool findClosestPoint(inout BoundingSphere s, inout Interaction i,
bool recordNormal = false)
{
// apply inverse transform to sphere
BoundingSphere sInv = transformSphere(tInv, s);
// find closest point
bool didFindClosestPoint = aggregate.findClosestPoint(sInv, i, recordNormal);
// apply transform to sphere and interaction
s.r2 = transformSphere(t, sInv).r2;
if (didFindClosestPoint)
{
transformInteraction(t, tInv, s.c, true, i);
return true;
}
return false;
}
// finds closest silhouette point on aggregate geometry from sphere center
public bool findClosestSilhouettePoint(inout BoundingSphere s, bool flipNormalOrientation,
float squaredMinRadius, float precision,
inout Interaction i)
{
// apply inverse transform to sphere
BoundingSphere sInv = transformSphere(tInv, s);
BoundingSphere sMin = BoundingSphere(s.c, squaredMinRadius);
BoundingSphere sMinInv = transformSphere(tInv, sMin);
// find closest silhouette point
bool didFindClosestSilhouettePoint = aggregate.findClosestSilhouettePoint(
sInv, flipNormalOrientation, sMinInv.r2, precision, i);
// apply transform to sphere and interaction
s.r2 = transformSphere(t, sInv).r2;
if (didFindClosestSilhouettePoint)
{
transformInteraction(t, tInv, s.c, true, i);
return true;
}
return false;
}
};
|