summaryrefslogtreecommitdiff
path: root/hw4/src/boundedVolumeNode.cpp
diff options
context:
space:
mode:
author53hornet <53hornet@gmail.com>2019-02-02 23:33:15 -0500
committer53hornet <53hornet@gmail.com>2019-02-02 23:33:15 -0500
commitdb072ad4dc181eca5a1458656b130beb43f475bf (patch)
treea3c03c7f5497cb70503e2486662fa85cfb53415a /hw4/src/boundedVolumeNode.cpp
downloadcsci427-master.tar.xz
csci427-master.zip
Diffstat (limited to 'hw4/src/boundedVolumeNode.cpp')
-rw-r--r--hw4/src/boundedVolumeNode.cpp97
1 files changed, 97 insertions, 0 deletions
diff --git a/hw4/src/boundedVolumeNode.cpp b/hw4/src/boundedVolumeNode.cpp
new file mode 100644
index 0000000..fd143bb
--- /dev/null
+++ b/hw4/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"
+
+#include <iostream> // remove before submission
+#include <stdio.h> // remove before submission
+
+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()
+{
+ // HW4: Implement this.
+ // Constructs the bounding volume hierarchy. You can alter the order of elements between
+ // the 'start' and 'end' iterator. The _left and _right node can either be a boundedPrimitive
+ // or a new boundedVolume node (see _left and _right below respectively for an example of both).
+ // Don't forget to initialize the bounding box (_bb). Average time complexity: O(NlogN).
+ // Modifies: _left, _right, and _bb.
+ // Returns: nothing.
+
+ // create bounding box _bb for the incoming vector of primitives
+ _bb = boundingBox();
+ for (auto itr = start; itr != end; itr++) { _bb += (**itr).boundingbox(); }
+
+ // select random axis to work with
+ unsigned int axis = random_int(2);
+
+ // terminate recursion with final remaining primitives
+ switch(std::distance(start, end)) {
+ case 0: return; // no elements remain
+ case 1: _left = *start; return; // single element remains; chose _left node
+ case 2: { // two elements remain; sort and set
+ if (getAxis(*start, axis) > getAxis(*(end - 1), axis)) {
+ std::swap(*start, *(end - 1));
+ }
+
+ _left = *start;
+ _right = *(end - 1);
+ return;
+ }
+ }
+
+ // perform quicksort-style reordering of vector
+ auto i = start;
+ auto j = end - 1;
+ // select random pivot
+ vec3d::value_type pivot = getAxis(*(start + random_int(std::distance(start, end) - 1)), axis);
+
+ while (i < j) {
+ while (getAxis(*j, axis) > pivot && j > i) { j--; }
+ while (getAxis(*i, axis) < pivot && i <= j) { i++; }
+
+ if (i < j) {
+ std::swap(*i, *j);
+ i++;
+ }
+
+ }
+
+ // recurse upon remaining elements
+ _right = std::shared_ptr<const boundedPrimitive>(new boundedVolumeNode(j, end));
+ _left = std::shared_ptr<const boundedPrimitive>(new boundedVolumeNode(start, i));
+ // Done.
+}
+
+vec3d::value_type boundedVolumeNode::getAxis(const std::shared_ptr<const boundedPrimitive>& primitive, unsigned int axis) {
+
+ switch(axis) {
+ case 0: return (*primitive).boundingbox().center().x;
+ case 1: return (*primitive).boundingbox().center().y;
+ case 2: return (*primitive).boundingbox().center().z;
+ }
+
+}
+
+intersectionPoint boundedVolumeNode::intersect(const ray& r) const
+{
+ // HW4: Implement this
+ // Intersect the bounding volume hierarchy, and return the nearest intersection point.
+ // You will need to explore both _left and _right. Average time complexity: O(logN).
+
+ intersectionPoint ip, ip_left, ip_right;
+ ip = intersectionPoint();
+ if (!hitBoundingBox(r)) { return ip; }
+ if (_left && _left->hitBoundingBox(r)) { ip_left = _left->intersect(r); }
+ if (_right && _right->hitBoundingBox(r)) { ip_right = _right->intersect(r); }
+ return (ip_left < ip_right ? ip_left : ip_right);
+}