void ORRKdTree::extendTreeByOneLevel(char* extdir) { int i, newaxis, dim = this->getDimension(); Box newbox(dim); KdTreeNode *newroot = NULL, *newchild = NULL; double boxsize; for ( i = 0 ; i < dim ; ++i ) { newaxis = mRoot->getPreviousAxis(); newbox.copyfrom(mRoot->getSpace()); boxsize = newbox.getDiameter(newaxis); if ( extdir[newaxis] == -1 ) { // Fix the box of the new root and create the root. Extend the lower bound of the box newbox.mIntervals[newaxis][0] -= boxsize; newroot = new KdTreeNode(newaxis, NULL/*no parent*/, newbox, NULL); // Fix the box of the new child and create the new child newbox.mIntervals[newaxis][1] = mRoot->getLowerBoxBound(newaxis); newchild = new KdTreeNode(mRoot->getAxis(), newroot/*the parent*/, newbox, NULL); // Now fix the children of the new root newroot->setChildren(newchild, mRoot); } else if ( extdir[newaxis] == 1 ) { // Fix the box of the new root and create the root. Extend the upper bound of the box newbox.mIntervals[newaxis][1] += boxsize; newroot = new KdTreeNode(newaxis, NULL/*no parent*/, newbox, NULL); // Fix the box of the new child and create the new child newbox.mIntervals[newaxis][0] = mRoot->getUpperBoxBound(newaxis); newchild = new KdTreeNode(mRoot->getAxis(), newroot/*the parent*/, newbox, NULL); // Now fix the children of the new root newroot->setChildren(mRoot, newchild); } else { fprintf(stderr, "ERROR in 'ORRKdTree::%s()': extension direction for the %i-th axis is %i! Can not extend the tree!\n", __func__, newaxis, extdir[newaxis]); fflush(stdout); return; } // Set the new root as the parent of the old one mRoot->setParent(newroot); // Save the new root mRoot = newroot; } // Now we have one level more ++mNumOfTreeLevels; }
void dumpKdTreeInfo( KdTree* tree) { std::ofstream out("./output/kdtree.txt"); if(! out.is_open() ) { cerr<<"Cannot open file kdtree.txt"<<endl; return; } if( !tree ) { cerr<<"Tree is not initialized"<<endl; return; } KdTreeNode* root = tree->getRoot(); AABB extends = root->getAABB(); out<<"Extends: "<<endl<<extends.getPos().x<<" "<<extends.getPos().y<<" " <<extends.getPos().z<<endl; out<<(extends.getPos()+extends.getSize()).x<<" " <<(extends.getPos()+extends.getSize()).y<<" " <<(extends.getPos()+extends.getSize()).z<<endl; dumpKdTreeInfoLeaf( root, out, 0 ); }
void ireon::kd_tree::KdTree<T>::subdivide( KdTreeNode<T>* node, const aabb& box, int depth, int a_Prims ) { // recycle used split list nodes //add sPool_ at end sList_ if (sList_) { SplitList* list = sList_; while (list->next) list = list->next; list->next = sPool_; sPool_ = sList_, sList_ = 0; } // determine split axis Vector3 s = box.getSize(); if ((s.x >= s.y) && (s.x >= s.z)) node->setAxis( 0 ); else if ((s.y >= s.x) && (s.y >= s.z)) node->setAxis( 1 ); int axis = node->getAxis(); // make a list of the split position candidates ObjectList<T>* l = node->getList(); real p1, p2; real pos1 = box.getPos().val[axis]; real pos2 = box.getPos().val[axis] + box.getSize().val[axis]; bool* pright = new bool[a_Prims]; float* eleft = new float[a_Prims], *eright = new float[a_Prims]; T** parray = new T*[a_Prims]; real etleft, etright; int aidx = 0; while (l) { T* p = parray[aidx] = l->getPrimitive(); pright[aidx] = true; etleft = eleft[aidx]; etright = eright[aidx]; p->calculateRange( etleft, etright, axis ); eleft[aidx] = (float)etleft; eright[aidx] = (float)etright; aidx++; for ( int i = 0; i < 3; i++ ) { p1 = (float)p->vertice( i )->cell[axis]; if ((p1 >= pos1) && (p1 <= pos2)) insertSplitPos( p1 ); } l = l->getNext(); } // determine n1count / n2count for each split position aabb b1, b2, b3 = box, b4 = box; SplitList* splist = sList_; float b3p1 = b3.getPos().val[axis]; float b4p2 = b4.getPos().val[axis] + b4.getSize().val[axis]; Vector3 foo; while (splist) { foo = b4.getPos(); foo.val[axis] = splist->splitpos; b4.setPos(foo); foo = b4.getSize(); foo.val[axis] = pos2 - splist->splitpos; b4.setSize(foo); foo = b3.getSize(); foo.val[axis] = splist->splitpos - pos1; b3.setSize(foo); float b3p2 = b3.getPos().val[axis] + b3.getSize().val[axis]; float b4p1 = b4.getPos().val[axis]; for ( int i = 0; i < a_Prims; i++ ) if (pright[i]) { T* p = parray[i]; if ((eleft[i] <= b3p2) && (eright[i] >= b3p1)) if (p->intersectBox( b3 )) splist->n1count++; if ((eleft[i] <= b4p2) && (eright[i] >= b4p1)) if (p->intersectBox( b4 )) splist->n2count++; else pright[i] = false; } else splist->n1count++; splist = splist->next; } delete[] pright; // calculate surface area for current node real SAV = 0.5f / (box.w() * box.d() + box.w() * box.h() + box.d() * box.h()); // calculate cost for not splitting real Cleaf = a_Prims * 1.0f; // determine optimal split plane position splist = sList_; real lowcost = 10000; real bestpos = 0; while (splist) { // calculate child node extends foo = b4.getPos(); foo.val[axis] = splist->splitpos; b4.setPos(foo); foo = b4.getSize(); foo.val[axis] = pos2 - splist->splitpos; b4.setSize(foo); foo = b3.getSize(); foo.val[axis] = splist->splitpos - pos1; b3.setSize(foo); // calculate child node cost real SA1 = 2 * (b3.w() * b3.d() + b3.w() * b3.h() + b3.d() * b3.h()); real SA2 = 2 * (b4.w() * b4.d() + b4.w() * b4.h() + b4.d() * b4.h()); real splitcost = 0.3f + 1.0f * (SA1 * SAV * splist->n1count + SA2 * SAV * splist->n2count); // update best cost tracking variables if (splitcost < lowcost) { lowcost = splitcost; bestpos = splist->splitpos; b1 = b3, b2 = b4; } splist = splist->next; } if (lowcost > Cleaf) { delete[] eleft; delete[] eright; delete[] parray; return; } node->setSplitPos( bestpos ); // construct child nodes KdTreeNode<T>* left = s_MManager->NewKdTreeNodePair(); int n1count = 0, n2count = 0, total = 0; // assign primitives to both sides float b1p1 = b1.getPos().val[axis]; float b2p2 = b2.getPos().val[axis] + b2.getSize().val[axis]; float b1p2 = b1.getPos().val[axis] + b1.getSize().val[axis]; float b2p1 = b2.getPos().val[axis]; for ( int i = 0; i < a_Prims; i++ ) { T* p = parray[i]; total++; if ((eleft[i] <= b1p2) && (eright[i] >= b1p1)) if (p->intersectBox( b1 )) { left->add( p ); n1count++; } if ((eleft[i] <= b2p2) && (eright[i] >= b2p1)) if (p->intersectBox( b2 )) { (left + 1)->add( p ); n2count++; } } delete[] eleft; delete[] eright; delete[] parray; s_MManager->FreeObjectList( node->getList() ); node->setLeft( left ); node->setLeaf( false ); if (depth < MAXTREEDEPTH) { if (n1count > 2) subdivide( left, b1, depth + 1, n1count ); if (n2count > 2) subdivide( left + 1, b2, depth + 1, n2count ); } }
//------------------------------------------------------------------------ bool KdTreeNode::intersect(const Ray& ray, float min, float max, float* pDistance, const Sphere** ppSphere) const { ASSERT(pDistance != nullptr && ppSphere != nullptr); // Case 1: leaf has been reached if (isLeaf()) { if (m_Spheres->size() == 0) { return false; } *pDistance = std::numeric_limits<float>::max(); bool success = false; for (auto it = m_Spheres->begin(); it != m_Spheres->end(); it++) { const Sphere& s = **it; float d; if (s.intersect(ray, &d)) { if (d < *pDistance && d < max) { success = true; *pDistance = d; *ppSphere = &s; } } } return success; } float dirAxis = ray.getDirection().get(m_Axis); float tSplit = ray.planeIntersectionDistance(m_SplitDistance, m_Axis); KdTreeNode* minNode; // Node the closest to the ray origin KdTreeNode* maxNode; // Node the furthest to the ray origin if (dirAxis > 0) { minNode = getA(); maxNode = getB(); } else { minNode = getB(); maxNode = getA(); } // Case 2: ray is parallel to split plane if (dirAxis == 0) { float originPlane = ray.getOrigin().get(m_Axis); if (originPlane < m_SplitDistance) { return getA()->intersect(ray, min, max, pDistance, ppSphere); } if (m_SplitDistance < originPlane) { return getB()->intersect(ray, min, max, pDistance, ppSphere); } return false; } // Case 3: ray only crosses min node if (max < tSplit) { return minNode->intersect(ray, min, max, pDistance, ppSphere); } // Case 4: ray only crosses max node if (tSplit < min) { return maxNode->intersect(ray, min, max, pDistance, ppSphere); } // Case 5: ray crosses both nodes if (minNode->intersect(ray, min, tSplit, pDistance, ppSphere)) { return true; } return maxNode->intersect(ray, tSplit, max, pDistance, ppSphere); }
void KdTree::subdivide( KdTreeNode *node, AABB aabb, int depth, int objCount ) { // recycle used split nodes if (m_splitList) { SplitNode* list = m_splitList; while (list->next) list = list->next; list->next = m_splitPool; m_splitPool = m_splitList; // Reset the split list m_splitList = 0; } // Find the split axis, we split the aixs of maximum size Vector3 s = aabb.getSize(); // Get the size int axis; if ( (s.x >= s.y) && (s.x >= s.z) ) // Split x axis = 0; else if ( (s.y >= s.x) && (s.y >= s.z) ) // Split y axis = 1; // y axis else // Split z axis = 2; // z axis node->setAxis( axis ); // make a list of the split position candidates ObjectNode* objNodes = node->getObjectList(); float posStart = aabb.getPos().xyz[axis]; float posEnd = aabb.getPos().xyz[axis] + aabb.getSize().xyz[axis]; float* eleft = new float[objCount]; float* eright = new float[objCount]; SceneObject** parray = new SceneObject*[objCount]; int id = 0; while (objNodes) { SceneObject* p = parray[id] = objNodes->getObject(); calculateAABBRange( p->m_boundingBox, eleft[id], eright[id], axis ); // Insert all of the split positions if( eleft[id] >= posStart && eleft[id] <= posEnd ) insertSplitPos( eleft[id] ); if( eright[id] >= posStart && eright[id] <= posEnd ) insertSplitPos( eright[id] ); id++; // Get next one objNodes = objNodes->getNext(); } // Calculate left count and right count for each split choice AABB leftAABB, rightAABB; // Need to do this to give the initial value of axis other than the axis we gonna split AABB leftAABBTmp = aabb, rightAABBTmp = aabb; SplitNode* splist = m_splitList; float leftAABBStartTmp = aabb.getPos().xyz[axis]; float rightAABBEndTmp = aabb.getPos().xyz[axis] + aabb.getSize().xyz[axis]; while ( splist ) { rightAABBTmp.getPos().xyz[axis] = splist->splitPos; rightAABBTmp.getSize().xyz[axis] = posEnd - splist->splitPos; leftAABBTmp.getSize().xyz[axis] = splist->splitPos - posStart; //SUB: float leftAABBEndTmp =splist->splitPos; float leftAABBEndTmp = leftAABBTmp.getPos().xyz[axis] + leftAABBTmp.getSize().xyz[axis]; //SUB:splist->splitPos; float rightAABBStartTmp = rightAABBTmp.getPos().xyz[axis]; /* *Intersect problematic */ for ( int i = 0; i < objCount; i++ ) { SceneObject* p = parray[i]; // SUB if ((eleft[i] <= leftAABBEndTmp) && (eright[i] >= leftAABBStartTmp)) { if (p->m_boundingBox.intersectAABB( leftAABBTmp )) splist->leftCount++; } // SUB if ((eleft[i] <= rightAABBEndTmp) && (eright[i] >= rightAABBStartTmp )) { if (p->m_boundingBox.intersectAABB( rightAABBTmp )) splist->rightCount++; } } splist = splist->next; } // calculate surface area for current node float SAV = 1.f / calculateSA( aabb ); // calculate cost for not splitting float costNoSplit = objCount; // determine optimal split plane position splist = m_splitList; float min = POS_INF; float bestpos = 0; leftAABBTmp = rightAABBTmp = aabb; while (splist) { // calculate child node extends rightAABBTmp.getPos().xyz[axis] = splist->splitPos; rightAABBTmp.getSize().xyz[axis] = posEnd - splist->splitPos; leftAABBTmp.getSize().xyz[axis] = splist->splitPos - posStart; // calculate child node cost float SA1 = calculateSA( leftAABBTmp ); float SA2 = calculateSA( rightAABBTmp ); float splitcost = 0.3f + 1.0f * (SA1 * SAV * splist->leftCount + SA2 * SAV * splist->rightCount ); // update best cost tracking variables if (splitcost < min) { min = splitcost; bestpos = splist->splitPos; // Record the best left AABB and right AABB leftAABB = leftAABBTmp; rightAABB = rightAABBTmp; } splist = splist->next; } if ( min > costNoSplit) { node->setLeaf( true ); return; } node->setSplitPos( bestpos ); // construct child nodes KdTreeNode* left = newKdTreeNodePair(); KdTreeNode* right = left + 1; // COF: total, useless? int leftCount, rightCount, totalCount; leftCount = rightCount = totalCount = 0; // assign primitives to both sides float leftAABBStart = leftAABB.getPos().xyz[axis]; float leftAABBEnd = leftAABB.getPos().xyz[axis] + leftAABB.getSize().xyz[axis]; float rightAABBStart = rightAABB.getPos().xyz[axis]; float rightAABBEnd = rightAABB.getPos().xyz[axis] + rightAABB.getSize().xyz[axis]; for ( int i = 0; i < objCount; i++ ) { SceneObject* p = parray[i]; totalCount++; // TIG if ((eleft[i] <= leftAABBEnd) && (eright[i] >= leftAABBStart)) { if (p->m_boundingBox.intersectAABB( leftAABB )) { left->add( p, this ); leftCount++; } } // TIG if ((eleft[i] <= rightAABBEnd) && (eright[i] >= rightAABBStart )) { if (p->m_boundingBox.intersectAABB( rightAABB )) { right->add( p, this ); rightCount++; } } } // Release if( eleft ) delete []eleft; if( eright ) delete []eright; if( parray ) delete []parray; left->setAABB( leftAABB ); right->setAABB( rightAABB ); node->setLeft( left ); node->setRight(right); node->setLeaf( false ); if (depth < MAX_TREE_DEPTH) { if (leftCount > 2) subdivide( left, leftAABB, depth + 1, leftCount); if (rightCount > 2) subdivide( right, rightAABB, depth + 1, rightCount ); } }
/* inline float getAxisElem4( cl_float4 vec, int axis ) { if( axis == 0 ) return vec.x; else if( axis == 1 ) return vec.y; else if( axis == 2 ) return vec.z; else return -1; } bool checkRange( const cl_float4 intersect, const cl_float4 range, const int axis ) { bool result = false; switch( axis ) { case 0: // X axis range if( intersect.y >= range.x && intersect.y <= range.y && intersect.z >= range.z && intersect.z <= range.w ) result = true; break; case 1: // Y axis range if( intersect.x >= range.x && intersect.x <= range.y && intersect.z >= range.z && intersect.z <= range.w ) result = true; break; case 2: // Z axis range if( intersect.x >= range.x && intersect.x <= range.y && intersect.y >= range.z && intersect.y <= range.w ) result = true; break; default: break; } return result; } float dot( cl_float3 f1, cl_float3 f2 ) { return f1.x*f2.x + f1.y*f2.y + f1.z*f2.z; } float doIntersectPlane( cl_float3 point, cl_float3 norm, cl_float4 eyePos, cl_float4 d) { float t = -1; float denominator = (norm.x*d.x+norm.y*d.y+norm.z*d.z); if(fabs(denominator)>EPSILON) { cl_float3 eye3; eye3.x =eyePos.x; eye3.y = eyePos.y; eye3.z = eyePos.z; t = (dot(norm, point)-dot(norm, eye3))/(denominator); } return t; } void doIntersectRayKdBox2( const cl_float4 eyePos, const cl_float4 d, float* near, float* far, const cl_float3 boxStart, const cl_float3 boxSize ) { *near = -1; *far = -1; cl_float3 start = boxStart; cl_float3 end; end .x = boxStart.x + boxSize.x; end .y = boxStart.y + boxSize.y; end .z = boxStart.z + boxSize.z; cl_float3 norm[3]; // = {(cl_float3)(1,0,0), (cl_float3)(0,1,0), (cl_float3)(0,0,1) }; norm[0].x = 1, norm[0].y = 0, norm[0].z = 0; norm[1].x = 0, norm[1].y = 1, norm[1].z = 0; norm[2].x = 0, norm[2].y = 0, norm[2].z = 1; cl_float4 range[3]; range[0].x = start.y, range[0].y = end.y, range[0].z = start.z, range[0].w = end.z; range[1].x = start.x, range[1].y = end.x, range[1].z = start.z, range[1].w = end.z; range[2].x = start.x, range[2].y = end.x, range[2].z = start.y, range[2].w = end.y; float t[6]; t[0] = doIntersectPlane( start, norm[0], eyePos, d ); t[1] = doIntersectPlane( end, norm[0], eyePos, d ); t[2] = doIntersectPlane( start, norm[1], eyePos, d ); t[3] = doIntersectPlane( end, norm[1], eyePos, d ); t[4] = doIntersectPlane( start, norm[2], eyePos, d ); t[5] = doIntersectPlane( end, norm[2], eyePos, d ); cl_float4 intersectPoint[6]; float min = POS_INF; float max = -POS_INF; for( int i = 0; i < 6; i++ ) { intersectPoint[i].x = eyePos.x + t[i]*d.x; intersectPoint[i].y = eyePos.y + t[i]*d.y; intersectPoint[i].z = eyePos.z + t[i]*d.z; intersectPoint[i].w = eyePos.w + t[i]*d.w; if( t[i] > 0 && checkRange( intersectPoint[i], range[i/2], i/2 ) && min > t[i] ) { min = t[i]; *near = t[i]; } if( t[i] > 0 && checkRange( intersectPoint[i], range[i/2], i/2 ) && max < t[i] ) { max = t[i]; *far = t[i]; } } } bool boxContain( const cl_float3 start, const cl_float3 size, const cl_float3 pos ) { cl_float3 v1 = start; cl_float3 v2; v2.x = start.x + size.x; v2.y = start.y + size.y; v2.z = start.z + size.z; return ((pos.x >= v1.x) && (pos.x <= v2.x) && (pos.y >= v1.y) && (pos.y <= v2.y) && (pos.z >= v1.z) && (pos.z <= v2.z)); } cl_float4 add4( cl_float4 v1, cl_float4 v2 ) { cl_float4 result; result.x = v1.x + v2.x; result.y = v1.y + v2.y; result.z = v1.z + v2.z; result.w = v1.w + v2.w; return result; } cl_float3 add3( cl_float3 v1, cl_float3 v2 ) { cl_float3 result; result.x = v1.x + v2.x; result.y = v1.y + v2.y; result.z = v1.z + v2.z; return result; } cl_float3 mult3( float s, cl_float3 v ) { cl_float3 result; result.x = s*v.x; result.y = s*v.y; result.z = s*v.z; return result; } cl_float4 mult4( float s, cl_float4 v ) { cl_float4 result; result.x = s*v.x; result.y = s*v.y; result.z = s*v.z; result.w = s*v.w; return result; } */ REAL intersect( const Vector4& eyePos, const QVector<SceneObject>& objects, const Vector4& d, int& objectIndex, int& faceIndex, KdTree* tree, AABB extends, bool refract ) { REAL minT = POS_INF; REAL resultT = -1; int tempFaceIndex = -1; if( settings.useKdTree && tree && !refract ) { assert( EQ( eyePos.w, 1) && EQ(d.w, 0) ); REAL near, far; doIntersectRayKdBox( eyePos, d, near, far, extends ); if( near <= 0&&far <= 0 ) return -1; QVector<KdTreeNode*> nodeStack; KdTreeNode* current = tree->getRoot(); while( current ) { while( !current->isLeaf() ) { AABB curBox = current->getAABB(); REAL near, far; doIntersectRayKdBox( eyePos, d, near, far, curBox ); int axis = current->getAxis(); float splitPos = current->getSplitPos(); if( near == far ) // inside the box near = 0; Vector4 nearPos = eyePos + d*near; Vector4 farPos = eyePos + d*far; if( nearPos.data[axis] <= splitPos ) { if( farPos.data[axis] <= splitPos ) { current = current->getLeft(); continue; } KdTreeNode* right = current->getRight(); current = current->getLeft(); // Preserve the right nodeStack.push_back( right ); } else { if( farPos.data[axis] > splitPos ) { current=current->getRight(); continue; } KdTreeNode* left = current->getLeft(); current = current->getRight(); nodeStack.push_back( left ); } } // Then we found an near leaf, find if there is intersect ObjectNode* objList = current->getObjectList(); minT = POS_INF; while( objList ) { SceneObject* curObj =objList->getObject(); Matrix4x4 invCompMat = (*curObj).m_invTransform; Vector4 eyePosObjSpace = invCompMat*eyePos; Vector4 dObjSpace = invCompMat*d; REAL t = doIntersect( *curObj, eyePosObjSpace, dObjSpace, tempFaceIndex); if( t>0 && t < minT ) { minT = t; objectIndex = curObj->m_arrayID; faceIndex = tempFaceIndex; } objList = objList->getNext(); } Vector4 dst = (eyePos + minT*d); // Here we need to enlarge the bounding box a little bit AABB curBox = AABB( current->getAABB().getPos() - Vector3( EPSILON, EPSILON, EPSILON ), current->getAABB().getSize() + 2*Vector3( EPSILON, EPSILON, EPSILON )); if( minT != POS_INF && curBox.contains(Vector3(dst.x, dst.y, dst.z ) ) ) { resultT = minT; break; } // Else we need to get one node from the stack if( nodeStack.empty() ) { // No more nodes, meaning there is no intersect break; } else { current = nodeStack.at(nodeStack.size()-1); nodeStack.pop_back(); } } /** GPU code, preserve for future test **/ /* float near, far; KdTreeNodeHost root = kdnode_test[0]; cl_float4 eye4; eye4.x = eyePos.x; eye4.y = eyePos.y; eye4.z = eyePos.z; eye4.w = eyePos.w; cl_float4 d4; d4.x = d.x; d4.y = d.y; d4.z = d.z; d4.w = d.w; doIntersectRayKdBox2( eye4, d4, &near, &far, root.boxBegin, root.boxSize ); if( near <= 0 && far <= 0 ) return -1; // else // return 1; int nodeStack[1024]; int stackTop = 0; int nextIndex = 0; while( nextIndex != -1 ) { KdTreeNodeHost current = kdnode_test[nextIndex]; while( !current.leaf ) { cl_float3 curBoxStart = current.boxBegin; cl_float3 curBoxSize = current.boxSize; float near, far; doIntersectRayKdBox2( eye4, d4, &near, &far, curBoxStart, curBoxSize ); int axis = current.axis; float splitPos = current.split; if( near == far ) // inside the box near = 0; cl_float4 nearPos = add4(eye4, mult4(near, d4)); cl_float4 farPos = add4(eye4, mult4(far, d4)); if( getAxisElem4(nearPos, axis) <= splitPos ) { if( getAxisElem4(farPos, axis) <= splitPos ) { //nextIndex = current.leftIndex; current = kdnode_test[current.leftIndex]; continue; } nodeStack[stackTop++] = current.rightIndex; current = kdnode_test[current.leftIndex]; // Preserve the right } else { if( getAxisElem4(farPos, axis) > splitPos ) { // nextIndex = current.rightIndex; current = kdnode_test[current.rightIndex]; continue; } //KdTreeNodeHost left = kdnode_test[current.leftIndex]; nodeStack[stackTop++] = current.leftIndex; current = kdnode_test[current.rightIndex]; } } // Then we found an near leaf, find if there is intersect int objIndex = current.objIndex; minT = POS_INF; while( objIndex != -1 ) { ObjectNodeHost objList = objnode_test[objIndex]; int sceneObjIndex = objList.objectIndex; const SceneObject& curSceneObj = objects[sceneObjIndex]; Matrix4x4 invCompMat = curSceneObj.m_invTransform; Vector4 eyePosObjSpace = invCompMat*eyePos; Vector4 dObjSpace = invCompMat*d; REAL t = doIntersect( curSceneObj, eyePosObjSpace, dObjSpace, tempFaceIndex); if( t>0 && t < minT ) { minT = t; objectIndex = sceneObjIndex; faceIndex = tempFaceIndex; } objIndex = objList.nextNodeIndex; } //cl_float4 dst = add4(eye4, mult4(minT, d4)); Vector4 dst = eyePos + minT*d; // Here we need to enlarge the bounding box a little bit cl_float3 ep1; ep1.x = -EPSILON; ep1.y = -EPSILON; ep1.z = -EPSILON; cl_float3 ep2; ep2.x = 2*EPSILON; ep2.y = 2*EPSILON; ep2.z = 2*EPSILON; cl_float3 boxStart = add3(current.boxBegin , ep1); cl_float3 boxSize = add3(current.boxSize, ep2 ); cl_float3 dst3; dst3.x = dst.x; dst3.y = dst.y; dst3.z = dst.z; if( minT != POS_INF && boxContain( boxStart, boxSize, dst3 ) ) { resultT = minT; //resultT = 1; break; } // Else we need to get one node from the stack if( stackTop == 0 ) { // No more nodes, meaning there is no intersect int a = 0; break; } else { nextIndex = nodeStack[--stackTop]; } }*/ } else { for( int i = 0; i < objects.size(); i++ ) { const SceneObject& curObj = objects[i]; Matrix4x4 invCompMat = curObj.m_invTransform; Vector4 eyePosObjSpace = invCompMat*eyePos; Vector4 dObjSpace = invCompMat*d; REAL t = doIntersect( curObj, eyePosObjSpace, dObjSpace, tempFaceIndex); if( t>0 && t < minT ) { minT = t; objectIndex = i; faceIndex = tempFaceIndex; } } if( minT != POS_INF ) { resultT = minT; } } return resultT; }