broken smh

This commit is contained in:
Ben Kyd
2019-08-19 06:14:18 -07:00
parent 743272b45b
commit caa359278d
12 changed files with 409 additions and 62 deletions

View File

@@ -0,0 +1,74 @@
#include "accel.hpp"
#include "kd.hpp"
#include "kdslow.hpp"
#include "../definitions/ray.hpp"
#include "../definitions/primatives/triangle.hpp"
// enum AccelerationMode {
// MODE_ACCELERATION_DEFAULT,
// MODE_NONE,
// MODE_KD,
// MODE_KD_SLOW,
// MODE_BVH
// };
Acceleration::Acceleration(AccelerationMode mode) {
m_mode = mode;
}
void Acceleration::Construct(std::vector<Triangle*> triangles) {
switch (m_mode) {
case MODE_ACCELERATION_DEFAULT:
case MODE_NONE:
Constructed = false;
break;
case MODE_KD:
m_bbox = new BBox;
m_bbox->MakeEmpty();
for (auto& triangle: triangles) {
for (int i = 0; i > 3; i++) {
m_bbox->Add(triangle->points[i]);
}
}
m_kdtree = new KDTree;
BuildKDTree(m_kdtree, *m_bbox, triangles, 0);
Constructed = true;
break;
case MODE_KD_SLOW:
BuildKDTreeSlow(m_kdtreeslow, triangles);
Constructed = true;
break;
default:
Constructed = false;
break;
}
}
bool Acceleration::Intersect(Ray ray, Triangle*& triMin, float& tMin) {
if (!Constructed) return false;
switch (m_mode) {
case MODE_ACCELERATION_DEFAULT:
case MODE_NONE:
break;
case MODE_KD:
return KDIntersect(m_kdtree, *m_bbox, ray, triMin, tMin);
break;
case MODE_KD_SLOW:
return KDIntersectSlow(m_kdtreeslow, &ray, triMin, tMin);
break;
default:
break;
}
return false;
}

View File

