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
|
/******************************************************************/
/* This file is part of the homework assignments for CSCI-427/527 */
/* at The College of William & Mary and authored by Pieter Peers. */
/* No part of this file, whether altered or in original form, can */
/* be distributed or used outside the context of CSCI-427/527 */
/* without consent of either the College of William & Mary or */
/* Pieter Peers. */
/******************************************************************/
#include <cassert>
#include <algorithm>
#include "boundedVolumeNode.h"
#include "random_number.h"
boundedVolumeNode::boundedVolumeNode(const std::vector<std::shared_ptr<const boundedPrimitive>>::iterator& start, const std::vector<std::shared_ptr<const boundedPrimitive>>::iterator& end)
: _left(nullptr), _right(nullptr), boundedPrimitive()
{
assert(std::distance(start, end) > 1);
// compute the bounding box
for_each(start, end, [&](const std::shared_ptr<const boundedPrimitive>& prim)
{
_bb += prim->boundingbox();
});
// select random splitting dimension & pivot
unsigned int split = random_int(2);
float pivot = _bb.center()[split];
// partition
auto middle = std::partition(start, end, [&](const std::shared_ptr<const boundedPrimitive>& prim)
{
return prim->boundingbox().center()[split] < pivot;
});
// special case: all centers are the same.
if(start == middle) middle++;
// create _left (recurse if more than one primitive)
if(std::distance(start, middle) == 1)
_left = *start;
else
_left = std::shared_ptr<const boundedPrimitive>(new boundedVolumeNode(start, middle));
// create _right (recurse if more than one primitive)
if(std::distance(middle, end) == 1)
_right = *middle;
else
_right = std::shared_ptr<const boundedPrimitive>(new boundedVolumeNode(middle, end));
// Done.
}
intersectionPoint boundedVolumeNode::intersect(const ray& r) const
{
intersectionPoint leftIp, rightIp;
// check left child
if(_left && _left->hitBoundingBox(r))
leftIp = _left->intersect(r);
// check right child
if(_right && _right->hitBoundingBox(r))
rightIp = _right->intersect(r);
// return closest
return std::min(leftIp, rightIp);
}
|