--- /dev/null
+#include <stdlib.h>
+#include <float.h>
+#include "bvh.h"
+
+int build_bvh_sah(struct bvhnode *tree)
+{
+ int i, j;
+ float sarea;
+
+ if(tree->num_faces < 5 || tree->left || tree->right) return 0;
+
+ dx = tree->aabb.vmax.x - tree->aabb.vmin.x;
+ dy = tree->aabb.vmax.y - tree->aabb.vmin.y;
+ dz = tree->aabb.vmax.z - tree->aabb.vmin.z;
+
+ if((sarea = surf_area(dx, dy, dz)) <= 0.0f) return 0;
+
+ tree->axis = dx > dy ? (dx > dz ? dx : dz) : (dy > dz ? dy : dz);
+
+ /* TODO */
+}
+
+void free_bvh_tree(struct bvhnode *tree)
+{
+ free(tree->faces);
+ free_bvh_tree(tree->left);
+ free_bvh_tree(tree->right);
+ free(tree);
+}
+
+int ray_bvhnode(cgm_ray *ray, struct bvhnode *bn, float tmax, struct rayhit *hit)
+{
+ int i, res = 0;
+ struct rayhit hit0;
+
+ if(!ray_aabox_any(ray, &bn->aabb, tmax)) {
+ return 0;
+ }
+
+ if(!hit) {
+ for(i=0; i<bn->num_faces; i++) {
+ if(ray_triangle(ray, bn->faces + i, tmax, 0)) {
+ return 1;
+ }
+ }
+ return 0;
+ }
+
+ hit0.t = FLT_MAX;
+ for(i=0; i<bn->num_faces; i++) {
+ if(ray_triangle(ray, bn->faces + i, tmax, hit) && hit->t < hit0.t) {
+ hit0 = *hit;
+ res = 1;
+ }
+ }
+ *hit = hit0;
+ return res;
+}
--- /dev/null
+#ifndef BVH_H_
+#define BVH_H_
+
+#include "geom.h"
+
+struct bvhnode {
+ struct aabox aabb;
+ int axis;
+
+ struct triangle *faces;
+ int num_faces, max_faces;
+
+ struct bvhnode *left, *right;
+};
+
+/* build_bvh* needs to be called with a pointer to a single-node tree,
+ * containing all the faces, left/right as null, and a pre-computed aabb
+ */
+int build_bvh_sah(struct bvhnode *tree);
+void free_bvh_tree(struct bvhnode *tree);
+
+int ray_bvhnode(cgm_ray *ray, struct bvhnode *bn, float tmax, struct rayhit *hit);
+
+#endif /* BVH_H_ */
#include <float.h>
#include "geom.h"
-void free_bvh_tree(struct bvhnode *tree)
-{
- struct bvhnode *node, *tmp;
-
- free(tree->faces);
-
- free_bvh_tree(tree->left);
- free_bvh_tree(tree->right);
- free(tree);
-}
-
int ray_triangle(cgm_ray *ray, struct triangle *tri, float tmax, struct rayhit *hit)
{
float t, ndotdir;
return 1;
}
-int ray_bvhnode(cgm_ray *ray, struct bvhnode *bn, float tmax, struct rayhit *hit)
+void aabox_union(struct aabox *res, struct aabox *a, struct aabox *b)
{
- int i, res = 0;
- struct rayhit hit0;
+ res->vmin.x = a->vmin.x < b->vmin.x ? a->vmin.x : b->vmin.x;
+ res->vmax.x = a->vmax.x > b->vmax.x ? a->vmax.x : b->vmax.x;
+ res->vmin.y = a->vmin.y < b->vmin.y ? a->vmin.y : b->vmin.y;
+ res->vmax.y = a->vmax.y > b->vmax.y ? a->vmax.y : b->vmax.y;
+ res->vmin.z = a->vmin.z < b->vmin.z ? a->vmin.z : b->vmin.z;
+ res->vmax.z = a->vmax.z > b->vmax.z ? a->vmax.z : b->vmax.z;
+}
- if(!ray_aabox_any(ray, &bn->aabb, tmax)) {
- return 0;
- }
+float aabox_surf_area(struct aabox *box)
+{
+ float dx, dy, dz;
- if(!hit) {
- for(i=0; i<bn->num_faces; i++) {
- if(ray_triangle(ray, bn->faces + i, tmax, 0)) {
- return 1;
- }
- }
- return 0;
- }
+ dx = box->vmax.x - box->vmin.x;
+ dy = box->vmax.y - box->vmin.y;
+ dz = box->vmax.z - box->vmin.z;
- hit0.t = FLT_MAX;
- for(i=0; i<bn->num_faces; i++) {
- if(ray_triangle(ray, bn->faces + i, tmax, hit) && hit->t < hit0.t) {
- hit0 = *hit;
- res = 1;
- }
+ return surf_area(dx, dy, dz);
+}
+
+float surf_area(float dx, float dy, float dz)
+{
+ if(dx <= 0 || dy <= 0 || dz <= 0) {
+ return 0.0f;
}
- *hit = hit0;
- return res;
+ return (dx * dy + dx * dz + dy * dz) * 2.0f;
}
cgm_vec3 vmin, vmax;
};
-struct bvhnode {
- struct aabox aabb;
-
- struct triangle *faces;
- int num_faces;
-
- struct bvhnode *left, *right;
-};
-
struct rayhit {
float t;
struct vertex v;
struct material *mtl;
};
-void free_bvh_tree(struct bvhnode *tree);
-
int ray_triangle(cgm_ray *ray, struct triangle *tri, float tmax, struct rayhit *hit);
int ray_aabox_any(cgm_ray *ray, struct aabox *box, float tmax);
-int ray_bvhnode(cgm_ray *ray, struct bvhnode *bn, float tmax, struct rayhit *hit);
+
+void aabox_union(struct aabox *res, struct aabox *a, struct aabox *b);
+float aabox_surf_area(struct aabox *box);
+float surf_area(float dx, float dy, float dz);
#endif /* GEOM_H_ */
#define LEVEL_H_
#include "rt.h"
-#include "geom.h"
+#include "bvh.h"
struct level {
struct bvhnode *st_root;