| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| |
| |
| |
| |
|
|
| #pragma once |
|
|
| #include <neural-graphics-primitives/common.h> |
| #include <neural-graphics-primitives/common_device.cuh> |
| #include <neural-graphics-primitives/triangle.cuh> |
|
|
| NGP_NAMESPACE_BEGIN |
|
|
| template <int N_POINTS> |
| NGP_HOST_DEVICE inline void project(Eigen::Vector3f points[N_POINTS], const Eigen::Vector3f& axis, float& min, float& max) { |
| min = std::numeric_limits<float>::infinity(); |
| max = -std::numeric_limits<float>::infinity(); |
|
|
| NGP_PRAGMA_UNROLL |
| for (uint32_t i = 0; i < N_POINTS; ++i) { |
| float val = axis.dot(points[i]); |
|
|
| if (val < min) { |
| min = val; |
| } |
|
|
| if (val > max) { |
| max = val; |
| } |
| } |
| } |
|
|
| struct BoundingBox { |
| NGP_HOST_DEVICE BoundingBox() {} |
|
|
| NGP_HOST_DEVICE BoundingBox(const Eigen::Vector3f& a, const Eigen::Vector3f& b) : min{a}, max{b} {} |
|
|
| NGP_HOST_DEVICE explicit BoundingBox(const Triangle& tri) { |
| min = max = tri.a; |
| enlarge(tri.b); |
| enlarge(tri.c); |
| } |
|
|
| BoundingBox(std::vector<Triangle>::iterator begin, std::vector<Triangle>::iterator end) { |
| min = max = begin->a; |
| for (auto it = begin; it != end; ++it) { |
| enlarge(*it); |
| } |
| } |
|
|
| NGP_HOST_DEVICE void enlarge(const BoundingBox& other) { |
| min = min.cwiseMin(other.min); |
| max = max.cwiseMax(other.max); |
| } |
|
|
| NGP_HOST_DEVICE void enlarge(const Triangle& tri) { |
| enlarge(tri.a); |
| enlarge(tri.b); |
| enlarge(tri.c); |
| } |
|
|
| NGP_HOST_DEVICE void enlarge(const Eigen::Vector3f& point) { |
| min = min.cwiseMin(point); |
| max = max.cwiseMax(point); |
| } |
|
|
| NGP_HOST_DEVICE void inflate(float amount) { |
| min -= Eigen::Vector3f::Constant(amount); |
| max += Eigen::Vector3f::Constant(amount); |
| } |
|
|
| NGP_HOST_DEVICE Eigen::Vector3f diag() const { |
| return max - min; |
| } |
|
|
| NGP_HOST_DEVICE Eigen::Vector3f relative_pos(const Eigen::Vector3f& pos) const { |
| return (pos - min).cwiseQuotient(diag()); |
| } |
|
|
| NGP_HOST_DEVICE Eigen::Vector3f center() const { |
| return 0.5f * (max + min); |
| } |
|
|
| NGP_HOST_DEVICE BoundingBox intersection(const BoundingBox& other) const { |
| BoundingBox result = *this; |
| result.min = result.min.cwiseMax(other.min); |
| result.max = result.max.cwiseMin(other.max); |
| return result; |
| } |
|
|
| NGP_HOST_DEVICE bool intersects(const BoundingBox& other) const { |
| return !intersection(other).is_empty(); |
| } |
|
|
| |
| |
| |
| |
| NGP_HOST_DEVICE bool intersects(const Triangle& triangle) const { |
| float triangle_min, triangle_max; |
| float box_min, box_max; |
|
|
| |
| Eigen::Vector3f box_normals[3] = { |
| Eigen::Vector3f{1.0f, 0.0f, 0.0f}, |
| Eigen::Vector3f{0.0f, 1.0f, 0.0f}, |
| Eigen::Vector3f{0.0f, 0.0f, 1.0f}, |
| }; |
|
|
| Eigen::Vector3f triangle_normal = triangle.normal(); |
| Eigen::Vector3f triangle_verts[3]; |
| triangle.get_vertices(triangle_verts); |
|
|
| for (int i = 0; i < 3; i++) { |
| project<3>(triangle_verts, box_normals[i], triangle_min, triangle_max); |
| if (triangle_max < min[i] || triangle_min > max[i]) { |
| return false; |
| } |
| } |
|
|
| Eigen::Vector3f verts[8]; |
| get_vertices(verts); |
|
|
| |
| float triangle_offset = triangle_normal.dot(triangle.a); |
| project<8>(verts, triangle_normal, box_min, box_max); |
| if (box_max < triangle_offset || box_min > triangle_offset) { |
| return false; |
| } |
|
|
| |
| Eigen::Vector3f edges[3] = { |
| triangle.a - triangle.b, |
| triangle.a - triangle.c, |
| triangle.b - triangle.c, |
| }; |
|
|
| for (int i = 0; i < 3; i++) { |
| for (int j = 0; j < 3; j++) { |
| |
| Eigen::Vector3f axis = edges[i].cross(box_normals[j]); |
| project<8>(verts, axis, box_min, box_max); |
| project<3>(triangle_verts, axis, triangle_min, triangle_max); |
| if (box_max < triangle_min || box_min > triangle_max) |
| return false; |
| } |
| } |
|
|
| |
| return true; |
| } |
|
|
| NGP_HOST_DEVICE Eigen::Vector2f ray_intersect(const Eigen::Vector3f& pos, const Eigen::Vector3f& dir) const { |
| float tmin = (min.x() - pos.x()) / dir.x(); |
| float tmax = (max.x() - pos.x()) / dir.x(); |
|
|
| if (tmin > tmax) { |
| tcnn::host_device_swap(tmin, tmax); |
| } |
|
|
| float tymin = (min.y() - pos.y()) / dir.y(); |
| float tymax = (max.y() - pos.y()) / dir.y(); |
|
|
| if (tymin > tymax) { |
| tcnn::host_device_swap(tymin, tymax); |
| } |
|
|
| if (tmin > tymax || tymin > tmax) { |
| return { std::numeric_limits<float>::max(), std::numeric_limits<float>::max() }; |
| } |
|
|
| if (tymin > tmin) { |
| tmin = tymin; |
| } |
|
|
| if (tymax < tmax) { |
| tmax = tymax; |
| } |
|
|
| float tzmin = (min.z() - pos.z()) / dir.z(); |
| float tzmax = (max.z() - pos.z()) / dir.z(); |
|
|
| if (tzmin > tzmax) { |
| tcnn::host_device_swap(tzmin, tzmax); |
| } |
|
|
| if (tmin > tzmax || tzmin > tmax) { |
| return { std::numeric_limits<float>::max(), std::numeric_limits<float>::max() }; |
| } |
|
|
| if (tzmin > tmin) { |
| tmin = tzmin; |
| } |
|
|
| if (tzmax < tmax) { |
| tmax = tzmax; |
| } |
|
|
| return { tmin, tmax }; |
| } |
|
|
| NGP_HOST_DEVICE bool is_empty() const { |
| return (max.array() < min.array()).any(); |
| } |
|
|
| NGP_HOST_DEVICE bool contains(const Eigen::Vector3f& p) const { |
| return |
| p.x() >= min.x() && p.x() <= max.x() && |
| p.y() >= min.y() && p.y() <= max.y() && |
| p.z() >= min.z() && p.z() <= max.z(); |
| } |
|
|
| |
| NGP_HOST_DEVICE float distance(const Eigen::Vector3f& p) const { |
| return sqrt(distance_sq(p)); |
| } |
|
|
| NGP_HOST_DEVICE float distance_sq(const Eigen::Vector3f& p) const { |
| return (min - p).cwiseMax(p - max).cwiseMax(0.0f).squaredNorm(); |
| } |
|
|
| NGP_HOST_DEVICE float signed_distance(const Eigen::Vector3f& p) const { |
| Eigen::Vector3f q = (p - min).cwiseAbs() - diag(); |
| return q.cwiseMax(0.0f).norm() + std::min(std::max(q.x(), std::max(q.y(), q.z())), 0.0f); |
| } |
|
|
| NGP_HOST_DEVICE void get_vertices(Eigen::Vector3f v[8]) const { |
| v[0] = {min.x(), min.y(), min.z()}; |
| v[1] = {min.x(), min.y(), max.z()}; |
| v[2] = {min.x(), max.y(), min.z()}; |
| v[3] = {min.x(), max.y(), max.z()}; |
| v[4] = {max.x(), min.y(), min.z()}; |
| v[5] = {max.x(), min.y(), max.z()}; |
| v[6] = {max.x(), max.y(), min.z()}; |
| v[7] = {max.x(), max.y(), max.z()}; |
| } |
|
|
| Eigen::Vector3f min = Eigen::Vector3f::Constant(std::numeric_limits<float>::infinity()); |
| Eigen::Vector3f max = Eigen::Vector3f::Constant(-std::numeric_limits<float>::infinity()); |
| }; |
|
|
| inline std::ostream& operator<<(std::ostream& os, const ngp::BoundingBox& bb) { |
| os << "["; |
| os << "min=[" << bb.min.x() << "," << bb.min.y() << "," << bb.min.z() << "], "; |
| os << "max=[" << bb.max.x() << "," << bb.max.y() << "," << bb.max.z() << "]"; |
| os << "]"; |
| return os; |
| } |
|
|
| NGP_NAMESPACE_END |
|
|