blob: 577e855c15abc7836ee9874a54edebfa0b95b1b5 (
plain) (
tree)
|
|
/******************************************************************/
/* 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);
}
|