/******************************************************************/ /* 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 #include #include "boundedVolumeNode.h" #include "random_number.h" #include // remove before submission #include // remove before submission boundedVolumeNode::boundedVolumeNode(const std::vector>::iterator& start, const std::vector>::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(new boundedVolumeNode(j, end)); _left = std::shared_ptr(new boundedVolumeNode(start, i)); // Done. } vec3d::value_type boundedVolumeNode::getAxis(const std::shared_ptr& 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); }