KiCad PCB EDA Suite
Loading...
Searching...
No Matches
bvh_packet_traversal.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright (C) 2015-2016 Mario Luzeiro <[email protected]>
5 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <https://www.gnu.org/licenses/>.
19 */
20
25
26#include "bvh_pbrt.h"
27
28
29#define BVH_RANGED_TRAVERSAL
30//#define BVH_PARTITION_TRAVERSAL
31
32
33#define MAX_TODOS 64
34
35
37{
38 int cell;
39 unsigned int ia; // Index to the first alive ray
40};
41
42
43static inline unsigned int getFirstHit( const RAYPACKET& aRayPacket, const BBOX_3D& aBBox,
44 unsigned int ia, HITINFO_PACKET* aHitInfoPacket )
45{
46 float hitT;
47
48 if( aBBox.Intersect( aRayPacket.m_ray[ia], &hitT )
49 && ( hitT < aHitInfoPacket[ia].m_HitInfo.m_tHit ) )
50 return ia;
51
52 if( !aRayPacket.m_Frustum.Intersect( aBBox ) )
54
55 for( unsigned int i = ia + 1; i < RAYPACKET_RAYS_PER_PACKET; ++i )
56 {
57 if( aBBox.Intersect( aRayPacket.m_ray[i], &hitT )
58 && ( hitT < aHitInfoPacket[i].m_HitInfo.m_tHit ) )
59 return i;
60 }
61
63}
64
65
66#ifdef BVH_RANGED_TRAVERSAL
67
68static inline unsigned int getLastHit( const RAYPACKET& aRayPacket, const BBOX_3D& aBBox,
69 unsigned int ia, HITINFO_PACKET* aHitInfoPacket )
70{
71 for( unsigned int ie = (RAYPACKET_RAYS_PER_PACKET - 1); ie > ia; --ie )
72 {
73 float hitT;
74
75 if( aBBox.Intersect( aRayPacket.m_ray[ie], &hitT )
76 && ( hitT < aHitInfoPacket[ie].m_HitInfo.m_tHit ) )
77 return ie + 1;
78 }
79
80 return ia + 1;
81}
82
83
84// "Large Ray Packets for Real-time Whitted Ray Tracing"
85// http://cseweb.ucsd.edu/~ravir/whitted.pdf
86
87// Ranged Traversal
88bool BVH_PBRT::Intersect( const RAYPACKET& aRayPacket, HITINFO_PACKET* aHitInfoPacket ) const
89{
90 if( m_nodes == nullptr )
91 return false;
92
93 if( &m_nodes[0] == nullptr )
94 return false;
95
96 bool anyHit = false;
97 int todoOffset = 0, nodeNum = 0;
98 StackNode todo[MAX_TODOS];
99
100 unsigned int ia = 0;
101
102 while( true )
103 {
104 const LinearBVHNode *curCell = &m_nodes[nodeNum];
105
106 ia = getFirstHit( aRayPacket, curCell->bounds, ia, aHitInfoPacket );
107
109 {
110 if( curCell->nPrimitives == 0 )
111 {
112 StackNode& node = todo[todoOffset++];
113 node.cell = curCell->secondChildOffset;
114 node.ia = ia;
115 nodeNum = nodeNum + 1;
116 continue;
117 }
118 else
119 {
120 const unsigned int ie = getLastHit( aRayPacket, curCell->bounds, ia,
121 aHitInfoPacket );
122
123 for( int j = 0; j < curCell->nPrimitives; ++j )
124 {
125 const OBJECT_3D* obj = m_primitives[curCell->primitivesOffset + j];
126
127 if( aRayPacket.m_Frustum.Intersect( obj->GetBBox() ) )
128 {
129 for( unsigned int i = ia; i < ie; ++i )
130 {
131 const bool hit = obj->Intersect( aRayPacket.m_ray[i],
132 aHitInfoPacket[i].m_HitInfo );
133
134 if( hit )
135 {
136 anyHit |= hit;
137 aHitInfoPacket[i].m_hitresult |= hit;
138 aHitInfoPacket[i].m_HitInfo.m_acc_node_info = nodeNum;
139 }
140 }
141 }
142 }
143 }
144 }
145
146 if( todoOffset == 0 )
147 break;
148
149 const StackNode& node = todo[--todoOffset];
150
151 nodeNum = node.cell;
152 ia = node.ia;
153 }
154
155 return anyHit;
156
157}
158#endif
159
160
161// "Ray Tracing Deformable Scenes Using Dynamic Bounding Volume Hierarchies"
162// http://www.cs.cmu.edu/afs/cs/academic/class/15869-f11/www/readings/wald07_packetbvh.pdf
163
164#ifdef BVH_PARTITION_TRAVERSAL
165
166static inline unsigned int getLastHit( const RAYPACKET& aRayPacket, const BBOX_3D& aBBox,
167 unsigned int ia, const unsigned int* aRayIndex,
168 HITINFO_PACKET* aHitInfoPacket )
169{
170 for( unsigned int ie = (RAYPACKET_RAYS_PER_PACKET - 1); ie > ia; --ie )
171 {
172 float hitT;
173
174 if( aBBox.Intersect( aRayPacket.m_ray[ aRayIndex[ie] ], &hitT )
175 && ( hitT < aHitInfoPacket[ aRayIndex[ie] ].m_HitInfo.m_tHit ) )
176 return ie + 1;
177 }
178
179 return ia + 1;
180}
181
182
183static inline unsigned int partRays( const RAYPACKET& aRayPacket, const BBOX_3D& aBBox,
184 unsigned int ia, unsigned int* aRayIndex,
185 HITINFO_PACKET* aHitInfoPacket )
186{
187
188 if( !aRayPacket.m_Frustum.Intersect( aBBox ) )
190
191 unsigned int ie = 0;
192
193 for( unsigned int i = 0; i < ia; ++i )
194 {
195 float hitT;
196
197 if( aBBox.Intersect( aRayPacket.m_ray[ aRayIndex[i] ], &hitT )
198 && ( hitT < aHitInfoPacket[ aRayIndex[i] ].m_HitInfo.m_tHit ) )
199 std::swap( aRayIndex[ie++], aRayIndex[i] );
200 }
201
202 return ie;
203}
204
205
206bool BVH_PBRT::Intersect( const RAYPACKET& aRayPacket, HITINFO_PACKET* aHitInfoPacket ) const
207{
208 bool anyHit = false;
209 int todoOffset = 0, nodeNum = 0;
210 StackNode todo[MAX_TODOS];
211
212 unsigned int I[RAYPACKET_RAYS_PER_PACKET];
213
214 memcpy( I, m_I, RAYPACKET_RAYS_PER_PACKET * sizeof( unsigned int ) );
215
216 unsigned int ia = 0;
217
218 while( true )
219 {
220 const LinearBVHNode *curCell = &m_nodes[nodeNum];
221
222 ia = partRays( aRayPacket, curCell->bounds, ia, I, aHitInfoPacket );
223
225 {
226 if( curCell->nPrimitives == 0 )
227 {
228 StackNode& node = todo[todoOffset++];
229 node.cell = curCell->secondChildOffset;
230 node.ia = ia;
231 nodeNum = nodeNum + 1;
232 continue;
233 }
234 else
235 {
236 unsigned int ie = getLastHit( aRayPacket, curCell->bounds, ia, I,
237 aHitInfoPacket );
238
239 for( int j = 0; j < curCell->nPrimitives; ++j )
240 {
241 const OBJECT_3D* obj = m_primitives[curCell->primitivesOffset + j];
242
243 if( aRayPacket.m_Frustum.Intersect( obj->GetBBox() ) )
244 {
245 for( unsigned int i = 0; i < ie; ++i )
246 {
247 unsigned int idx = I[i];
248
249 bool hit = obj->Intersect( aRayPacket.m_ray[idx],
250 aHitInfoPacket[idx].m_HitInfo );
251
252 if( hit )
253 {
254 anyHit |= hit;
255 aHitInfoPacket[idx].m_hitresult |= hit;
256 aHitInfoPacket[idx].m_HitInfo.m_acc_node_info = nodeNum;
257 }
258 }
259 }
260 }
261 }
262 }
263
264 if( todoOffset == 0 )
265 break;
266
267 const StackNode& node = todo[--todoOffset];
268
269 nodeNum = node.cell;
270 ia = node.ia;
271 }
272
273 return anyHit;
274}
275#endif
#define MAX_TODOS
static unsigned int getLastHit(const RAYPACKET &aRayPacket, const BBOX_3D &aBBox, unsigned int ia, HITINFO_PACKET *aHitInfoPacket)
static unsigned int getFirstHit(const RAYPACKET &aRayPacket, const BBOX_3D &aBBox, unsigned int ia, HITINFO_PACKET *aHitInfoPacket)
This BVH implementation is based on the source code implementation from the book "Physically Based Re...
LinearBVHNode * m_nodes
Definition bvh_pbrt.h:144
unsigned int m_I[RAYPACKET_RAYS_PER_PACKET]
Definition bvh_pbrt.h:149
std::vector< const OBJECT_3D * > m_primitives
Definition bvh_pbrt.h:143
bool Intersect(const RAY &aRay, HITINFO &aHitInfo) const override
virtual bool Intersect(const RAY &aRay, HITINFO &aHitInfo) const =0
const BBOX_3D & GetBBox() const
Definition object_3d.h:88
#define I(x, y, z)
Definition md5_hash.cpp:18
#define RAYPACKET_RAYS_PER_PACKET
Definition raypacket.h:31
Manage a bounding box defined by two SFVEC3F min max points.
Definition bbox_3d.h:39
bool Intersect(const RAY &aRay, float *t) const
bool Intersect(const BBOX_3D &aBBox) const
Intersect aBBox with this frustum.
Definition frustum.cpp:59
bool m_hitresult
Definition hitinfo.h:53
HITINFO m_HitInfo
Definition hitinfo.h:54
unsigned int m_acc_node_info
( 4) The acc stores here the node that it hits
Definition hitinfo.h:38
float m_tHit
( 4) distance
Definition hitinfo.h:34
int secondChildOffset
interior
Definition bvh_pbrt.h:87
BBOX_3D bounds
Definition bvh_pbrt.h:81
uint16_t nPrimitives
0 -> interior node
Definition bvh_pbrt.h:91
int primitivesOffset
leaf
Definition bvh_pbrt.h:86
RAY m_ray[RAYPACKET_RAYS_PER_PACKET]
Definition raypacket.h:50
FRUSTUM m_Frustum
Definition raypacket.h:49