Skip to content

Commit

Permalink
Merge pull request #13 from goksuguvendiren/bounding_box
Browse files Browse the repository at this point in the history
Bounding box
  • Loading branch information
goksuguvendiren committed Mar 26, 2017
2 parents 1bb1557 + eb43b5d commit 037cfae
Show file tree
Hide file tree
Showing 21 changed files with 1,455,572 additions and 103 deletions.
144 changes: 144 additions & 0 deletions BoundingVolume.cpp
@@ -0,0 +1,144 @@
//
// Created by Göksu Güvendiren on 24/03/2017.
//

#include "HitInfo.h"
#include "BoundingVolume.h"
#include "Shape.h"
#include "Box.h"
#include "glm/glm.hpp"
#include "Triangle.h"

BoundingVolume::BoundingVolume(const std::vector<Shape*>& shapes, Axis axis)
{
left = nullptr;
right = nullptr;
shape = nullptr;

assert(shapes.size() > 0);

if (shapes.size() == 1){
shape = shapes[0];
box = Box(shapes[0]->Min(), shapes[0]->Max());

return;
}

std::vector<Shape*> leftshapes; leftshapes.reserve(shapes.size() / 2 + 1);
std::vector<Shape*> rightshapes; rightshapes.reserve(shapes.size() / 2 + 1);

Axis nextAxis;
glm::vec3 middle;

std::vector<Shape*>::const_iterator beginning;
std::vector<Shape*>::const_iterator middling;
std::vector<Shape*>::const_iterator ending;

auto sortedShapes = shapes;

assert(axis == Axis::X || axis == Axis::Y || axis == Axis::Z);

switch(axis){
case Axis::X :
std::sort(sortedShapes.begin(), sortedShapes.end(), [](auto& sh1, auto& sh2){
return sh1->Middle().x < sh2->Middle().x;
});

nextAxis = Axis::Y;
break;

case Axis::Y :
std::sort(sortedShapes.begin(), sortedShapes.end(), [](auto& sh1, auto& sh2){
return sh1->Middle().y < sh2->Middle().y;
});

nextAxis = Axis::Z;
break;

case Axis::Z :
std::sort(sortedShapes.begin(), sortedShapes.end(), [](auto& sh1, auto& sh2){
return sh1->Middle().z < sh2->Middle().z;
});

nextAxis = Axis::X;
break;
}

beginning = sortedShapes.begin();
middling = sortedShapes.begin() + (sortedShapes.size() / 2);
ending = sortedShapes.end();

leftshapes = std::vector<Shape*>(beginning, middling);
rightshapes = std::vector<Shape*>(middling, ending);

assert(shapes.size() == (leftshapes.size() + rightshapes.size()));

left = new BoundingVolume(leftshapes, nextAxis);
right = new BoundingVolume(rightshapes, nextAxis);

box.Min(glm::min(left->box.Min(), right->box.Min()));
box.Max(glm::max(left->box.Max(), right->box.Max()));
}

auto to_ptrs(const std::vector<Triangle> &triangles)
{
std::vector<Shape*> shapes(triangles.size());

for(int i = 0; i < triangles.size(); i++){
const Shape* s = triangles.data() + i;
shapes[i] = const_cast<Shape*>(s);
}

return shapes;
}

BoundingVolume::BoundingVolume(const std::vector<Triangle> &triangles, Axis axis) :
BoundingVolume(to_ptrs(triangles), axis)
{}

boost::optional<HitInfo> BoundingVolume::Hit(const Ray &ray) const
{
if (!box.Hit(ray)) return boost::none;
if (!left && !right) return shape->Hit(ray);

boost::optional<HitInfo> leftHitInfo = left->Hit(ray);
boost::optional<HitInfo> rightHitInfo = right->Hit(ray);

if (!leftHitInfo && !rightHitInfo) return boost::none;

HitInfo ultimate;

if (leftHitInfo) {
ultimate = *leftHitInfo;
}
if (rightHitInfo){
if (rightHitInfo->Parameter() < ultimate.Parameter())
ultimate = *rightHitInfo;
}

return ultimate;
}


