a rewrite (maybe rust) is coming SOON
This commit is contained in:
5
hart/inferno-hart-cpu/src/kdtree.cpp
Normal file
5
hart/inferno-hart-cpu/src/kdtree.cpp
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
#include "kdtree.hpp"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
@@ -1,203 +1,135 @@
|
|||||||
#include <hart_graphics.hpp>
|
#pragma once
|
||||||
|
|
||||||
#include <tracing/ray.hpp>
|
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
#include <utility>
|
|
||||||
#include <array>
|
#include <hart_graphics.hpp>
|
||||||
#include <iostream>
|
|
||||||
|
#include <tracing/ray.hpp>
|
||||||
|
#include <yolo/yolo.hpp>
|
||||||
|
|
||||||
using namespace inferno;
|
using namespace inferno;
|
||||||
|
|
||||||
inline bool AABBIntersection(glm::vec3 min, glm::vec3 max, const Ray* r)
|
struct Triangle
|
||||||
{
|
{
|
||||||
float tmin = 0.0, tmax = INFINITY;
|
unsigned int indices[3];
|
||||||
glm::vec3 invDir = 1.0f / r->Direction;
|
};
|
||||||
|
|
||||||
for (int i = 0; i < 3; ++i) {
|
struct AABB
|
||||||
float t1 = (min[i] - r->Origin[i]) * invDir[i];
|
{
|
||||||
float t2 = (max[i] - r->Origin[i]) * invDir[i];
|
glm::vec3 min;
|
||||||
|
glm::vec3 max;
|
||||||
|
};
|
||||||
|
|
||||||
tmin = std::max(tmin, std::min(t1, t2));
|
struct KDNode
|
||||||
tmax = std::min(tmax, std::max(t1, t2));
|
{
|
||||||
|
AABB aabb;
|
||||||
|
unsigned int splitAxis;
|
||||||
|
std::vector<Triangle> triangles;
|
||||||
|
KDNode *left;
|
||||||
|
KDNode *right;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline AABB createAABB(const std::vector<glm::vec3>& vertices, const std::vector<Triangle>& triangles)
|
||||||
|
{
|
||||||
|
glm::vec3 min(std::numeric_limits<float>::max());
|
||||||
|
glm::vec3 max(std::numeric_limits<float>::min());
|
||||||
|
|
||||||
|
for (const auto& triangle : triangles)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < 3; ++i)
|
||||||
|
{
|
||||||
|
min = glm::min(min, vertices[triangle.indices[i]]);
|
||||||
|
max = glm::max(max, vertices[triangle.indices[i]]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool hit = (tmin <= tmax);
|
return { min, max };
|
||||||
//if (hit) {
|
|
||||||
//std::cout << "Ray hits AABB: " << tmin << ", " << tmax << std::endl;
|
|
||||||
//} else {
|
|
||||||
//std::cout << "Ray misses AABB" << std::endl;
|
|
||||||
//}
|
|
||||||
return hit;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct KDNode {
|
inline bool intersectAABB(const AABB& aabb, const glm::vec3& origin, const glm::vec3& direction, float& tNear, float& tFar)
|
||||||
uint32_t TriIdx;
|
{
|
||||||
glm::vec3 MinBounds;
|
for (int i = 0; i < 3; ++i)
|
||||||
glm::vec3 MaxBounds;
|
{
|
||||||
KDNode* LeftChild;
|
float invDirection = 1.0f / direction[i];
|
||||||
KDNode* RightChild;
|
float t0 = (aabb.min[i] - origin[i]) * invDirection;
|
||||||
|
float t1 = (aabb.max[i] - origin[i]) * invDirection;
|
||||||
|
|
||||||
KDNode(uint32_t triIdx, glm::vec3 minBounds, glm::vec3 maxBounds)
|
if (invDirection < 0.0f)
|
||||||
: TriIdx(triIdx), MinBounds(minBounds), MaxBounds(maxBounds), LeftChild(nullptr), RightChild(nullptr) {}
|
|
||||||
|
|
||||||
~KDNode() {
|
|
||||||
delete LeftChild;
|
|
||||||
delete RightChild;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setLeftChild(KDNode* child) {
|
|
||||||
LeftChild = child;
|
|
||||||
updateBounds();
|
|
||||||
}
|
|
||||||
|
|
||||||
void setRightChild(KDNode* child) {
|
|
||||||
RightChild = child;
|
|
||||||
updateBounds();
|
|
||||||
}
|
|
||||||
|
|
||||||
void updateBounds() {
|
|
||||||
if (LeftChild && RightChild) {
|
|
||||||
MinBounds = glm::min(LeftChild->MinBounds, RightChild->MinBounds);
|
|
||||||
MaxBounds = glm::max(LeftChild->MaxBounds, RightChild->MaxBounds);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class KDTree {
|
|
||||||
public:
|
|
||||||
KDTree(float* vertices, uint32_t* indices, std::vector<uint32_t>& indicesToProcess, uint32_t startIdx, uint32_t endIdx, uint32_t depthLimit)
|
|
||||||
: mVertices(vertices), mIndices(indices), mDepthLimit(depthLimit), mRoot(nullptr)
|
|
||||||
{
|
{
|
||||||
if (indicesToProcess.size() == 0) {
|
std::swap(t0, t1);
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
mRoot = buildNode(indicesToProcess, startIdx, endIdx, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
~KDTree() {
|
tNear = t0 > tNear ? t0 : tNear;
|
||||||
delete mRoot;
|
tFar = t1 < tFar ? t1 : tFar;
|
||||||
|
|
||||||
|
if (tNear > tFar)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void intersect(const Ray* ray, std::vector<uint32_t>& outIndices) {
|
return true;
|
||||||
intersect(mRoot, ray, outIndices);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
KDNode* getRoot() const {
|
inline KDNode* buildKDTree(const std::vector<glm::vec3>& vertices, std::vector<Triangle>& triangles, unsigned int depth = 0)
|
||||||
return mRoot;
|
{
|
||||||
}
|
if (triangles.empty())
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
void printTree(KDNode* node, int depth) const {
|
unsigned int splitAxis = depth % 3;
|
||||||
if (!node) {
|
std::sort(triangles.begin(), triangles.end(), [&](const Triangle& a, const Triangle& b) {
|
||||||
return;
|
return vertices[a.indices[0]][splitAxis] < vertices[b.indices[0]][splitAxis];
|
||||||
}
|
});
|
||||||
|
|
||||||
for (int i = 0; i < depth; i++) {
|
size_t midIdx = triangles.size() / 2;
|
||||||
std::cout << "-";
|
KDNode* node = new KDNode;
|
||||||
}
|
node->splitAxis = splitAxis;
|
||||||
std::cout << " " << glm::to_string(node->MinBounds) << " " << glm::to_string(node->MaxBounds) << ": " << node->TriIdx << "\n";
|
node->aabb = createAABB(vertices, triangles);
|
||||||
|
node->triangles.push_back(triangles[midIdx]);
|
||||||
|
|
||||||
printTree(node->LeftChild, depth + 1);
|
std::vector<Triangle> leftTriangles(triangles.begin(), triangles.begin() + midIdx);
|
||||||
printTree(node->RightChild, depth + 1);
|
std::vector<Triangle> rightTriangles(triangles.begin() + midIdx + 1, triangles.end());
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
node->left = buildKDTree(vertices, leftTriangles, depth + 1);
|
||||||
KDNode* buildNode(std::vector<uint32_t>& indicesToProcess, uint32_t startIdx, uint32_t endIdx, uint32_t depth) {
|
node->right = buildKDTree(vertices, rightTriangles, depth + 1);
|
||||||
if (startIdx >= endIdx || depth >= mDepthLimit) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (endIdx - startIdx == 1) {
|
return node;
|
||||||
return new KDNode(indicesToProcess[startIdx], getVertexBounds(mIndices[indicesToProcess[startIdx] * 3]), getVertexBounds(mIndices[indicesToProcess[startIdx] * 3]));
|
}
|
||||||
}
|
|
||||||
|
|
||||||
glm::vec3 minBounds(INFINITY), maxBounds(-INFINITY);
|
inline void intersectKDTree(KDNode* node, const glm::vec3& origin, const glm::vec3& direction, std::vector<Triangle>& hitCandidates) {
|
||||||
for (uint32_t i = startIdx; i < endIdx; ++i) {
|
if (!node)
|
||||||
const glm::vec3& v0 = getVertexBounds(mIndices[indicesToProcess[i] * 3]);
|
{
|
||||||
const glm::vec3& v1 = getVertexBounds(mIndices[indicesToProcess[i] * 3 + 1]);
|
return;
|
||||||
const glm::vec3& v2 = getVertexBounds(mIndices[indicesToProcess[i] * 3 + 2]);
|
}
|
||||||
minBounds = glm::min(minBounds, glm::min(v0, glm::min(v1, v2)));
|
|
||||||
maxBounds = glm::max(maxBounds, glm::max(v0, glm::max(v1, v2)));
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t axis = depth % 3;
|
float tNear = -std::numeric_limits<float>::max();
|
||||||
uint32_t median = partition(indicesToProcess, startIdx, endIdx, axis);
|
float tFar = std::numeric_limits<float>::max();
|
||||||
bool isPartitionValid = checkPartition(indicesToProcess, startIdx, endIdx, axis, median);
|
if (!intersectAABB(node->aabb, origin, direction, tNear, tFar))
|
||||||
if (!isPartitionValid) {
|
{
|
||||||
std::cout << "Partition failed!" << std::endl;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
KDNode* node = new KDNode(0, minBounds, maxBounds);
|
if (!node->left && !node->right)
|
||||||
|
{
|
||||||
|
hitCandidates.insert(hitCandidates.end(), node->triangles.begin(), node->triangles.end());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<uint32_t> leftIndices(indicesToProcess.begin() + startIdx, indicesToProcess.begin() + median);
|
intersectKDTree(node->left, origin, direction, hitCandidates);
|
||||||
std::vector<uint32_t> rightIndices(indicesToProcess.begin() + median, indicesToProcess.begin() + endIdx);
|
intersectKDTree(node->right, origin, direction, hitCandidates);
|
||||||
|
}
|
||||||
|
|
||||||
node->setLeftChild(buildNode(leftIndices, startIdx, median, depth + 1));
|
inline void deleteKDTree(KDNode* node)
|
||||||
node->setRightChild(buildNode(rightIndices, 0, endIdx - median, depth + 1));
|
{
|
||||||
|
if (node)
|
||||||
|
{
|
||||||
|
deleteKDTree(node->left);
|
||||||
|
deleteKDTree(node->right);
|
||||||
|
delete node;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
|
|
||||||
void intersect(const KDNode* node, const Ray* ray, std::vector<uint32_t>& outIndices) {
|
|
||||||
if (!node) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
//std::cout << "Checking node bounds: " << glm::to_string(node->MinBounds) << " " << glm::to_string(node->MaxBounds) << std::endl;
|
|
||||||
|
|
||||||
if (AABBIntersection(node->MinBounds, node->MaxBounds, ray)) {
|
|
||||||
//std::cout << "Ray intersects node, num tris: " << (node->LeftChild || node->RightChild ? -1 : 1) << std::endl;
|
|
||||||
if (node->LeftChild || node->RightChild) {
|
|
||||||
intersect(node->LeftChild, ray, outIndices);
|
|
||||||
intersect(node->RightChild, ray, outIndices);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
//std::cout << "Ray hit leaf node with triangle index: " << node->TriIdx << std::endl;
|
|
||||||
outIndices.push_back(node->TriIdx);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
//std::cout << "Ray does not intersect node" << std::endl;
|
|
||||||
}
|
|
||||||
//std::cout << std::endl;
|
|
||||||
//exit(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
glm::vec3 getVertexBounds(uint32_t index) const {
|
|
||||||
return { mVertices[index * 3], mVertices[index * 3 + 1], mVertices[index * 3 + 2] };
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: this could definately be more advanced, at the moment is is a split down the middle
|
|
||||||
uint32_t partition(std::vector<uint32_t>& indicesToProcess, uint32_t startIdx, uint32_t endIdx, uint32_t axis) {
|
|
||||||
uint32_t medianIdx = (startIdx + endIdx) / 2;
|
|
||||||
glm::vec3 pivot = getVertexBounds(mIndices[indicesToProcess[medianIdx] * 3]);
|
|
||||||
std::nth_element(indicesToProcess.begin() + startIdx, indicesToProcess.begin() + medianIdx, indicesToProcess.begin() + endIdx,
|
|
||||||
[this, &pivot, axis](uint32_t a, uint32_t b) { return getVertexBounds(mIndices[a * 3])[axis] < getVertexBounds(mIndices[b * 3])[axis]; });
|
|
||||||
return medianIdx;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool checkPartition(std::vector<uint32_t>& indicesToProcess, uint32_t startIdx, uint32_t endIdx, uint32_t axis, uint32_t median) {
|
|
||||||
for (uint32_t i = startIdx; i < median; ++i) {
|
|
||||||
if (getVertexBounds(mIndices[indicesToProcess[i] * 3])[axis] > getVertexBounds(mIndices[indicesToProcess[median] * 3])[axis]) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (uint32_t i = median + 1; i < endIdx; ++i) {
|
|
||||||
if (getVertexBounds(mIndices[indicesToProcess[i] * 3])[axis] < getVertexBounds(mIndices[indicesToProcess[median] * 3])[axis]) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
float* mVertices;
|
|
||||||
uint32_t* mIndices;
|
|
||||||
uint32_t mDepthLimit;
|
|
||||||
KDNode* mRoot;
|
|
||||||
};
|
|
||||||
|
|||||||
@@ -16,158 +16,166 @@ using namespace inferno;
|
|||||||
|
|
||||||
class HARTCPU : public HARTModule
|
class HARTCPU : public HARTModule
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
HARTCPU()
|
HARTCPU()
|
||||||
{
|
|
||||||
mMasterWorker = std::thread(&HARTCPU::intersectMasterWorker, this);
|
|
||||||
mLogModule = yolo::registerModule("hartcpu", "\u001b[35;1m");
|
|
||||||
}
|
|
||||||
|
|
||||||
~HARTCPU()
|
|
||||||
{
|
|
||||||
this->stop(true);
|
|
||||||
mMasterWorker.detach();
|
|
||||||
}
|
|
||||||
|
|
||||||
void submitTris(void* vert,
|
|
||||||
void* norm,
|
|
||||||
int vc,
|
|
||||||
void* indices,
|
|
||||||
int ic) override
|
|
||||||
{
|
|
||||||
std::lock_guard<std::mutex> lock(_mData);
|
|
||||||
|
|
||||||
mState = EModuleState::Build;
|
|
||||||
mVert = (float*)vert; mNorm = (float*)norm; mVc = vc; mIndices = (uint32_t*)indices; mIc = ic;
|
|
||||||
yolo::info(mLogModule, "Recieved {} verticies ({}) and {} indicies ({})", vc / 3, vert, ic / 3, indices);
|
|
||||||
|
|
||||||
std::vector<uint32_t> indicesToProcess(ic / 3);
|
|
||||||
for (uint32_t i = 0; i < ic / 3; ++i)
|
|
||||||
{
|
{
|
||||||
indicesToProcess[i] = i;
|
mMasterWorker = std::thread(&HARTCPU::intersectMasterWorker, this);
|
||||||
|
mLogModule = yolo::registerModule("hartcpu", "\u001b[35;1m");
|
||||||
|
rootNode = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
mKdTree = new KDTree(mVert, mIndices, indicesToProcess, 0, indicesToProcess.size() - 1, 10);
|
~HARTCPU()
|
||||||
mKdTree->printTree(mKdTree->getRoot(), 1);
|
|
||||||
yolo::info(mLogModule, "Accelerator ready..");
|
|
||||||
|
|
||||||
mState = EModuleState::Idle;
|
|
||||||
}
|
|
||||||
|
|
||||||
void updateTris() override {}
|
|
||||||
|
|
||||||
void start() override
|
|
||||||
{
|
|
||||||
std::lock_guard<std::mutex> signalLock(_mSignalMut);
|
|
||||||
mIsRunning = true;
|
|
||||||
mState = EModuleState::Trace;
|
|
||||||
_mSignalCv.notify_all();
|
|
||||||
|
|
||||||
yolo::info(mLogModule, "Signal master to start");
|
|
||||||
|
|
||||||
{
|
{
|
||||||
std::unique_lock<std::mutex> doneLock(_mDoneMut);
|
this->stop(true);
|
||||||
_mDoneCv.wait(doneLock, [this] { return mState == EModuleState::Idle; });
|
mMasterWorker.detach();
|
||||||
|
if (rootNode) {
|
||||||
|
deleteKDTree(rootNode);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void stop(bool interrupt) override
|
void submitTris(void* vert,
|
||||||
{
|
void* norm,
|
||||||
if (!interrupt)
|
int vc,
|
||||||
|
void* indices,
|
||||||
|
int ic) override
|
||||||
{
|
{
|
||||||
mIsRunning = false;
|
std::lock_guard<std::mutex> lock(_mData);
|
||||||
return;
|
|
||||||
}
|
|
||||||
// TODO: Find a way to force the thread to hault
|
|
||||||
}
|
|
||||||
|
|
||||||
void intersectMasterWorker()
|
mState = EModuleState::Build;
|
||||||
{
|
mVert = (float*)vert; mNorm = (float*)norm; mVc = vc; mIndices = (uint32_t*)indices; mIc = ic;
|
||||||
for (;;)
|
yolo::info(mLogModule, "Recieved {} verticies ({}) and {} indicies ({})", vc / 3, vert, ic / 3, indices);
|
||||||
{
|
|
||||||
std::unique_lock<std::mutex> lock(_mData);
|
std::vector<glm::vec3> vertices(mVc / 3);
|
||||||
if (!mIsRunning)
|
for (size_t i = 0; i < vertices.size(); ++i) {
|
||||||
{
|
vertices[i] = glm::vec3(mVert[i * 3], mVert[i * 3 + 1], mVert[i * 3 + 2]);
|
||||||
_mSignalCv.wait(lock, [this]{ return (mIsRunning || mState == EModuleState::Trace); });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mToTrace.size() == 0)
|
std::vector<Triangle> triangles(mIc / 3);
|
||||||
{
|
for (size_t i = 0; i < triangles.size(); ++i) {
|
||||||
lock.unlock();
|
triangles[i].indices[0] = mIndices[i * 3];
|
||||||
mState = EModuleState::Idle;
|
triangles[i].indices[1] = mIndices[i * 3 + 1];
|
||||||
_mDoneCv.notify_all();
|
triangles[i].indices[2] = mIndices[i * 3 + 2];
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rootNode = buildKDTree(vertices, triangles);
|
||||||
|
yolo::info(mLogModule, "Accelerator ready..");
|
||||||
|
|
||||||
|
mState = EModuleState::Idle;
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateTris() override {}
|
||||||
|
|
||||||
|
void start() override
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> signalLock(_mSignalMut);
|
||||||
|
mIsRunning = true;
|
||||||
mState = EModuleState::Trace;
|
mState = EModuleState::Trace;
|
||||||
|
_mSignalCv.notify_all();
|
||||||
|
|
||||||
Ray* ray = mToTrace.front();
|
yolo::info(mLogModule, "Signal master to start");
|
||||||
int bestIdx = -1;
|
|
||||||
glm::vec2 coords;
|
|
||||||
glm::vec2 bestTexcoord;
|
|
||||||
float bestDist = INFINITY;
|
|
||||||
float dist;
|
|
||||||
|
|
||||||
// Traverse the K-D tree to identify the set of triangles that may intersect the ray.
|
|
||||||
std::vector<uint32_t> candidateIndices;
|
|
||||||
mKdTree->intersect(ray, candidateIndices);
|
|
||||||
|
|
||||||
for (uint32_t idx : candidateIndices)
|
|
||||||
{
|
{
|
||||||
uint32_t ind1 = mIndices[idx * 3];
|
std::unique_lock<std::mutex> doneLock(_mDoneMut);
|
||||||
uint32_t ind2 = mIndices[idx * 3 + 1];
|
_mDoneCv.wait(doneLock, [this] { return mState == EModuleState::Idle; });
|
||||||
uint32_t ind3 = mIndices[idx * 3 + 2];
|
|
||||||
|
|
||||||
const glm::vec3 a = { mVert[ind1], mVert[ind1 + 1], mVert[ind1 + 2] };
|
|
||||||
const glm::vec3 b = { mVert[ind2], mVert[ind2 + 1], mVert[ind2 + 2] };
|
|
||||||
const glm::vec3 c = { mVert[ind3], mVert[ind3 + 1], mVert[ind3 + 2] };
|
|
||||||
|
|
||||||
// Perform intersection test...
|
|
||||||
if (!glm::intersectRayTriangle(ray->Origin, ray->Direction, a, b, c, coords, dist)) { continue; }
|
|
||||||
if (dist > bestDist || dist < 0.0f) { continue; }
|
|
||||||
|
|
||||||
bestIdx = idx;
|
|
||||||
bestDist = dist;
|
|
||||||
bestTexcoord = coords;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
HitInfo hit;
|
|
||||||
hit.Caller = ray;
|
|
||||||
// If no hit, we still need to inform the HHM
|
|
||||||
if (bestIdx < 0)
|
|
||||||
{
|
|
||||||
mToTrace.pop();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
hit.Distance = bestDist;
|
|
||||||
hit.UV = bestTexcoord;
|
|
||||||
|
|
||||||
Hit(mCtx, &hit);
|
|
||||||
|
|
||||||
mToTrace.pop();
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
void stop(bool interrupt) override
|
||||||
// Signaling Stuffs
|
{
|
||||||
std::atomic<bool> mIsRunning;
|
if (!interrupt)
|
||||||
std::thread mMasterWorker;
|
{
|
||||||
std::mutex _mSignalMut;
|
mIsRunning = false;
|
||||||
std::mutex _mDoneMut;
|
return;
|
||||||
std::condition_variable _mSignalCv;
|
}
|
||||||
std::condition_variable _mDoneCv;
|
// TODO: Find a way to force the thread to hault
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
void intersectMasterWorker()
|
||||||
// Scene Data
|
{
|
||||||
KDTree* mKdTree;
|
for (;;)
|
||||||
|
{
|
||||||
|
std::unique_lock<std::mutex> lock(_mData);
|
||||||
|
if (!mIsRunning)
|
||||||
|
{
|
||||||
|
_mSignalCv.wait(lock, [this]{ return (mIsRunning || mState == EModuleState::Trace); });
|
||||||
|
}
|
||||||
|
|
||||||
float* mVert;
|
if (mToTrace.size() == 0)
|
||||||
float* mNorm;
|
{
|
||||||
int mVc;
|
lock.unlock();
|
||||||
uint32_t* mIndices;
|
mState = EModuleState::Idle;
|
||||||
int mIc;
|
_mDoneCv.notify_all();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
mState = EModuleState::Trace;
|
||||||
|
|
||||||
uint8_t mLogModule;
|
Ray* ray = mToTrace.front();
|
||||||
|
int bestIdx = -1;
|
||||||
|
glm::vec2 coords;
|
||||||
|
glm::vec2 bestTexcoord;
|
||||||
|
float bestDist = INFINITY;
|
||||||
|
float dist;
|
||||||
|
// ...
|
||||||
|
// (Keep the existing implementation of intersectMasterWorker, but replace the KDTree intersection part)
|
||||||
|
|
||||||
|
std::vector<Triangle> candidateTriangles;
|
||||||
|
intersectKDTree(rootNode, ray->Origin, ray->Direction, candidateTriangles);
|
||||||
|
|
||||||
|
for (const Triangle& triangle : candidateTriangles)
|
||||||
|
{
|
||||||
|
uint32_t ind1 = triangle.indices[0];
|
||||||
|
uint32_t ind2 = triangle.indices[1];
|
||||||
|
uint32_t ind3 = triangle.indices[2];
|
||||||
|
|
||||||
|
const glm::vec3 a = { mVert[ind1 * 3], mVert[ind1 * 3 + 1], mVert[ind1 * 3 + 2] };
|
||||||
|
const glm::vec3 b = { mVert[ind2 * 3], mVert[ind2 * 3 + 1], mVert[ind2 * 3 + 2] };
|
||||||
|
const glm::vec3 c = { mVert[ind3 * 3], mVert[ind3 * 3 + 1], mVert[ind3 * 3 + 2] };
|
||||||
|
|
||||||
|
// Perform intersection test...
|
||||||
|
if (!glm::intersectRayTriangle(ray->Origin, ray->Direction, a, b, c, coords, dist)) { continue; }
|
||||||
|
if (dist > bestDist || dist < 0.0f) { continue; }
|
||||||
|
|
||||||
|
//bestIdx = ;
|
||||||
|
bestDist = dist;
|
||||||
|
bestTexcoord = coords;
|
||||||
|
}
|
||||||
|
|
||||||
|
HitInfo hit;
|
||||||
|
hit.Caller = ray;
|
||||||
|
// If no hit, we still need to inform the HHM
|
||||||
|
if (bestIdx < 0)
|
||||||
|
{
|
||||||
|
mToTrace.pop();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
hit.Distance = bestDist;
|
||||||
|
hit.UV = bestTexcoord;
|
||||||
|
|
||||||
|
Hit(mCtx, &hit);
|
||||||
|
|
||||||
|
mToTrace.pop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
// Signaling Stuffs
|
||||||
|
std::atomic<bool> mIsRunning;
|
||||||
|
std::thread mMasterWorker;
|
||||||
|
std::mutex _mSignalMut;
|
||||||
|
std::mutex _mDoneMut;
|
||||||
|
std::condition_variable _mSignalCv;
|
||||||
|
std::condition_variable _mDoneCv;
|
||||||
|
|
||||||
|
private:
|
||||||
|
KDNode* rootNode;
|
||||||
|
|
||||||
|
float* mVert;
|
||||||
|
float* mNorm;
|
||||||
|
int mVc;
|
||||||
|
uint32_t* mIndices;
|
||||||
|
int mIc;
|
||||||
|
|
||||||
|
uint8_t mLogModule;
|
||||||
};
|
};
|
||||||
|
|
||||||
HART_INTERFACE void* _GET()
|
HART_INTERFACE void* _GET()
|
||||||
@@ -185,10 +193,11 @@ HART_INTERFACE void* _CREDIT()
|
|||||||
{
|
{
|
||||||
return new ModuleCredit {
|
return new ModuleCredit {
|
||||||
.ModuleName = "HART_CPU",
|
.ModuleName = "HART_CPU",
|
||||||
.AuthorName = "Ben Kyd",
|
.AuthorName = "Ben Kyd",
|
||||||
.ModuleDesc = "Accelerating inferno raytracing with CPU",
|
.ModuleDesc = "Accelerating inferno raytracing with CPU",
|
||||||
.VersionMajor = 0,
|
.VersionMajor = 0,
|
||||||
.VersionMinor = 0,
|
.VersionMinor = 0,
|
||||||
.VersionBuild = 1,
|
.VersionBuild = 1,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ class HARTModule
|
|||||||
public:
|
public:
|
||||||
class HARTViz
|
class HARTViz
|
||||||
{
|
{
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class EModuleState : uint8_t
|
enum class EModuleState : uint8_t
|
||||||
|
|||||||
Reference in New Issue
Block a user