为什么边界框会以一种奇怪的方式出现在对象周围?
Why does the bounding box appear around the object in a strange way?
我正在为多边形模型创建一个基于 OpenGL 的光线追踪器。基本结构是将结果从片段着色器渲染到四边形。为了加速应用程序,使用了 BVH 树。因为 GLSL 中没有递归,所以我决定寻找其他方法来遍历边界框。 bvh 节点(包括框)和原始坐标被发送到片段着色器到着色器存储缓冲区中。
我正在使用中描述的基本思想:
上述解决方案使用links“用于跳过不需要评估的节点”。
有命中link:命中时跳转到哪个节点 有未命中link:未命中时跳转到哪个节点。
实际上,我没有使用 links 在框之间导航,因为我有一个完整的二叉树,这使得在不同深度之间导航更容易。但基本概念类似于上面的link。我按广度优先顺序存储节点。
不幸的是,当程序是 运行 时会出现奇怪的结果。我可以看到部分光线追踪的对象和边界框。边界框是灰色的,但是这个颜色应该是背景的颜色。
下图为当前状态。您应该会在灰色背景中看到一个圆锥体,但您会在其对象周围看到一个灰色边界框,而不是这个。
...以及它应该是什么样子(它是非 bvh-tree 版本)
这是我的片段着色器:
#version 460 core
layout(std140, binding=0) buffer primitives{
vec3 primitiveCoordinates[];
};
struct FlatBvhNode //I checked the data and it works fine.
{
// base aligment aligned offset
vec4 min; // 16 byte 0
vec4 max; // 16 byte 16
int order; // 4 byte 32
int isLeaf; // 4 byte 36
int createdEmpty;// 4 byte 40 //it is because of the complete binary tree
int leftOrRight; // 4 byte 44
vec4 indices[10];// 32 byte 48
};
layout(std430, binding=2) buffer TNodes
{
FlatBvhNode nodes[]; // the nodes of the tree in breadth-first order
};
out vec4 FragColor;
in vec3 p;
uniform vec3 wEye;
struct Light{
vec3 Le, La;
vec3 direction;
vec3 position;
};
uniform Light lights[];
struct Ray{
vec3 orig, dir;
};
struct Hit{
vec3 orig, dir, normal;
float t;
};
Hit rayTriangleIntersect(Ray ray, vec3 v0, vec3 v1, vec3 v2){
// This works well, so I don't include.
}
vec3 getCoordinatefromIndices(float index){
return primitiveCoordinates[int(index)];
}
Hit firstIntersect(Ray ray, int i){
Hit besthit;
besthit.t=-1;
for (int j=0;j<nodes[i].indices.length();j++){
vec3 TrianglePointA=getCoordinatefromIndices(nodes[i].indices[j].x);
vec3 TrianglePointB=getCoordinatefromIndices(nodes[i].indices[j].y);
vec3 TrianglePointC=getCoordinatefromIndices(nodes[i].indices[j].z);
Hit hit=rayTriangleIntersect(ray, TrianglePointA, TrianglePointB, TrianglePointC);
if (hit.t==-1){ continue; }
if (hit.t>0 && (besthit.t>hit.t || besthit.t<0)){
besthit=hit;
}
}
return besthit;
}
bool rayIntersectWithBox(const vec4 boxMin, const vec4 boxMax, const Ray r) {
vec3 invdir = 1.0 / r.dir.xyz;
const vec3 f = (boxMax.xyz - r.orig.xyz) * invdir;
const vec3 n = (boxMin.xyz - r.orig.xyz) * invdir;
const vec3 tmax = max(f, n);
const vec3 tmin = min(f, n);
const float t1 = min(tmax.x, min(tmax.y, tmax.z));
const float t0 = max(max(tmin.x, max(tmin.y, tmin.z)), 0.0f);
return t1 >= t0;
}
//This is where should be the problem.
//This is the method responsible for evaluating the bboxes.
//Instead of the links I can reach the childs with 2*i+1 or 2*i+2 and I can also get the parent
//with an inverse (int(ceil(i-2)/2))
Hit traverseBvhNode(Ray ray, FlatBvhNode node){
Hit result;
int next = 0;
for (int i = 0; i < nodes.length(); i++) {
if (i != next) { continue; }
bool hit = rayIntersectWithBox(nodes[i].min, nodes[i].max, ray);
if (nodes[i].createdEmpty==1){ hit=false;}
if (hit) {
if (nodes[i].isLeaf==1 && nodes[i].createdEmpty!=1){ return firstIntersect(ray, i);}
next = 2*i+1;
}
else if (!hit) {
if (nodes[i].leftOrRight==0){ next = i+1; }
else if (nodes[i].leftOrRight==1){ next = int(ceil(i-2)/2);
if (next==5){
result.t=-1;
return result;
}
}
}
}
return result;
}
Hit traverseBvhTree(Ray ray){
Hit hit;
if (rayIntersectWithBox(nodes[0].min, nodes[0].max, ray)){
return traverseBvhNode(ray, nodes[0]);
}
return hit;
}
vec3 trace(Ray ray){
vec3 color= vec3(0, 0, 0);
vec3 ka= vec3(0.135, 0.2225, 0.1575);
vec3 kd= vec3(0.54, 0.89, 0.63);
Hit hit=traverseBvhTree(ray);
if (hit.t==-1){ return lights[0].La; }
color=lights[0].La*ka;
// The below part is under contruction, but functions well.
Ray shadowRay;
shadowRay.orig=hit.orig+hit.normal*0.001f;
shadowRay.dir=lights[0].direction;
float cosTheta = dot(hit.normal, lights[0].direction)/(length(hit.normal)*length(lights[0].direction));
if (cosTheta > 0){
color+=lights[0].Le*cosTheta*kd;
float cosDelta=dot(hit.normal, normalize(-ray.dir + lights[0].direction));
if (cosDelta>0){
color=color+lights[0].Le*vec3(0.316228, 0.316228, 0.316228)*pow(0.1, cosDelta);
}
}
return color;
}
void main()
{
Ray ray;
ray.orig = wEye;
ray.dir = normalize(p - wEye);
FragColor = vec4(trace(ray), 1);
}
非常感谢任何帮助。
更新 1:
我使用了 Rabbid76 的建议并将 rayIntersectWithBox
方法的 return 语句从 return t1 >= t0;
修改为 return tmin.x < tmax.x && tmin.y < tmax.y && tmin.z < tmax.z;
正如您在快照中所见,没有可见的边界框,但对象仍然存在一些问题。
更新 2:
我更新了片段着色器的代码traverseBvhNode
。我确信该算法现在遍历了所有节点,因为我检查了 i==nodes.length()
是否为真。
不幸的是,window 中的结果仍然与我上次更新时的结果相同。
这里是traverseBvhNode
方法的修改:
为简单起见我把firstIntersection
方法的内容放到了traverseBvhNode
方法中。
此外,我将 return besthit
行移动到
traverseBvhNode方法,因为我之前要遍历所有节点
return与最佳路口相交。
我也修改了for循环为while循环,和while
我可以修改block中i
的值,而for不允许这种行动。
因为traverseBvhNode
方法中也有一些continue
指令,所以我把i++
指令放在了方法的开头。
这是更新后的代码:
Hit traverseBvhNode(Ray ray, FlatBvhNode node){
Hit besthit;
besthit.t=-1;
int db=0;
Hit hitreal;
int next = 0;
int i=-1;
while(i<=nodes.length()) {
i++;
if(i >nodes.length()){ break;}
if (i != next) { continue; }
bool hit = rayIntersectWithBox(nodes[i].min, nodes[i].max, ray);
if (nodes[i].createdEmpty==1){ hit=false; }
if (hit) {
if (nodes[i].isLeaf==1 && nodes[i].createdEmpty!=1){
db++;
for (int j=0;j<nodes[i].indices.length();j++){
if (mod(nodes[i].indices[j].x, 1)==0 && mod(nodes[i].indices[j].y, 1)==0 && mod(nodes[i].indices[j].z, 1)==0){
vec3 TrianglePointA=getCoordinatefromIndices(nodes[i].indices[j].x).xyz;
vec3 TrianglePointB=getCoordinatefromIndices(nodes[i].indices[j].y).xyz;
vec3 TrianglePointC=getCoordinatefromIndices(nodes[i].indices[j].z).xyz;
hitreal=rayTriangleIntersect(ray, TrianglePointA, TrianglePointB, TrianglePointC);
if (hitreal.t==-1){ continue; }
if (hitreal.t>0 && (besthit.t>hitreal.t || besthit.t<0)){
besthit=hitreal;
}
}
else{ continue;}
}
}
else{ next = 2*i+1;}
}
else {
if (nodes[i].leftOrRight==0){ next = i+1; }
else if (nodes[i].leftOrRight==1){
int id=int(ceil(i-2)/2);
FlatBvhNode parent=nodes[id];
while(parent.leftOrRight==1){
parent=nodes[int(ceil(parent.order-2)/2)];
}
next = parent.order+1;
i=next-1;
}
}
}
return besthit;
}
rayIntersectWithBox
中的算法好像有误
光线与盒子相交,如果最小值小于最大值,分别针对所有 3 个维度
此外,您还必须考虑光线的方向。这意味着您必须根据方向向量 (sign(invdir)
) 分量的 符号 来计算最小值和最大值。
我建议:
bool rayIntersectWithBox(const vec4 boxMin, const vec4 boxMax, const Ray r) {
vec3 invdir = 1.0 / r.dir.xyz;
const vec3 f = (boxMax.xyz - r.orig.xyz) * invdir;
const vec3 n = (boxMin.xyz - r.orig.xyz) * invdir;
const vec3 tmax = f * sign(invdir);
const vec3 tmin = n * sign(invdir);
return tmin.x < tmax.x && tmin.y < tmax.y && tmin.z < tmax.z;
}
所以边界体积树的遍历由于几个故障而流血此外,我还更新了rayIntersectionWithBox
方法(感谢飞向Rabbid76)
所以这里是bvh遍历方法和rayIntersectWithBox
。我还将 firstintersection
方法移到了遍历方法中。
我的解决方案类似于:,只是我没有在节点中使用预定义链接。我使用广度优先算法到达父节点或子节点。
bool rayIntersectWithBox(vec4 boxMin, vec4 boxMax, Ray r) {
vec3 invdir = 1.0 / r.dir.xyz;
vec3 f = (boxMax.xyz - r.orig.xyz) * invdir;
vec3 n = (boxMin.xyz - r.orig.xyz) * invdir;
vec3 tmax = f * sign(invdir);
vec3 tmin = n * sign(invdir);
return tmin.x < tmax.x && tmin.y < tmax.y && tmin.z < tmax.z;
}
Hit traverseBvhNode(Ray ray, FlatBvhNode node){
Hit besthit;
besthit.t=-1;
bool hit;
Hit hitreal;
int i=0;
while (i<=nodes.length()) {
if (nodes[i].isLeaf==1){
for (int j=0;j<nodes[i].indices.length();j++){
if (mod(nodes[i].indices[j].x, 1)==0 && mod(nodes[i].indices[j].y, 1)==0 && mod(nodes[i].indices[j].z, 1)==0){
vec3 TrianglePointA=getCoordinatefromIndices(nodes[i].indices[j].x).xyz;
vec3 TrianglePointB=getCoordinatefromIndices(nodes[i].indices[j].y).xyz;
vec3 TrianglePointC=getCoordinatefromIndices(nodes[i].indices[j].z).xyz;
hitreal=rayTriangleIntersect(ray, TrianglePointA, TrianglePointB, TrianglePointC);
if (hitreal.t==-1){ continue; }
if (hitreal.t>0 && (besthit.t>hitreal.t || besthit.t<0)){
besthit=hitreal;
}
}
}
if (nodes[i].leftOrRight==0){
i=i+1;
continue;
}
else if (nodes[i].leftOrRight==1){
int id=int(ceil(i-2)/2);
FlatBvhNode parent=nodes[id];
while (parent.leftOrRight==1){
parent=nodes[int(ceil(parent.order-2)/2)];
if (parent.order==0){
return besthit;
}
}
i = parent.order+1;
continue;
}
}
hit = rayIntersectWithBox(nodes[i].min, nodes[i].max, ray);
if (hit) {
if (nodes[i].isLeaf==0){
i=2*i+1;
continue;
}
}
else {
if (nodes[i].order==0){
break;
}
if (nodes[i].leftOrRight==0) {
i=i+1;
continue;
}
node-nál vagyunk.
else if (nodes[i].leftOrRight==1){
FlatBvhNode parent=nodes[int(ceil(i-2)/2)];
while (parent.leftOrRight==1){
parent=nodes[int(ceil(parent.order-2)/2)];
if (parent.order==0){
if (parent.order==0){
return besthit;
}
}
}
i = parent.order+1;
continue;
}
}
}
return besthit;
}
我正在为多边形模型创建一个基于 OpenGL 的光线追踪器。基本结构是将结果从片段着色器渲染到四边形。为了加速应用程序,使用了 BVH 树。因为 GLSL 中没有递归,所以我决定寻找其他方法来遍历边界框。 bvh 节点(包括框)和原始坐标被发送到片段着色器到着色器存储缓冲区中。
我正在使用中描述的基本思想:
上述解决方案使用links“用于跳过不需要评估的节点”。 有命中link:命中时跳转到哪个节点 有未命中link:未命中时跳转到哪个节点。
实际上,我没有使用 links 在框之间导航,因为我有一个完整的二叉树,这使得在不同深度之间导航更容易。但基本概念类似于上面的link。我按广度优先顺序存储节点。
不幸的是,当程序是 运行 时会出现奇怪的结果。我可以看到部分光线追踪的对象和边界框。边界框是灰色的,但是这个颜色应该是背景的颜色。
下图为当前状态。您应该会在灰色背景中看到一个圆锥体,但您会在其对象周围看到一个灰色边界框,而不是这个。
...以及它应该是什么样子(它是非 bvh-tree 版本)
这是我的片段着色器:
#version 460 core
layout(std140, binding=0) buffer primitives{
vec3 primitiveCoordinates[];
};
struct FlatBvhNode //I checked the data and it works fine.
{
// base aligment aligned offset
vec4 min; // 16 byte 0
vec4 max; // 16 byte 16
int order; // 4 byte 32
int isLeaf; // 4 byte 36
int createdEmpty;// 4 byte 40 //it is because of the complete binary tree
int leftOrRight; // 4 byte 44
vec4 indices[10];// 32 byte 48
};
layout(std430, binding=2) buffer TNodes
{
FlatBvhNode nodes[]; // the nodes of the tree in breadth-first order
};
out vec4 FragColor;
in vec3 p;
uniform vec3 wEye;
struct Light{
vec3 Le, La;
vec3 direction;
vec3 position;
};
uniform Light lights[];
struct Ray{
vec3 orig, dir;
};
struct Hit{
vec3 orig, dir, normal;
float t;
};
Hit rayTriangleIntersect(Ray ray, vec3 v0, vec3 v1, vec3 v2){
// This works well, so I don't include.
}
vec3 getCoordinatefromIndices(float index){
return primitiveCoordinates[int(index)];
}
Hit firstIntersect(Ray ray, int i){
Hit besthit;
besthit.t=-1;
for (int j=0;j<nodes[i].indices.length();j++){
vec3 TrianglePointA=getCoordinatefromIndices(nodes[i].indices[j].x);
vec3 TrianglePointB=getCoordinatefromIndices(nodes[i].indices[j].y);
vec3 TrianglePointC=getCoordinatefromIndices(nodes[i].indices[j].z);
Hit hit=rayTriangleIntersect(ray, TrianglePointA, TrianglePointB, TrianglePointC);
if (hit.t==-1){ continue; }
if (hit.t>0 && (besthit.t>hit.t || besthit.t<0)){
besthit=hit;
}
}
return besthit;
}
bool rayIntersectWithBox(const vec4 boxMin, const vec4 boxMax, const Ray r) {
vec3 invdir = 1.0 / r.dir.xyz;
const vec3 f = (boxMax.xyz - r.orig.xyz) * invdir;
const vec3 n = (boxMin.xyz - r.orig.xyz) * invdir;
const vec3 tmax = max(f, n);
const vec3 tmin = min(f, n);
const float t1 = min(tmax.x, min(tmax.y, tmax.z));
const float t0 = max(max(tmin.x, max(tmin.y, tmin.z)), 0.0f);
return t1 >= t0;
}
//This is where should be the problem.
//This is the method responsible for evaluating the bboxes.
//Instead of the links I can reach the childs with 2*i+1 or 2*i+2 and I can also get the parent
//with an inverse (int(ceil(i-2)/2))
Hit traverseBvhNode(Ray ray, FlatBvhNode node){
Hit result;
int next = 0;
for (int i = 0; i < nodes.length(); i++) {
if (i != next) { continue; }
bool hit = rayIntersectWithBox(nodes[i].min, nodes[i].max, ray);
if (nodes[i].createdEmpty==1){ hit=false;}
if (hit) {
if (nodes[i].isLeaf==1 && nodes[i].createdEmpty!=1){ return firstIntersect(ray, i);}
next = 2*i+1;
}
else if (!hit) {
if (nodes[i].leftOrRight==0){ next = i+1; }
else if (nodes[i].leftOrRight==1){ next = int(ceil(i-2)/2);
if (next==5){
result.t=-1;
return result;
}
}
}
}
return result;
}
Hit traverseBvhTree(Ray ray){
Hit hit;
if (rayIntersectWithBox(nodes[0].min, nodes[0].max, ray)){
return traverseBvhNode(ray, nodes[0]);
}
return hit;
}
vec3 trace(Ray ray){
vec3 color= vec3(0, 0, 0);
vec3 ka= vec3(0.135, 0.2225, 0.1575);
vec3 kd= vec3(0.54, 0.89, 0.63);
Hit hit=traverseBvhTree(ray);
if (hit.t==-1){ return lights[0].La; }
color=lights[0].La*ka;
// The below part is under contruction, but functions well.
Ray shadowRay;
shadowRay.orig=hit.orig+hit.normal*0.001f;
shadowRay.dir=lights[0].direction;
float cosTheta = dot(hit.normal, lights[0].direction)/(length(hit.normal)*length(lights[0].direction));
if (cosTheta > 0){
color+=lights[0].Le*cosTheta*kd;
float cosDelta=dot(hit.normal, normalize(-ray.dir + lights[0].direction));
if (cosDelta>0){
color=color+lights[0].Le*vec3(0.316228, 0.316228, 0.316228)*pow(0.1, cosDelta);
}
}
return color;
}
void main()
{
Ray ray;
ray.orig = wEye;
ray.dir = normalize(p - wEye);
FragColor = vec4(trace(ray), 1);
}
非常感谢任何帮助。
更新 1:
我使用了 Rabbid76 的建议并将 rayIntersectWithBox
方法的 return 语句从 return t1 >= t0;
修改为 return tmin.x < tmax.x && tmin.y < tmax.y && tmin.z < tmax.z;
正如您在快照中所见,没有可见的边界框,但对象仍然存在一些问题。
更新 2:
我更新了片段着色器的代码traverseBvhNode
。我确信该算法现在遍历了所有节点,因为我检查了 i==nodes.length()
是否为真。
不幸的是,window 中的结果仍然与我上次更新时的结果相同。
这里是traverseBvhNode
方法的修改:
为简单起见我把
firstIntersection
方法的内容放到了traverseBvhNode
方法中。此外,我将
return besthit
行移动到 traverseBvhNode方法,因为我之前要遍历所有节点 return与最佳路口相交。我也修改了for循环为while循环,和
while
我可以修改block中i
的值,而for不允许这种行动。因为
traverseBvhNode
方法中也有一些continue
指令,所以我把i++
指令放在了方法的开头。
这是更新后的代码:
Hit traverseBvhNode(Ray ray, FlatBvhNode node){
Hit besthit;
besthit.t=-1;
int db=0;
Hit hitreal;
int next = 0;
int i=-1;
while(i<=nodes.length()) {
i++;
if(i >nodes.length()){ break;}
if (i != next) { continue; }
bool hit = rayIntersectWithBox(nodes[i].min, nodes[i].max, ray);
if (nodes[i].createdEmpty==1){ hit=false; }
if (hit) {
if (nodes[i].isLeaf==1 && nodes[i].createdEmpty!=1){
db++;
for (int j=0;j<nodes[i].indices.length();j++){
if (mod(nodes[i].indices[j].x, 1)==0 && mod(nodes[i].indices[j].y, 1)==0 && mod(nodes[i].indices[j].z, 1)==0){
vec3 TrianglePointA=getCoordinatefromIndices(nodes[i].indices[j].x).xyz;
vec3 TrianglePointB=getCoordinatefromIndices(nodes[i].indices[j].y).xyz;
vec3 TrianglePointC=getCoordinatefromIndices(nodes[i].indices[j].z).xyz;
hitreal=rayTriangleIntersect(ray, TrianglePointA, TrianglePointB, TrianglePointC);
if (hitreal.t==-1){ continue; }
if (hitreal.t>0 && (besthit.t>hitreal.t || besthit.t<0)){
besthit=hitreal;
}
}
else{ continue;}
}
}
else{ next = 2*i+1;}
}
else {
if (nodes[i].leftOrRight==0){ next = i+1; }
else if (nodes[i].leftOrRight==1){
int id=int(ceil(i-2)/2);
FlatBvhNode parent=nodes[id];
while(parent.leftOrRight==1){
parent=nodes[int(ceil(parent.order-2)/2)];
}
next = parent.order+1;
i=next-1;
}
}
}
return besthit;
}
rayIntersectWithBox
中的算法好像有误
光线与盒子相交,如果最小值小于最大值,分别针对所有 3 个维度
此外,您还必须考虑光线的方向。这意味着您必须根据方向向量 (sign(invdir)
) 分量的 符号 来计算最小值和最大值。
我建议:
bool rayIntersectWithBox(const vec4 boxMin, const vec4 boxMax, const Ray r) {
vec3 invdir = 1.0 / r.dir.xyz;
const vec3 f = (boxMax.xyz - r.orig.xyz) * invdir;
const vec3 n = (boxMin.xyz - r.orig.xyz) * invdir;
const vec3 tmax = f * sign(invdir);
const vec3 tmin = n * sign(invdir);
return tmin.x < tmax.x && tmin.y < tmax.y && tmin.z < tmax.z;
}
所以边界体积树的遍历由于几个故障而流血此外,我还更新了rayIntersectionWithBox
方法(感谢飞向Rabbid76)
所以这里是bvh遍历方法和rayIntersectWithBox
。我还将 firstintersection
方法移到了遍历方法中。
我的解决方案类似于:
bool rayIntersectWithBox(vec4 boxMin, vec4 boxMax, Ray r) {
vec3 invdir = 1.0 / r.dir.xyz;
vec3 f = (boxMax.xyz - r.orig.xyz) * invdir;
vec3 n = (boxMin.xyz - r.orig.xyz) * invdir;
vec3 tmax = f * sign(invdir);
vec3 tmin = n * sign(invdir);
return tmin.x < tmax.x && tmin.y < tmax.y && tmin.z < tmax.z;
}
Hit traverseBvhNode(Ray ray, FlatBvhNode node){
Hit besthit;
besthit.t=-1;
bool hit;
Hit hitreal;
int i=0;
while (i<=nodes.length()) {
if (nodes[i].isLeaf==1){
for (int j=0;j<nodes[i].indices.length();j++){
if (mod(nodes[i].indices[j].x, 1)==0 && mod(nodes[i].indices[j].y, 1)==0 && mod(nodes[i].indices[j].z, 1)==0){
vec3 TrianglePointA=getCoordinatefromIndices(nodes[i].indices[j].x).xyz;
vec3 TrianglePointB=getCoordinatefromIndices(nodes[i].indices[j].y).xyz;
vec3 TrianglePointC=getCoordinatefromIndices(nodes[i].indices[j].z).xyz;
hitreal=rayTriangleIntersect(ray, TrianglePointA, TrianglePointB, TrianglePointC);
if (hitreal.t==-1){ continue; }
if (hitreal.t>0 && (besthit.t>hitreal.t || besthit.t<0)){
besthit=hitreal;
}
}
}
if (nodes[i].leftOrRight==0){
i=i+1;
continue;
}
else if (nodes[i].leftOrRight==1){
int id=int(ceil(i-2)/2);
FlatBvhNode parent=nodes[id];
while (parent.leftOrRight==1){
parent=nodes[int(ceil(parent.order-2)/2)];
if (parent.order==0){
return besthit;
}
}
i = parent.order+1;
continue;
}
}
hit = rayIntersectWithBox(nodes[i].min, nodes[i].max, ray);
if (hit) {
if (nodes[i].isLeaf==0){
i=2*i+1;
continue;
}
}
else {
if (nodes[i].order==0){
break;
}
if (nodes[i].leftOrRight==0) {
i=i+1;
continue;
}
node-nál vagyunk.
else if (nodes[i].leftOrRight==1){
FlatBvhNode parent=nodes[int(ceil(i-2)/2)];
while (parent.leftOrRight==1){
parent=nodes[int(ceil(parent.order-2)/2)];
if (parent.order==0){
if (parent.order==0){
return besthit;
}
}
}
i = parent.order+1;
continue;
}
}
}
return besthit;
}