Exemplo n.º 1
0
        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
        }
Exemplo n.º 2
0
        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);
            }
        }