//bool BoundingVolume::FastHit (const Ray& ray) const
//{
// if (!box.Hit(ray)) return false;
// if (!left && !right) return shape->FastHit(ray);
//
// boost::optional<HitInfo> leftHitInfo = left->Hit(ray);
// boost::optional<HitInfo> rightHitInfo = right->Hit(ray);
//
// if (!leftHitInfo && !rightHitInfo) return false;
//
// HitInfo ultimate;
//
// if (leftHitInfo) {
// ultimate = *leftHitInfo;
// }
// if (rightHitInfo){
// if (rightHitInfo->Parameter() < ultimate.Parameter())
// ultimate = *rightHitInfo;
// }
//
// return ultimate;
//}
39 changes: 39 additions & 0 deletions BoundingVolume.h
@@ -0,0 +1,39 @@
//
// Created by Göksu Güvendiren on 24/03/2017.
//

#pragma once
#include <vector>
#include "glm/vec3.hpp"
#include "boost/optional.hpp"
#include "Box.h"

class Shape;
class Triangle;
class Ray;
class HitInfo;

enum class Axis
{
X,
Y,
Z
};

class BoundingVolume
{
Box box;
BoundingVolume* left;
BoundingVolume* right;

Shape* shape;

public:
BoundingVolume() : left(nullptr), right(nullptr), shape(nullptr) {};
const Box& BBox() const { return box; }
BoundingVolume(const std::vector<Shape*>& shapes, Axis axis);
BoundingVolume(const std::vector<Triangle>& triangles, Axis axis);

boost::optional<HitInfo> Hit (const Ray& ray) const;
bool FastHit (const Ray& ray) const;
};
48 changes: 48 additions & 0 deletions Box.cpp
@@ -0,0 +1,48 @@
//
// Created by Göksu Güvendiren on 18/03/2017.
//

#include "Box.h"
#include "Shape.h"
#include "Ray.h"

bool Box::Hit(const Ray &ray) const
{
auto mins = (minValues - ray.Origin()) * ray.InvDirection();
auto maxs = (maxValues - ray.Origin()) * ray.InvDirection();

float tx1 = mins.x;
float tx2 = maxs.x;

float tmin = std::min(tx1, tx2);
float tmax = std::max(tx1, tx2);

float ty1 = mins.y;
float ty2 = maxs.y;

tmin = std::max(tmin, std::min(ty1, ty2));
tmax = std::min(tmax, std::max(ty1, ty2));

float tz1 = mins.z;
float tz2 = maxs.z;

tmin = std::max(tmin, std::min(tz1, tz2));
tmax = std::min(tmax, std::max(tz1, tz2));

return tmax >= std::max(0.f, tmin);
}

void Box::Compare(const glm::vec3 &val)
{
minValues = glm::min(minValues, val);
maxValues = glm::max(maxValues, val);
}

Box::Box()
{}

Box::Box(glm::vec3 minval, glm::vec3 maxval)
{
minValues = minval;
maxValues = maxval;
}
34 changes: 34 additions & 0 deletions Box.h
@@ -0,0 +1,34 @@
//
// Created by Göksu Güvendiren on 18/03/2017.
//

#pragma once

#include <boost/optional.hpp>
#include "glm/vec3.hpp"

class HitInfo;
class Ray;