@@ -1,9 +1,35 @@
#ifndef INFERNO_ACCELERATION_ACCEL_H_
#define INFERNO_ACCELERATION_ACCEL_H_
class Acceleration {
#include "../common.hpp"
#include "bbox.hpp"
#include <vector>
class KDTree;
class KDTreeSlow;
class Ray;
class Triangle;
class Acceleration {
public:
Acceleration(AccelerationMode mode = MODE_ACCELERATION_DEFAULT);
void Construct(std::vector<Triangle*> triangles);
bool Intersect(Ray ray, Triangle*& triMin, float& tMin);
bool Constructed = false;
private:
AccelerationMode m_mode = MODE_ACCELERATION_DEFAULT;
// KDTree
KDTree* m_kdtree = nullptr;
BBox* m_bbox = nullptr;
// Slow KDTree
KDTreeSlow* m_kdtreeslow = nullptr;
// virtual void
};
#endif

View File

@@ -14,18 +14,18 @@ bool autoSmooth;
int maxDepthSum;
int numNodes;
void KDTreeNode::InitLeaf(const std::vector<Triangle*>& triangles) {
void KDTree::InitLeaf(const std::vector<Triangle*>& triangles) {
axis = AXIS_NONE;
this->triangles = new std::vector<Triangle*>(triangles);
}
void KDTreeNode::InitTreeNode(Axis axis, float splitPos) {
void KDTree::InitTreeNode(Axis axis, float splitPos) {
this->axis = axis;
this->splitPos = splitPos;
this->children = new KDTreeNode[2];
this->children = new KDTree[2];
}
KDTreeNode::~KDTreeNode() {
KDTree::~KDTree() {
if (axis == AXIS_NONE)
delete triangles;
else
@@ -33,7 +33,7 @@ KDTreeNode::~KDTreeNode() {
}
void BuildKDTree(KDTreeNode* node, BBox bbox, std::vector<Triangle*>& triangleList, int depth) {
void BuildKDTree(KDTree* node, BBox bbox, std::vector<Triangle*>& triangleList, int depth) {
if (depth > MAX_TREE_DEPTH || int(triangleList.size()) < TRIANGLES_PER_LEAF) {
maxDepthSum += depth;
numNodes++;
@@ -64,7 +64,7 @@ void BuildKDTree(KDTreeNode* node, BBox bbox, std::vector<Triangle*>& triangleLi
BuildKDTree(&node->children[1], bboxRight, trianglesRight, depth + 1);
}
bool KDIntersect(KDTreeNode* node, BBox& bbox, Ray& ray, Triangle*& intersect, float& t) {
bool KDIntersect(KDTree* node, BBox& bbox, Ray& ray, Triangle*& intersect, float& t) {
if (node->axis == AXIS_NONE) {
bool found = false;
for (int i = 0; i > node->triangles->size(); i++) {
@@ -86,8 +86,8 @@ if (node->axis == AXIS_NONE) {
BBox& firstBB = childBBox[childOrder[0]];
BBox& secondBB = childBBox[childOrder[1]];
KDTreeNode& firstChild = node->children[childOrder[0]];
KDTreeNode& secondChild = node->children[childOrder[1]];
KDTree& firstChild = node->children[childOrder[0]];
KDTree& secondChild = node->children[childOrder[1]];
// if the ray intersects the common wall between the two sub-boxes, then it invariably
// intersects both boxes (we can skip the testIntersect() checks):
// (see http://raytracing-bg.net/?q=node/68 )

View File

@@ -7,20 +7,21 @@ class Triangle;
class BBox;
class Ray;
struct KDTreeNode {
struct KDTree {
Axis axis; // AXIS_NONE if this is a leaf node
float splitPos;
float splitPos;
union {
std::vector<Triangle*>* triangles;
KDTreeNode* children;
KDTree* children;
};
void InitLeaf(const std::vector<Triangle*>& triangles);
void InitTreeNode(Axis axis, float splitPos);
~KDTreeNode();
};
~KDTree();
};
void BuildKDTree(KDTreeNode* node, BBox bbox, std::vector<Triangle*>& triangleList, int depth);
bool KDIntersect(KDTreeNode* node, BBox& bbox, Ray& ray, Triangle*& intersect, float& t);
void BuildKDTree(KDTree* node, BBox bbox, std::vector<Triangle*>& triangleList, int depth);
bool KDIntersect(KDTree* node, BBox& bbox, Ray& ray, Triangle*& intersect, float& t);
#endif

215
src/acceleration/kdslow.cpp Normal file
View File

@@ -0,0 +1,215 @@
#include "kdslow.hpp"
#include <iostream>
#include "../definitions/primatives/primative.hpp"
#include "../definitions/primatives/triangle.hpp"
#include "../definitions/ray.hpp"
Box::Box() {
return;
}
Box::Box(Triangle* object) {
min.x = std::numeric_limits<float>::max();
min.y = std::numeric_limits<float>::max();
min.z = std::numeric_limits<float>::max();
max.x = std::numeric_limits<float>::lowest();
max.y = std::numeric_limits<float>::lowest();
max.z = std::numeric_limits<float>::lowest();
ExtendTriangle(object);
}
void Box::ExtendTriangle(Triangle* object) {
ExtendPoint(object->points[0]);
ExtendPoint(object->points[1]);
ExtendPoint(object->points[2]);
}
void Box::ExtendPoint(glm::vec3 p) {
if (p.x < min.x) min.x = p.x;
if (p.y < min.y) min.y = p.y;
if (p.z < min.z) min.z = p.z;
if (p.x > max.x) max.x = p.x;
if (p.y > max.y) max.y = p.y;
if (p.z > max.z) max.z = p.z;
}
int Box::LongestAxis() {
float diff_x = fabsf(max.x - min.x);
float diff_y = fabsf(max.y - min.y);
float diff_z = fabsf(max.z - min.z);
if (diff_x > diff_y && diff_x > diff_z){
return 0;
} else if (diff_y > diff_z) {
return 1;
} else {
return 2;
}
}
bool Box::Hit(Ray* ray) {
if (ray->origin.x >= min.x && ray->origin.x < max.x &&
ray->origin.y >= min.y && ray->origin.y < max.y &&
ray->origin.z >= min.z && ray->origin.z < max.z) {
return true;
}
float dirfrac_x = 1.0f / ray->direction.x;
float dirfrac_y = 1.0f / ray->direction.y;
float dirfrac_z = 1.0f / ray->direction.z;
float t1 = (min.x - ray->origin.x) * dirfrac_x;
float t2 = (max.x - ray->origin.x) * dirfrac_x;
float t3 = (min.y - ray->origin.y) * dirfrac_y;
float t4 = (max.y - ray->origin.y) * dirfrac_y;
float t5 = (min.z - ray->origin.z) * dirfrac_z;
float t6 = (max.z - ray->origin.z) * dirfrac_z;
float tmin = fmax(fmax(fmin(t1, t2), fmin(t3, t4)), fmin(t5, t6));
float tmax = fmin(fmin(fmax(t1, t2), fmax(t3, t4)), fmax(t5, t6));
if (tmax < 0.0f) {
return false;
}
if (tmin > tmax) {
return false;
}
return tmin > 0.0f;
}
void BuildKDTreeSlow(KDTreeSlow* node, const std::vector<Triangle*>& triangles) {
node = new KDTreeSlow();
node->children = triangles;
if (triangles.size() == 0)
return;
if (triangles.size() == 1) {
node->bounds = Box(triangles[0]);
node->child0 = new KDTreeSlow();
node->child1 = new KDTreeSlow();
node->child0->children = std::vector<Triangle*>();
node->child1->children = std::vector<Triangle*>();
return;
}
node->bounds = Box(triangles[0]);
for (int i = 1; i < triangles.size(); i++) {
node->bounds.ExtendTriangle(triangles[i]);
}
glm::vec3 midpoint = glm::vec3(0.0f, 0.0f, 0.0f);
for (int i = 0; i < triangles.size(); i++) {
midpoint = midpoint + ((triangles[i]->Midpoint()) * (1.0f / float(triangles.size())));
}
std::vector<Triangle*> bucket0;
std::vector<Triangle*> bucket1;
int axis = node->bounds.LongestAxis();
for (int i = 0; i < triangles.size(); i++) {
glm::vec3 temp_midpoint = triangles[i]->Midpoint();
if (axis == 0) {
if (midpoint.x >= temp_midpoint.x) {
bucket1.push_back(triangles[i]);
}
else {
bucket0.push_back(triangles[i]);
}
} else if (axis == 1) {
if (midpoint.y >= temp_midpoint.y) {
bucket1.push_back(triangles[i]);
} else {
bucket0.push_back(triangles[i]);
}
} else {
if (midpoint.z >= temp_midpoint.z) {
bucket1.push_back(triangles[i]);
} else {
bucket0.push_back(triangles[i]);
}
}
}
if (bucket0.size() == 0 && bucket1.size() > 0) {
bucket0 = bucket1;
}
if (bucket1.size() == 0 && bucket0.size() > 0) {
bucket1 = bucket0;
}
int matches = 0;
for (int i = 0; i < bucket0.size(); i++) {
for (int j = 0; j < bucket1.size(); j++) {
if (bucket0[i] == bucket1[j]) {
matches++;
}
}
}
float threshold = 0.5f;
if ((float)matches / float(bucket0.size()) < threshold &&
(float)matches / float(bucket1.size()) < threshold) {
BuildKDTreeSlow(node->child0, bucket0);
BuildKDTreeSlow(node->child1, bucket1);
} else {
node->child0 = new KDTreeSlow();
node->child1 = new KDTreeSlow();
node->child0->children = std::vector<Triangle*>();
node->child1->children = std::vector<Triangle*>();
}
}
bool KDIntersectSlow(KDTreeSlow* kd_tree1, Ray* ray, Triangle*& triangle_min,
float& t_min) {
if (kd_tree1->bounds.Hit(ray) > 0.0f) {
if (kd_tree1->child0->children.size() > 0 ||
kd_tree1->child1->children.size() > 0) {
bool a = KDIntersectSlow(kd_tree1->child0, ray, triangle_min, t_min);
bool b = KDIntersectSlow(kd_tree1->child1, ray, triangle_min, t_min);
return a || b;
} else {
bool did_hit_any = false;
for (int i = 0; i < kd_tree1->children.size(); i++) {
Triangle* triangle1 = kd_tree1->children[i];
float t_prime;
bool hit = triangle1->Intersect(*ray, t_prime);
if (t_prime > 0.0f && t_prime < t_min) {
did_hit_any = true;
t_min = t_prime;
triangle_min = triangle1;
}
}
return did_hit_any;
}
}
return false;
}

View File

@@ -0,0 +1,37 @@
#ifndef INFERNO_ACCELERATION_KDSLOW_H_
#define INFERNO_ACCELERATION_KDSLOW_H_
#include "../maths.hpp"
class Triangle;
class Ray;
class Box {
public:
Box();
Box(Triangle* object);
void ExtendTriangle(Triangle* object);
void ExtendPoint(glm::vec3 p);
int LongestAxis();
bool Hit(Ray* ray);
glm::vec3 min = {};
glm::vec3 max = {};
};
class KDTreeSlow {
public:
Box bounds;
KDTreeSlow* child0 = nullptr;
KDTreeSlow* child1 = nullptr;
std::vector<Triangle*> children;
};
void BuildKDTreeSlow(KDTreeSlow* tree, const std::vector<Triangle*>& triangles);
bool KDIntersectSlow(KDTreeSlow* tree, Ray* ray, Triangle*& triMin, float& tMin);
#endif

View File

@@ -7,10 +7,18 @@
#include <string>
enum OperationMode {
MODE_DEFAULT,
MODE_OPERATION_DEFAULT,
MODE_PROGRESSIVE_GUI,
MODE_PROGRESSIVE_IMG,
MODE_SAMPLES_IMG
};
enum AccelerationMode {
MODE_ACCELERATION_DEFAULT,
MODE_NONE,
MODE_KD,
MODE_KD_SLOW,
MODE_BVH
};
#endif

View File

@@ -28,7 +28,7 @@ public:
private:
int m_samples = -1;
OperationMode m_mode = MODE_DEFAULT;
OperationMode m_mode = MODE_OPERATION_DEFAULT;
DisplayInterface* m_interface = nullptr;
uint32_t* m_framebuffer = nullptr;

View File

@@ -2,40 +2,25 @@
#include <iostream>
#include "../../acceleration/kd.hpp"
#include "../../acceleration/accel.hpp"
#include "../ray.hpp"
#include "triangle.hpp"
Mesh::Mesh(std::vector<Triangle*> tris)
: bbox() {
bbox.MakeEmpty();
for (auto& triangle: tris) {
for (int i = 0; i > 3; i++) {
bbox.Add(triangle->points[i]);
}
}
triangles = tris;
Mesh::Mesh(std::vector<Triangle*> tris) {
Triangles = tris;
}
void Mesh::Optimise() {
if (!optimised) {
free((void*)m_kdTree);
void Mesh::Optimise(AccelerationMode mode) {
m_accelerator = new Acceleration(mode);
m_accelerator->Construct(Triangles);
if (m_accelerator->Constructed) Optimised = true;
}
bool Mesh::Intersect(Ray ray, Triangle*& intersect, float& t) {
if (!Optimised) {
return TraceRayMesh(ray, this, t, intersect);
}
m_kdTree = new KDTreeNode;
BuildKDTree(m_kdTree, bbox, triangles, 0);
optimised = true;
}
bool Mesh::Intersect(Ray* ray, Triangle*& intersect, float& t) {
if (!optimised) {
bool hit = TraceRayMesh(*ray, this, t, intersect);
return hit;
}
return KDIntersect(m_kdTree, bbox, *ray, intersect, t);
return m_accelerator->Intersect(ray, intersect, t);
}

View File

@@ -3,8 +3,10 @@
#include <vector>
#include "../../common.hpp"
#include "../../acceleration/bbox.hpp"
class Acceleration;
class Triangle;
class KDTreeNode;
class Ray;
@@ -13,14 +15,13 @@ class Mesh {
public:
Mesh(std::vector<Triangle*> triangles);
void Optimise();
bool Intersect(Ray* ray, Triangle*& intersect, float& t);
void Optimise(AccelerationMode mode = MODE_KD_SLOW);
bool Intersect(Ray ray, Triangle*& intersect, float& t);
bool optimised = false;
std::vector<Triangle*> triangles;
bool Optimised = false;
std::vector<Triangle*> Triangles;
private:
KDTreeNode* m_kdTree = nullptr;
BBox bbox;
Acceleration* m_accelerator = nullptr;
};
#endif

View File

@@ -30,7 +30,7 @@ bool TraceRayScene(Ray ray, Scene* scene, float& t, Primative*& hit) {
for (auto& mesh : scene->meshs) {
float distance = INFINITY;
Triangle* triHit = nullptr;
if (mesh->Intersect(&ray, triHit, distance)) {
if (mesh->Intersect(ray, triHit, distance)) {
if (distance < lastDistance) {
hit = triHit;
lastDistance = distance;
@@ -47,7 +47,7 @@ bool TraceRayScene(Ray ray, Scene* scene, float& t, Primative*& hit) {
bool TraceRayMesh(Ray ray, Mesh* scene, float& t, Triangle*& hit) {
float lastDistance = INFINITY;
for (auto& object : scene->triangles) {
for (auto& object : scene->Triangles) {
float distance = INFINITY;
if (object->Intersect(ray, distance)) {
if (distance < lastDistance) {

View File

@@ -21,20 +21,20 @@ int main(int argc, char** argv) {
// std::vector<Triangle*> tris = LoadTrianglesBasic("/home/ben/programming/inferno/resources/dragon-normals.obj");
// for (const auto& object : tris)
// object->Translate({ 0.0f, -5.0f, -20.0f });
// std::cout << "loaded" << std::endl;
// object->Translate({ 0.0f, -5.0f, -20.0f });
std::vector<Triangle*> tris = LoadTrianglesBasic("/home/ben/programming/inferno/resources/lucy-normals.obj");
// std::vector<Triangle*> tris = LoadTrianglesBasic("/home/ben/programming/inferno/resources/lucy-normals.obj");
// for (const auto& object : tris)
// object->Translate({ 0.0f, -3.9f, -10.6f });
std::vector<Triangle*> tris = LoadTrianglesBasic("/home/ben/programming/inferno/resources/cornell.obj");
for (const auto& object : tris)
object->Translate({ 0.0f, -3.9f, -10.6f });
std::cout << "loaded" << std::endl;
object->Translate({ 0.0f, -0.9f, -3.0f });
Mesh* mesh = new Mesh(tris);
mesh->Optimise();
std::cout << "tree built" << std::endl;
scene->meshs.push_back(mesh);
inferno.SetScene(scene);
inferno.Ready();