public void intersect(Ray r, IntersectionState state) { float intervalMin = r.getMin(); float intervalMax = r.getMax(); float orgX = r.ox; float dirX = r.dx, invDirX = 1 / dirX; float t1, t2; t1 = (bounds.getMinimum().x - orgX) * invDirX; t2 = (bounds.getMaximum().x - orgX) * invDirX; if (invDirX > 0) { if (t1 > intervalMin) { intervalMin = t1; } if (t2 < intervalMax) { intervalMax = t2; } } else { if (t2 > intervalMin) { intervalMin = t2; } if (t1 < intervalMax) { intervalMax = t1; } } if (intervalMin > intervalMax) { return; } float orgY = r.oy; float dirY = r.dy, invDirY = 1 / dirY; t1 = (bounds.getMinimum().y - orgY) * invDirY; t2 = (bounds.getMaximum().y - orgY) * invDirY; if (invDirY > 0) { if (t1 > intervalMin) { intervalMin = t1; } if (t2 < intervalMax) { intervalMax = t2; } } else { if (t2 > intervalMin) { intervalMin = t2; } if (t1 < intervalMax) { intervalMax = t1; } } if (intervalMin > intervalMax) { return; } float orgZ = r.oz; float dirZ = r.dz, invDirZ = 1 / dirZ; t1 = (bounds.getMinimum().z - orgZ) * invDirZ; t2 = (bounds.getMaximum().z - orgZ) * invDirZ; if (invDirZ > 0) { if (t1 > intervalMin) { intervalMin = t1; } if (t2 < intervalMax) { intervalMax = t2; } } else { if (t2 > intervalMin) { intervalMin = t2; } if (t1 < intervalMax) { intervalMax = t1; } } if (intervalMin > intervalMax) { return; } // compute custom offsets from direction sign bit int offsetXFront = (int)((uint)(ByteUtil.floatToRawIntBits(dirX) & (1 << 31)) >> 30); //>>> int offsetYFront = (int)((uint)(ByteUtil.floatToRawIntBits(dirY) & (1 << 31)) >> 30); //>>> int offsetZFront = (int)((uint)(ByteUtil.floatToRawIntBits(dirZ) & (1 << 31)) >> 30); //>>> int offsetXBack = offsetXFront ^ 2; int offsetYBack = offsetYFront ^ 2; int offsetZBack = offsetZFront ^ 2; IntersectionState.StackNode[] stack = state.getStack(); int stackTop = state.getStackTop(); int stackPos = stackTop; int node = 0; while (true) { int tn = tree[node]; int axis = tn & (3 << 30); int offset = tn & ~(3 << 30); switch (axis) { case 0: { float d = (ByteUtil.intBitsToFloat(tree[node + 1]) - orgX) * invDirX; int back = offset + offsetXBack; node = back; if (d < intervalMin) { continue; } node = offset + offsetXFront; // front if (d > intervalMax) { continue; } // push back node stack[stackPos].node = back; stack[stackPos].near = (d >= intervalMin) ? d : intervalMin; stack[stackPos].far = intervalMax; stackPos++; // update ray interval for front node intervalMax = (d <= intervalMax) ? d : intervalMax; continue; } case 1 << 30: { // y axis float d = (ByteUtil.intBitsToFloat(tree[node + 1]) - orgY) * invDirY; int back = offset + offsetYBack; node = back; if (d < intervalMin) { continue; } node = offset + offsetYFront; // front if (d > intervalMax) { continue; } // push back node stack[stackPos].node = back; stack[stackPos].near = (d >= intervalMin) ? d : intervalMin; stack[stackPos].far = intervalMax; stackPos++; // update ray interval for front node intervalMax = (d <= intervalMax) ? d : intervalMax; continue; } case 2 << 30: { // z axis float d = (ByteUtil.intBitsToFloat(tree[node + 1]) - orgZ) * invDirZ; int back = offset + offsetZBack; node = back; if (d < intervalMin) { continue; } node = offset + offsetZFront; // front if (d > intervalMax) { continue; } // push back node stack[stackPos].node = back; stack[stackPos].near = (d >= intervalMin) ? d : intervalMin; stack[stackPos].far = intervalMax; stackPos++; // update ray interval for front node intervalMax = (d <= intervalMax) ? d : intervalMax; continue; } default: { // leaf - test some objects int n = tree[node + 1]; while (n > 0) { primitiveList.intersectPrimitive(r, primitives[offset], state); n--; offset++; } if (r.getMax() < intervalMax) { return; } do { // stack is empty? if (stackPos == stackTop) { return; } // move back up the stack stackPos--; intervalMin = stack[stackPos].near; if (r.getMax() < intervalMin) { continue; } node = stack[stackPos].node; intervalMax = stack[stackPos].far; break; } while (true); break; } } // switch } // traversal loop }
public void intersect(Ray r, IntersectionState state) { float intervalMin = r.getMin(); float intervalMax = r.getMax(); float orgX = r.ox; float dirX = r.dx, invDirX = 1 / dirX; float t1, t2; t1 = (bounds.getMinimum().x - orgX) * invDirX; t2 = (bounds.getMaximum().x - orgX) * invDirX; if (invDirX > 0) { if (t1 > intervalMin) { intervalMin = t1; } if (t2 < intervalMax) { intervalMax = t2; } } else { if (t2 > intervalMin) { intervalMin = t2; } if (t1 < intervalMax) { intervalMax = t1; } } if (intervalMin > intervalMax) { return; } float orgY = r.oy; float dirY = r.dy, invDirY = 1 / dirY; t1 = (bounds.getMinimum().y - orgY) * invDirY; t2 = (bounds.getMaximum().y - orgY) * invDirY; if (invDirY > 0) { if (t1 > intervalMin) { intervalMin = t1; } if (t2 < intervalMax) { intervalMax = t2; } } else { if (t2 > intervalMin) { intervalMin = t2; } if (t1 < intervalMax) { intervalMax = t1; } } if (intervalMin > intervalMax) { return; } float orgZ = r.oz; float dirZ = r.dz, invDirZ = 1 / dirZ; t1 = (bounds.getMinimum().z - orgZ) * invDirZ; t2 = (bounds.getMaximum().z - orgZ) * invDirZ; if (invDirZ > 0) { if (t1 > intervalMin) { intervalMin = t1; } if (t2 < intervalMax) { intervalMax = t2; } } else { if (t2 > intervalMin) { intervalMin = t2; } if (t1 < intervalMax) { intervalMax = t1; } } if (intervalMin > intervalMax) { return; } // compute custom offsets from direction sign bit int offsetXFront = (int)((uint)ByteUtil.floatToRawIntBits(dirX) >> 31); //>>> int offsetYFront = (int)((uint)ByteUtil.floatToRawIntBits(dirY) >> 31); //>>> int offsetZFront = (int)((uint)ByteUtil.floatToRawIntBits(dirZ) >> 31); //>>> int offsetXBack = offsetXFront ^ 1; int offsetYBack = offsetYFront ^ 1; int offsetZBack = offsetZFront ^ 1; int offsetXFront3 = offsetXFront * 3; int offsetYFront3 = offsetYFront * 3; int offsetZFront3 = offsetZFront * 3; int offsetXBack3 = offsetXBack * 3; int offsetYBack3 = offsetYBack * 3; int offsetZBack3 = offsetZBack * 3; // avoid always adding 1 during the inner loop offsetXFront++; offsetYFront++; offsetZFront++; offsetXBack++; offsetYBack++; offsetZBack++; IntersectionState.StackNode[] stack = state.getStack(); int stackTop = state.getStackTop(); int stackPos = stackTop; int node = 0; while (true) { pushloop: while (true) { int tn = tree[node]; int axis = tn & (7 << 29); int offset = tn & ~(7 << 29); switch (axis) { case 0: { // x axis float tf = (ByteUtil.intBitsToFloat(tree[node + offsetXFront]) - orgX) * invDirX; float tb = (ByteUtil.intBitsToFloat(tree[node + offsetXBack]) - orgX) * invDirX; // ray passes between clip zones if (tf < intervalMin && tb > intervalMax) { goto pushloopend; } int back = offset + offsetXBack3; node = back; // ray passes through far node only if (tf < intervalMin) { intervalMin = (tb >= intervalMin) ? tb : intervalMin; continue; } node = offset + offsetXFront3; // front // ray passes through near node only if (tb > intervalMax) { intervalMax = (tf <= intervalMax) ? tf : intervalMax; continue; } // ray passes through both nodes // push back node stack[stackPos].node = back; stack[stackPos].near = (tb >= intervalMin) ? tb : intervalMin; stack[stackPos].far = intervalMax; stackPos++; // update ray interval for front node intervalMax = (tf <= intervalMax) ? tf : intervalMax; continue; } case 1 << 30: { float tf = (ByteUtil.intBitsToFloat(tree[node + offsetYFront]) - orgY) * invDirY; float tb = (ByteUtil.intBitsToFloat(tree[node + offsetYBack]) - orgY) * invDirY; // ray passes between clip zones if (tf < intervalMin && tb > intervalMax) { goto pushloopend; } int back = offset + offsetYBack3; node = back; // ray passes through far node only if (tf < intervalMin) { intervalMin = (tb >= intervalMin) ? tb : intervalMin; continue; } node = offset + offsetYFront3; // front // ray passes through near node only if (tb > intervalMax) { intervalMax = (tf <= intervalMax) ? tf : intervalMax; continue; } // ray passes through both nodes // push back node stack[stackPos].node = back; stack[stackPos].near = (tb >= intervalMin) ? tb : intervalMin; stack[stackPos].far = intervalMax; stackPos++; // update ray interval for front node intervalMax = (tf <= intervalMax) ? tf : intervalMax; continue; } case 2 << 30: { // z axis float tf = (ByteUtil.intBitsToFloat(tree[node + offsetZFront]) - orgZ) * invDirZ; float tb = (ByteUtil.intBitsToFloat(tree[node + offsetZBack]) - orgZ) * invDirZ; // ray passes between clip zones if (tf < intervalMin && tb > intervalMax) { goto pushloopend; } int back = offset + offsetZBack3; node = back; // ray passes through far node only if (tf < intervalMin) { intervalMin = (tb >= intervalMin) ? tb : intervalMin; continue; } node = offset + offsetZFront3; // front // ray passes through near node only if (tb > intervalMax) { intervalMax = (tf <= intervalMax) ? tf : intervalMax; continue; } // ray passes through both nodes // push back node stack[stackPos].node = back; stack[stackPos].near = (tb >= intervalMin) ? tb : intervalMin; stack[stackPos].far = intervalMax; stackPos++; // update ray interval for front node intervalMax = (tf <= intervalMax) ? tf : intervalMax; continue; } case 3 << 30: { // leaf - test some objects int n = tree[node + 1]; while (n > 0) { primitives.intersectPrimitive(r, objects[offset], state); n--; offset++; } goto pushloopend; } case 1 << 29: { float tf = (ByteUtil.intBitsToFloat(tree[node + offsetXFront]) - orgX) * invDirX; float tb = (ByteUtil.intBitsToFloat(tree[node + offsetXBack]) - orgX) * invDirX; node = offset; intervalMin = (tf >= intervalMin) ? tf : intervalMin; intervalMax = (tb <= intervalMax) ? tb : intervalMax; if (intervalMin > intervalMax) { goto pushloopend; } continue; } case 3 << 29: { float tf = (ByteUtil.intBitsToFloat(tree[node + offsetYFront]) - orgY) * invDirY; float tb = (ByteUtil.intBitsToFloat(tree[node + offsetYBack]) - orgY) * invDirY; node = offset; intervalMin = (tf >= intervalMin) ? tf : intervalMin; intervalMax = (tb <= intervalMax) ? tb : intervalMax; if (intervalMin > intervalMax) { goto pushloopend; } continue; } case 5 << 29: { float tf = (ByteUtil.intBitsToFloat(tree[node + offsetZFront]) - orgZ) * invDirZ; float tb = (ByteUtil.intBitsToFloat(tree[node + offsetZBack]) - orgZ) * invDirZ; node = offset; intervalMin = (tf >= intervalMin) ? tf : intervalMin; intervalMax = (tb <= intervalMax) ? tb : intervalMax; if (intervalMin > intervalMax) { goto pushloopend; } continue; } default: return; // should not happen } // switch } // traversal loop pushloopend: do { // stack is empty? if (stackPos == stackTop) { return; } // move back up the stack stackPos--; intervalMin = stack[stackPos].near; if (r.getMax() < intervalMin) { continue; } node = stack[stackPos].node; intervalMax = stack[stackPos].far; break; } while (true); } }