You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
177 lines
4.0 KiB
177 lines
4.0 KiB
#pragma once
|
|
#include <vector>
|
|
#include <cassert>
|
|
|
|
template<typename T>
|
|
class Vec3 {
|
|
public:
|
|
Vec3(T a_, T b_, T c_) : a(a_), b(b_), c(c_) {}
|
|
Vec3() : a(0), b(0), c(0) {}
|
|
|
|
union { T x, a; };
|
|
union { T y, b; };
|
|
union { T z, c; };
|
|
|
|
T operator[](int i) const {
|
|
if (i == 0) {
|
|
return a;
|
|
} else if (i == 1) {
|
|
return b;
|
|
} else if (i == 2) {
|
|
return c;
|
|
}
|
|
return a;
|
|
}
|
|
|
|
T &operator[](int i) {
|
|
if (i == 0) {
|
|
return a;
|
|
} else if (i == 1) {
|
|
return b;
|
|
} else if (i == 2) {
|
|
return c;
|
|
}
|
|
return a;
|
|
}
|
|
|
|
Vec3 operator+(const Vec3 &other) const {
|
|
return {a + other.a, b + other.b, c + other.c};
|
|
}
|
|
|
|
Vec3 operator/(const float w) const {
|
|
return {a / w, b / w, c / w};
|
|
}
|
|
|
|
Vec3 operator-(const Vec3 &other) const {
|
|
return {a - other.a, b - other.b, c - other.c};
|
|
}
|
|
|
|
Vec3 operator*(const float &w) const {
|
|
return {a * w, b * w, c * w};
|
|
}
|
|
|
|
float length() const {
|
|
return sqrt(a * a + b * b + c * c);
|
|
}
|
|
|
|
Vec3 norm() const {
|
|
return *this / length();
|
|
}
|
|
|
|
Vec3 cross(const Vec3 &other) const {
|
|
return {b * other.c - c * other.b, c * other.a - a * other.c, a * other.b - b * other.a};
|
|
}
|
|
|
|
float dot(const Vec3 &other) const {
|
|
return a * other.a + b * other.b + c * other.c;
|
|
}
|
|
|
|
bool operator==(const Vec3& other) const {
|
|
return x == other.x && y == other.y && z == other.z;
|
|
}
|
|
};
|
|
|
|
// 为 Vec3 创建哈希函数
|
|
namespace std {
|
|
template<typename T>
|
|
struct hash<Vec3<T>> {
|
|
size_t operator()(const Vec3<T>& vec) const {
|
|
return hash<T>()(vec.x) ^ hash<T>()(vec.y) ^ hash<T>()(vec.z);
|
|
}
|
|
};
|
|
}
|
|
|
|
typedef Vec3<float> Vec3f;
|
|
typedef Vec3<unsigned int> Vec3u;
|
|
|
|
class AABB {
|
|
public:
|
|
Vec3f min = {std::numeric_limits<float>::max(), std::numeric_limits<float>::max(),
|
|
std::numeric_limits<float>::max()};
|
|
Vec3f max = {std::numeric_limits<float>::lowest(), std::numeric_limits<float>::lowest(),
|
|
std::numeric_limits<float>::lowest()};
|
|
Vec3f center() const {
|
|
return (min + max) / 2;
|
|
}
|
|
Vec3f size() const {
|
|
return max - min;
|
|
}
|
|
AABB operator+(const Vec3f& v) const {
|
|
return {min + v, max + v};
|
|
}
|
|
};
|
|
|
|
class Mesh {
|
|
public:
|
|
std::vector<Vec3f> vertices;
|
|
std::vector<Vec3u> faces;
|
|
// 获得指定面的 AABB
|
|
AABB getAABB(const std::vector<size_t>& faceIndices) const {
|
|
AABB aabb;
|
|
for (const size_t &idx: faceIndices) {
|
|
const Vec3u &face = faces[idx];
|
|
for (int i = 0; i < 3; ++i) {
|
|
const Vec3f &v = vertices[face[i]];
|
|
for (int j = 0; j < 3; ++j) {
|
|
aabb.min[j] = std::min(aabb.min[j], v[j]);
|
|
aabb.max[j] = std::max(aabb.max[j], v[j]);
|
|
}
|
|
}
|
|
}
|
|
return aabb;
|
|
}
|
|
AABB getAABB() const {
|
|
AABB aabb;
|
|
for (const Vec3f &v: vertices) {
|
|
for (int j = 0; j < 3; ++j) {
|
|
aabb.min[j] = std::min(aabb.min[j], v[j]);
|
|
aabb.max[j] = std::max(aabb.max[j], v[j]);
|
|
}
|
|
}
|
|
return aabb;
|
|
}
|
|
};
|
|
|
|
|
|
//class LineSegment {
|
|
//public:
|
|
// Vec3f start;
|
|
// Vec3f end;
|
|
//
|
|
// /**
|
|
// * @brief Construct a new Line Segment object
|
|
// * @param s start point
|
|
// * @param e end point
|
|
// * @param r radius
|
|
// */
|
|
// LineSegment(const Vec3f &s, const Vec3f &e, const float r = 0) : start(s), end(e) {
|
|
// length = (end - start).length();
|
|
// dir = (end - start).norm();
|
|
// }
|
|
//
|
|
// float getLength() const {
|
|
// return length;
|
|
// }
|
|
//
|
|
// Vec3f getDir() const {
|
|
// return dir;
|
|
// }
|
|
//
|
|
//private:
|
|
// float length;
|
|
// Vec3f dir;
|
|
//};
|
|
|
|
class Ray {
|
|
public:
|
|
Vec3f start;
|
|
Vec3f dir;
|
|
|
|
Ray(const Vec3f &s, const Vec3f &d) : start(s), dir(d) {
|
|
dir = dir.norm();
|
|
}
|
|
};
|
|
|
|
|
|
|
|
|
|
|