[Fix] Missing tris bug.

[Add] Do empty space cutoff in BIH tree builder.
This commit is contained in:
Rtch90 2018-03-17 17:13:42 +00:00
parent c0739f7abf
commit a9c2abdb71

View File

@ -10,6 +10,8 @@
#define MAX_LEAF_PRIMS 2
#define MAX_DEPTH 20
#define MAX_SPLITPOS_RETRIES 32
#define MIN_SPACE_CUTOFF 0.33
#define EPSILON 0.00001
#include <float.h>
#include <stdio.h>
@ -100,8 +102,8 @@ GeomTree::GeomTree(int numVerts, int numTris, float* vertices, int* indices) : m
m_aabb.max.x,
m_aabb.max.y,
m_aabb.max.z);
m_nodes = new BIHNode[numTris*2];
m_nodesAllocSize = numTris*2;
m_nodes = new BIHNode[numTris*4];
m_nodesAllocSize = numTris*4;
m_nodesAllocPos = 0;
m_triAllocPos = 0;
@ -133,6 +135,82 @@ void GeomTree::BihTreeGhBuild(BIHNode* a_node, Aabb& a_box, Aabb& a_splitBox, in
int s1count, s2count, splitAxis, attempt;
attempt = 0;
Aabb realAabb;
realAabb.min = vector3d(FLT_MAX, FLT_MAX, FLT_MAX);
realAabb.max = vector3d(-FLT_MAX, -FLT_MAX, -FLT_MAX);
/* Make actual objects aabb, to see if we can usefully cut off some empty space. */
for(int i = 0; i < a_prims; i++) {
vector3d v0 = vector3d(&m_vertices[3*m_indices[prim_lump[i]->triIdx]]);
vector3d v1 = vector3d(&m_vertices[3*m_indices[prim_lump[i]->triIdx+1]]);
vector3d v2 = vector3d(&m_vertices[3*m_indices[prim_lump[i]->triIdx+2]]);
realAabb.Update(v0);
realAabb.Update(v1);
realAabb.Update(v2);
}
#if 0
printf("Empty space: (%f,%f,%f), (%f,%f,%f)\n",
(realAabb.min - a_box.min).x,
(realAabb.min - a_box.min).y.
(realAabb.min - a_box.min).z,
(a_box.max - realAabb.max).x,
(a_box.max - realAabb.max).y,
(a_box.max - realAabb.max).z);
#endif
{
vector3d boxSize = a_box.max - a_box.min;
vector3d lowSpace = realAabb.min - a_box.min;
vector3d highSpace = a_box.max - realAabb.max;
/* Choose best. */
float bestCost = 0;
int axis = -1;
int isTop = false;
for(int i = 0; i < 3; i++) {
float cost = (lowSpace[i]+EPSILON) / boxSize[i];
if(cost > bestCost) {
bestCost = cost;
axis = i;
isTop = false;
}
cost = (highSpace[i]+EPSILON) / boxSize[i];
if(cost > bestCost) {
bestCost = cost;
axis = i;
isTop = true;
}
}
//if(axis != -1) printf("Best is axis %d on %s (cost %f%%)\n", axis, (isTop ? "top" : "botton"), bestCost*100);
/* Cut off whitespace. */
if((bestCost > MIN_SPACE_CUTOFF) && (bestCost < 1.0f)) {
printf("Clicing off %f%%\n", bestCost*100);
a_node->SetLeaf(false);
a_node->SetAxis(axis);
Aabb newAabb = a_box;
if(isTop) {
newAabb.max[axis] = realAabb.max[axis]+EPSILON;
a_node->SetSplitPos1(realAabb.max[axis]);
a_node->SetSplitPos2(newAabb.max[axis]);
Aabb splitBox = newAabb;
left->SetList(prim_lump[0]);
BihTreeGhBuild(left, newAabb, splitBox, a_depth+1, a_prims);
right->SetLeaf(true);
} else {
newAabb.min[axis] = realAabb.min[axis] - EPSILON;
a_node->SetSplitPos1(a_box.min[axis]);
a_node->SetSplitPos2(newAabb.min[axis]);
Aabb splitBox = newAabb;
right->SetList(prim_lump[0]);
BihTreeGhBuild(right, newAabb, splitBox, a_depth+1, a_prims);
left->SetLeaf(true);
}
return;
}
}
for(;;) {
splitAxis = 0;
vector3d splitBoxSize = a_splitBox.max - a_splitBox.min;
@ -223,7 +301,10 @@ void GeomTree::BihTreeGhBuild(BIHNode* a_node, Aabb& a_box, Aabb& a_splitBox, in
}
break;
}
//printf(prims total %d, left %d, right %d\n", a_prims, s1count, s2count);
/* Traversal algo can't handle completely flat cells. */
splitPos1 += EPSILON;
splitPos2 -= EPSILON;
a_node->SetLeaf(false);
a_node->SetAxis(splitAxis);
@ -369,7 +450,6 @@ pop_bstack:
}
}
#define EPSILON 0.00001f
void GeomTree::RayTriIntersect(const vector3f& origin, const vector3f& dir, int triIdx, isect_t* isect) {
const vector3f a(&m_vertices[3*m_indices[triIdx]]);
const vector3f b(&m_vertices[3*m_indices[triIdx+1]]);