【UE4】GAMES101 图形学作业6:通过BVH划分算法加速求交
最编程
2024-08-14 11:46:10
...
/GAMES101/Source/GAMES101/Assignment6
├─ Hw6_Main.cpp
├─ Hw6_Main.h
├─ BVHAccel.cpp -
├─ BVHAccel.h
├─ Hw6_MeshTriangle.cpp
├─ Hw6_MeshTriangle.h
├─ Bounds3.h
├─ Hw6_Global.h
└─ ObjectInterface.h
class AHw6_Main : public AActor
入口和渲染void InitialScene(); //初始化场景组件
void buildBVHTree(); //构建 BVH 树
Intersection intersect(const Ray& ray) const; //求交
void Render(); //渲染入口,计算光线属性,更新贴图
FVector castRay(const Ray &ray, int depth); //光照计算
FVector reflect(const FVector& I, const FVector& N); //反射
FVector refract(const FVector& I, const FVector& N, const float& ior); //折射
float fresnel(const FVector& I, const FVector& N, const float& ior); //菲涅尔
void CreateTexture(); //贴图相关
class UBVHBuildNode : public UObject
BVH 节点Bounds3 bounds; //区域范围
UBVHBuildNode* left; //左节点
UBVHBuildNode* right; //右节点
TScriptInterface<IObjectInterface> object; //区域内的物体
class UBVHAccel : public UObject
BVH 加速树//初始化
void Init(TArray<TScriptInterface<IObjectInterface>> p, int maxPrimsInNode = 1, SplitMethod splitMethod = SplitMethod::NAIVE, bool _bDraw = false);
Intersection Intersect(const Ray& ray) const; //求交,本质还是调用 getIntersection
Intersection getIntersection(UBVHBuildNode* node, const Ray& ray)const; //二叉树搜索求交
UBVHBuildNode* recursiveBuild(TArray<TScriptInterface<IObjectInterface>> objects); 构建节点,可递归
UPROPERTY()
UBVHBuildNode* root;
UPROPERTY()
TArray<TScriptInterface<IObjectInterface>> primitives;
bool IntersectP(const Ray& ray) const; //无用
class Bounds3
表示包围盒空间范围的类FVector pMin, pMax; // two points to specify the bounding box
Bounds3() //三种构造方法
Bounds3(const FVector p) : pMin(p), pMax(p) {}
Bounds3(const FVector p1, const FVector p2)
FVector Diagonal() const { return pMax - pMin; } //对角线向量
int maxExtent() const // 最大轴分量,0、1、2分别代表 X、Y、Z 轴,便于按最长划分空间
double SurfaceArea() const // 表面积,暂时无用
FVector Centroid() { return 0.5 * pMin + 0.5 * pMax; } // 中心点位置
bool Overlaps(const Bounds3& b1, const Bounds3& b2) // 两空间是否重叠,暂时无用
bool Inside(const FVector& p, const Bounds3& b) // 点是否在空间内
inline const FVector& operator[](int i) const // 取pMin pMax
void Union(const Bounds3& b2) //求空间并集
void Union(const FVector& p)
bool IntersectP(const Ray& ray, const FVector& invDir, const FVector& dirisNeg) const //判断光线是否通过空间包围盒
void Draw(const UObject* worldContex, FLinearColor color, float time = 0.02f, float thickness = 1.5f)
IObjectInterface
接口UINTERFACE(MinimalAPI)
class UObjectInterface : public UInterface
class GAMES101_API IObjectInterface
{
GENERATED_BODY()
public:
virtual bool intersect(const Ray& ray) = 0;
virtual bool intersect(const Ray& ray, float&, uint32_t&) const = 0;
virtual Intersection getIntersection(Ray _ray) = 0;
virtual void getSurfaceProperties(const FVector&, const FVector&, const uint32_t&, const FVector2D&, FVector&, FVector2D&) const = 0;
virtual FVector evalDiffuseColor(const FVector2D&) const = 0;
virtual Bounds3 getBounds() const = 0;
};
class UHw6_Triangle : public UObject, public IObjectInterface
三角面FVector v0, v1, v2; // vertices A, B ,C , counter-clockwise order
FVector e1, e2; // 2 edges v1-v0, v2-v0;
FVector t0, t1, t2; // texture coords
FVector normal;
Material* m;
Bounds3 bounding_box;
UHw6_Triangle() {}
void Init(FVector _v0, FVector _v1, FVector _v2, Material* _m = nullptr) //初始化顶点位置,计算法线(ue4坐标轴需要换下位置)、包围盒
Intersection getIntersection(Ray ray) override; // 求交,重点
void getSurfaceProperties(
const FVector& P, const FVector& I,
const uint32_t& index, const FVector2D& uv,
FVector& N, FVector2D& st) const override { N = normal; };
FVector evalDiffuseColor(const FVector2D&) const override {return FVector(0.5, 0.5, 0.5);}
Bounds3 getBounds() const override { return bounding_box; }
bool intersect(const Ray& ray) override{ return true; }
bool intersect(const Ray& ray, float& tnear, uint32_t& index) const override { return true; }
class AHw6_MeshTriangle : public AActor, public IObjectInterface
网格物体Bounds3 bounding_box;
Material* m;
UPROPERTY()
TArray<FVector> vertices;
UPROPERTY()
TArray<uint32> vertexIndex;
UPROPERTY()
TArray<FVector2D> stCoordinates;
UPROPERTY()
TArray<TScriptInterface<IObjectInterface>> triangles;
UPROPERTY()
UBVHAccel* bvhTree;
UPROPERTY(VisibleAnywhere)
UStaticMeshComponent* meshComp;
void getStaticMeshData();
//将 mesh 拆分成三角面构造 BVH Tree
void buildBVHTree();
// 判断光线是否和三角面相交
bool rayTriangleIntersect(const FVector& v0, const FVector& v1, const FVector& v2,
const FVector& orig, const FVector& dir, float& tnear, float& u, float& v) const;
// 判断是否相交
bool intersect(const Ray& ray, float& tnear, uint32_t& index) const override;
bool intersect(const Ray& ray) override { return true; }
// 获取空间区域
Bounds3 getBounds() const override { return bounding_box; }
// 获取表面信息
void getSurfaceProperties(
const FVector& P, const FVector& I,
const uint32_t& index, const FVector2D& uv,
FVector& N, FVector2D& st) const override;
// 获取点对应的颜色
FVector evalDiffuseColor(const FVector2D& st) const override;
// 获取相交信息
Intersection getIntersection(Ray ray) override;
Hw6_Global.h
全局设置