diff options
Diffstat (limited to 'hw6/src/boundedCompound.cpp')
-rw-r--r-- | hw6/src/boundedCompound.cpp | 139 |
1 files changed, 139 insertions, 0 deletions
diff --git a/hw6/src/boundedCompound.cpp b/hw6/src/boundedCompound.cpp new file mode 100644 index 0000000..c37ca0f --- /dev/null +++ b/hw6/src/boundedCompound.cpp @@ -0,0 +1,139 @@ +/******************************************************************/ +/* 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 "boundedCompound.h" +#include "intersector_factory_base.h" + +///////////////// +// Constructor // +///////////////// +boundedCompound::boundedCompound(void) + : boundedPrimitive() +{ + _transform = transformation3d(); + _intersector = nullptr; +} + + +boundedCompound::boundedCompound(const transformation3d& transform, const std::shared_ptr<const shader_base>& shader) + + : boundedPrimitive(boundingBox(), shader) +{ + _transform = transform; + _intersector = nullptr; +} + + +///////////// +// Methods // +///////////// +intersectionPoint boundedCompound::intersect(const ray& r) const +{ + // sanity check + assert(_intersector); + + // inverse transform ray + ray transformedRay = inverseTransform(r, _transform); + + // pass intersection computation to _intersector + intersectionPoint ip = _intersector->intersect( transformedRay ); + + // if no shader, insert current shader + if(!ip.hasShader()) ip.setShader(_shader); + + // transform the intersection point + ip.transform(_transform); + + // Done. + return ip; +} + + +float boundedCompound::area(void) const +{ + float total_area = 0.0f; + for_each(compounds().begin(), compounds().end(), [&](const std::shared_ptr<const boundedPrimitive>& prim) + { + total_area += prim->area(); + }); + + // Done. + return total_area; +} + + +surfaceSample boundedCompound::sample(float r1, float r2) const +{ + float total_area = area(); + auto primItr = compounds().begin(); + + // sample compounds (proportional to area) + float prim_area = (*primItr)->area(); + float residual = r1*total_area; + while(residual > prim_area && std::next(primItr) != compounds().end()) + { + residual -= prim_area; + primItr++; + prim_area = (*primItr)->area(); + } + + // rescale the random variable + r1 = std::min(residual / prim_area, 1.0f); + + // sample point in triangle (and adjust pdf to include the above selection) + surfaceSample sample = (*primItr)->sample(r1, r2) * (prim_area / total_area); + + // apply transformation + sample.transform(_transform); + + // Done. + return sample; +} + + +void boundedCompound::initialize(const intersector_factory_base& ifb) +{ + // create the _intersector + _intersector = ifb(*this); +} + + +void boundedCompound::initializeBoundingBox(void) +{ + // compute the bounding box in world coordinates + _bb = boundingBox(); + for_each(compounds().begin(), compounds().end(), [&](const std::shared_ptr<const boundedPrimitive>& prim) + { + _bb += transform(prim->boundingbox(), _transform); + }); +} + + +bool boundedCompound::hasShader(void) const +{ + // check if this has a shader + if(boundedPrimitive::hasShader()) return true; + + // check if each child has a shader + for(auto itr = compounds().begin(); itr != compounds().end(); itr++) + { + if(!(*itr)->hasShader()) return false; + } + + // Done. + return true; +} + + +void boundedCompound::_print(std::ostream& s) const +{ + s << "boundedCompound (" << _bb << ", " << compounds().size() << " compounds)"; +} |