diff options
author | 53hornet <53hornet@gmail.com> | 2019-02-02 23:33:15 -0500 |
---|---|---|
committer | 53hornet <53hornet@gmail.com> | 2019-02-02 23:33:15 -0500 |
commit | db072ad4dc181eca5a1458656b130beb43f475bf (patch) | |
tree | a3c03c7f5497cb70503e2486662fa85cfb53415a /hw6/src/boundedVolumeNode.cpp | |
download | csci427-master.tar.xz csci427-master.zip |
Diffstat (limited to 'hw6/src/boundedVolumeNode.cpp')
-rw-r--r-- | hw6/src/boundedVolumeNode.cpp | 97 |
1 files changed, 97 insertions, 0 deletions
diff --git a/hw6/src/boundedVolumeNode.cpp b/hw6/src/boundedVolumeNode.cpp new file mode 100644 index 0000000..fc790b5 --- /dev/null +++ b/hw6/src/boundedVolumeNode.cpp @@ -0,0 +1,97 @@ +/******************************************************************/ +/* 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); +} + + +float boundedVolumeNode::area(void) const +{ + float total_area = 0.0f; + if(_left) total_area += _left->area(); + if(_right) total_area += _right->area(); + return total_area; +} + + +surfaceSample boundedVolumeNode::sample(float r1, float r2) const +{ + if(_left && !_right) return _left->sample(r1, r2); + else if(_right && !_left) return _right->sample(r1, r2); + else + { + float area_left = _left->area(); + float area_right = _right->area(); + float prob_left = area_left / (area_left + area_right); + float prob_right = 1.0f - prob_left; + + if(r1 <= prob_left) + return _left->sample(r1 / prob_left, r2) * prob_left; + else + return _right->sample((r1 - prob_left) / prob_right, r2) * prob_right; + } +} |