class Box
{
glm::vec3 minValues;
glm::vec3 maxValues;

public:
Box();
Box(glm::vec3 minval, glm::vec3 maxval);

// boost::optional<HitInfo> Hit(const Ray &ray) const;
bool Hit(const Ray &ray) const;

void Min(glm::vec3 val) { minValues = val; }
void Max(glm::vec3 val) { maxValues = val; }

const glm::vec3& Min() const { return minValues; }
const glm::vec3& Max() const { return maxValues; }
const glm::vec3 Middle() const { return (minValues + maxValues) / 2.0f; }

void Compare(const glm::vec3& val);

};
2 changes: 1 addition & 1 deletion CMakeLists.txt
Expand Up @@ -9,7 +9,7 @@ set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -O3")
set(SOURCE_FILES main.cpp Camera.cpp Camera.h ImagePlane.cpp ImagePlane.h Color.cpp Color.h Sphere.cpp Sphere.h
Ray.cpp Ray.h Scene.cpp Scene.h Image.cpp Image.h Triangle.cpp Triangle.h HitInfo.cpp HitInfo.h Material.cpp
Material.h tinyxml/tinyxml2.cpp tinyxml/tinyxml2.h Vertex.cpp Vertex.h Mesh.cpp Mesh.h LightSource.cpp
LightSource.h Shape.cpp Shape.h Transformation.cpp Transformation.h)
LightSource.h Shape.cpp Shape.h Transformation.cpp Transformation.h Box.cpp Box.h BoundingVolume.cpp BoundingVolume.h)

add_executable(RayTracer ${SOURCE_FILES})

Expand Down
22 changes: 6 additions & 16 deletions Camera.cpp
Expand Up @@ -8,7 +8,7 @@
#include "Ray.h"
#include "Scene.h"
#include "Triangle.h"
#include "Mesh.h"
#include "BoundingVolume.h"
#include "LightSource.h"

glm::vec3 Camera::CalculateReflectance(const HitInfo& hit) const
Expand All @@ -21,9 +21,7 @@ glm::vec3 Camera::CalculateReflectance(const HitInfo& hit) const
Ray ray(hit.Position() + (scene.ShadowRayEpsilon() * direction),
direction);

if (std::any_of(scene.Shapes().begin(), scene.Shapes().end(), [&ray](auto shape) {
return shape->FastHit(ray);
})) continue;
if (scene.BoundingBox().Hit(ray)) continue;

glm::vec3 pointToLight = light.Position() - hit.Position();
auto intensity = light.Intensity(pointToLight);
Expand Down Expand Up @@ -80,18 +78,10 @@ Image Camera::Render() const
rowPixLocation += oneRight;
auto ray = Ray(position, rowPixLocation - position);

boost::optional<HitInfo> ultHit;

for (auto shape : scene.Shapes()){
boost::optional<HitInfo> hit;
if ((hit = shape->Hit(ray)) && (!ultHit || hit->Parameter() < ultHit->Parameter())){
ultHit = *hit;
}
}

if (ultHit)
image.at(i, j) = CalculateReflectance(*ultHit);
// image.at(i, j) = 255.0f * (ultHit->Normal() + glm::vec3{1, 1, 1}) / 2.0f; //CalculateReflectance(*ultHit);
boost::optional<HitInfo> hit = scene.BoundingBox().Hit(ray);
if (hit)
image.at(i, j) = CalculateReflectance(*hit);
// image.at(i, j) = 255.0f * (hit->Normal() + glm::vec3{1, 1, 1}) / 2.0f; //CalculateReflectance(*ultHit);
else
image.at(i, j) = scene.BackgroundColor();
}
Expand Down
15 changes: 6 additions & 9 deletions HitInfo.h
Expand Up @@ -15,22 +15,19 @@ class HitInfo
glm::vec3 normal;
glm::vec3 position;

Material mat;
// Ray ray;

const Material* mat;

public:
HitInfo(glm::vec3 n,
Material m,
// Ray r = {{0, 0, 0}, {}}) : normal(n), mat(m), param(t), ray(r)
const Material& m,
glm::vec3 point,
float t = std::numeric_limits<float>::infinity()) : normal(n), mat(m), position(point), param(t)
float t = std::numeric_limits<float>::infinity()) : normal(n), mat(&m), position(point), param(t)
{}

const Material& Material() const { return mat; }
HitInfo() : param(std::numeric_limits<float>::infinity()) {}

const Material& Material() const { return *mat; }
float Parameter() const { return param; }
glm::vec3 Normal() const { return normal; }
// Ray Ray() const { return ray; }
// glm::vec3 Position() const { return ray.Origin() + param * ray.Direction(); }
glm::vec3 Position() const { return position; }
};

0 comments on commit 037cfae

Please sign in to comment.