Beispiel #1
0
        public void intersectPrimitiveRobust(Ray r, int primID, IntersectionState state)
        {
            // ray-triangle intersection here
            int tri = 3 * primID;
            int a = 3 * triangles[tri + 0];
            int b = 3 * triangles[tri + 1];
            int c = 3 * triangles[tri + 2];
            float[] stack = state.getRobustStack();
            for (int i = 0, i3 = 0; i < 3; i++, i3 += 3)
            {
                stack[i3 + 0] = points[a + i];
                stack[i3 + 1] = points[b + i];
                stack[i3 + 2] = points[c + i];
            }
            stack[9] = float.PositiveInfinity;
            int stackpos = 0;
            float orgX = r.ox;
            float dirX = r.dx, invDirX = 1 / dirX;
            float orgY = r.oy;
            float dirY = r.dy, invDirY = 1 / dirY;
            float orgZ = r.oz;
            float dirZ = r.dz, invDirZ = 1 / dirZ;
            float t1, t2;
            float minx, maxx;
            float miny, maxy;
            float minz, maxz;
            float mint = r.getMin();
            float maxt = r.getMax();
            while (stackpos >= 0)
            {
                float intervalMin = mint;
                float intervalMax = maxt;
                float p0x = stack[stackpos + 0];
                float p1x = stack[stackpos + 1];
                float p2x = stack[stackpos + 2];
                t1 = ((minx = MathUtils.min(p0x, p1x, p2x)) - orgX) * invDirX;
                t2 = ((maxx = MathUtils.max(p0x, p1x, p2x)) - 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)
                {
                    stackpos -= 10;
                    continue;
                }
                float p0y = stack[stackpos + 3];
                float p1y = stack[stackpos + 4];
                float p2y = stack[stackpos + 5];
                t1 = ((miny = MathUtils.min(p0y, p1y, p2y)) - orgY) * invDirY;
                t2 = ((maxy = MathUtils.max(p0y, p1y, p2y)) - 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)
                {
                    stackpos -= 10;
                    continue;
                }
                float p0z = stack[stackpos + 6];
                float p1z = stack[stackpos + 7];
                float p2z = stack[stackpos + 8];
                t1 = ((minz = MathUtils.min(p0z, p1z, p2z)) - orgZ) * invDirZ;
                t2 = ((maxz = MathUtils.max(p0z, p1z, p2z)) - 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)
                {
                    stackpos -= 10;
                    continue;
                }
                // intersection was found - keep going
                float size = (maxx - minx) + (maxy - miny) + (maxz - minz);
                if (ByteUtil.floatToRawIntBits(stack[stackpos + 9]) == ByteUtil.floatToRawIntBits(size))
                {
                    // L1 norm is 0, we are done
                    r.setMax(intervalMin);
                    triaccel[primID].intersectBox(r, p0x, p0y, p0z, primID, state);
                    return; // safe to return, only one intersection per primitive
                }
                // not small enough yet - subdivide
                float p01x = (p0x + p1x) * 0.5f;
                float p01y = (p0y + p1y) * 0.5f;
                float p01z = (p0z + p1z) * 0.5f;

                float p12x = (p1x + p2x) * 0.5f;
                float p12y = (p1y + p2y) * 0.5f;
                float p12z = (p1z + p2z) * 0.5f;

                float p20x = (p2x + p0x) * 0.5f;
                float p20y = (p2y + p0y) * 0.5f;
                float p20z = (p2z + p0z) * 0.5f;

                // triangle 0
                stack[stackpos + 0] = p0x;
                stack[stackpos + 1] = p01x;
                stack[stackpos + 2] = p20x;
                stack[stackpos + 3] = p0y;
                stack[stackpos + 4] = p01y;
                stack[stackpos + 5] = p20y;
                stack[stackpos + 6] = p0z;
                stack[stackpos + 7] = p01z;
                stack[stackpos + 8] = p20z;
                stack[stackpos + 9] = size;
                stackpos += 10;
                // triangle 1
                stack[stackpos + 0] = p1x;
                stack[stackpos + 1] = p12x;
                stack[stackpos + 2] = p01x;
                stack[stackpos + 3] = p1y;
                stack[stackpos + 4] = p12y;
                stack[stackpos + 5] = p01y;
                stack[stackpos + 6] = p1z;
                stack[stackpos + 7] = p12z;
                stack[stackpos + 8] = p01z;
                stack[stackpos + 9] = size;
                stackpos += 10;
                // triangle 2
                stack[stackpos + 0] = p2x;
                stack[stackpos + 1] = p20x;
                stack[stackpos + 2] = p12x;
                stack[stackpos + 3] = p2y;
                stack[stackpos + 4] = p20y;
                stack[stackpos + 5] = p12y;
                stack[stackpos + 6] = p2z;
                stack[stackpos + 7] = p20z;
                stack[stackpos + 8] = p12z;
                stack[stackpos + 9] = size;
                stackpos += 10;
                // triangle 4
                stack[stackpos + 0] = p20x;
                stack[stackpos + 1] = p12x;
                stack[stackpos + 2] = p01x;
                stack[stackpos + 3] = p20y;
                stack[stackpos + 4] = p12y;
                stack[stackpos + 5] = p01y;
                stack[stackpos + 6] = p20z;
                stack[stackpos + 7] = p12z;
                stack[stackpos + 8] = p01z;
                stack[stackpos + 9] = size;
            }
        }
Beispiel #2
0
        public void intersectPrimitive(Ray r, int primID, IntersectionState state)
        {
            // ray patch intersection
            float[] stack = state.getRobustStack();
            int STACKSIZE = 64;
            {
                // init patch
                float[] patch = patches[primID];
                for (int i = 0; i < 4 * 4 * 3; i++)
                    stack[i] = patch[i];
                stack[48] = float.PositiveInfinity; // bbox size
                stack[49] = 0; // umin
                stack[50] = 0; // vmin
                stack[51] = 1; // umax
                stack[52] = 1; // vmax
            }
            int stackpos = 0;
            float orgX = r.ox, invDirX = 1 / r.dx;
            float orgY = r.oy, invDirY = 1 / r.dy;
            float orgZ = r.oz, invDirZ = 1 / r.dz;
            float t1, t2;
            while (stackpos >= 0)
            {
                float intervalMin = r.getMin();
                float intervalMax = r.getMax();
                // x-axis bbox
                float minx = stack[stackpos + 0];
                float maxx = stack[stackpos + 0];
                for (int j = 1, idx = stackpos + 3; j < 4 * 4; j++, idx += 3)
                {
                    if (minx > stack[idx])
                        minx = stack[idx];
                    if (maxx < stack[idx])
                        maxx = stack[idx];
                }
                t1 = (minx - orgX) * invDirX;
                t2 = (maxx - 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)
                {
                    stackpos -= STACKSIZE;
                    continue;
                }
                // y-axis bbox
                float miny = stack[stackpos + 1];
                float maxy = stack[stackpos + 1];
                for (int j = 1, idx = stackpos + 4; j < 4 * 4; j++, idx += 3)
                {
                    if (miny > stack[idx])
                        miny = stack[idx];
                    if (maxy < stack[idx])
                        maxy = stack[idx];
                }
                t1 = (miny - orgY) * invDirY;
                t2 = (maxy - 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)
                {
                    stackpos -= STACKSIZE;
                    continue;
                }
                // z-axis bbox
                float minz = stack[stackpos + 2];
                float maxz = stack[stackpos + 2];
                for (int j = 1, idx = stackpos + 5; j < 4 * 4; j++, idx += 3)
                {
                    if (minz > stack[idx])
                        minz = stack[idx];
                    if (maxz < stack[idx])
                        maxz = stack[idx];
                }

                t1 = (minz - orgZ) * invDirZ;
                t2 = (maxz - 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)
                {
                    stackpos -= STACKSIZE;
                    continue;
                }
                // intersection was found - keep going
                float size = (maxx - minx) + (maxy - miny) + (maxz - minz);
                if (ByteUtil.floatToRawIntBits(stack[stackpos + 48]) == ByteUtil.floatToRawIntBits(size))
                {
                    // L1 norm is 0, we are done
                    r.setMax(intervalMin);
                    state.setIntersection(primID, stack[stackpos + 49], stack[stackpos + 50]);
                    stackpos -= STACKSIZE;
                    continue;
                }
                // not small enough yet - subdivide
                // lets pick a subdivision axis first:
                float sizeu = 0;
                float sizev = 0;
                for (int i = 0; i < 3; i++)
                {
                    sizeu += System.Math.Abs(stack[stackpos + (0 * 4 + 3) * 3 + i] - stack[stackpos + i]);
                    sizev += System.Math.Abs(stack[stackpos + (3 * 4 + 0) * 3 + i] - stack[stackpos + i]);
                }

                if (sizeu > sizev)
                {
                    // split in U direction
                    for (int i = 0; i < 4; i++)
                    {
                        for (int axis = 0; axis < 3; axis++)
                        {
                            // load data
                            float p0 = stack[stackpos + (i * 4 + 0) * 3 + axis];
                            float p1 = stack[stackpos + (i * 4 + 1) * 3 + axis];
                            float p2 = stack[stackpos + (i * 4 + 2) * 3 + axis];
                            float p3 = stack[stackpos + (i * 4 + 3) * 3 + axis];
                            // Split curve in the middle
                            float q0 = p0;
                            float q1 = (p0 + p1) * 0.5f;
                            float q2 = q1 * 0.5f + (p1 + p2) * 0.25f;
                            float r3 = p3;
                            float r2 = (p2 + p3) * 0.5f;
                            float r1 = r2 * 0.5f + (p1 + p2) * 0.25f;
                            float q3 = (q2 + r1) * 0.5f;
                            float r0 = q3;
                            // load new curve data into the stack
                            stack[stackpos + (i * 4 + 0) * 3 + axis] = q0;
                            stack[stackpos + (i * 4 + 1) * 3 + axis] = q1;
                            stack[stackpos + (i * 4 + 2) * 3 + axis] = q2;
                            stack[stackpos + (i * 4 + 3) * 3 + axis] = q3;
                            stack[stackpos + STACKSIZE + (i * 4 + 0) * 3 + axis] = r0;
                            stack[stackpos + STACKSIZE + (i * 4 + 1) * 3 + axis] = r1;
                            stack[stackpos + STACKSIZE + (i * 4 + 2) * 3 + axis] = r2;
                            stack[stackpos + STACKSIZE + (i * 4 + 3) * 3 + axis] = r3;
                        }
                    }
                    // copy current bbox size
                    stack[stackpos + 48] = stack[stackpos + STACKSIZE + 48] = size;
                    // finally - split uv ranges
                    float umin = stack[stackpos + 49];
                    float umax = stack[stackpos + 51];
                    stack[stackpos + 49] = umin;
                    stack[stackpos + STACKSIZE + 50] = stack[stackpos + 50];
                    stack[stackpos + 51] = stack[stackpos + STACKSIZE + 49] = (umin + umax) * 0.5f;
                    stack[stackpos + STACKSIZE + 51] = umax;
                    stack[stackpos + STACKSIZE + 52] = stack[stackpos + 52];
                }
                else
                {
                    // split in V direction
                    for (int i = 0; i < 4; i++)
                    {
                        for (int axis = 0; axis < 3; axis++)
                        {
                            // load data
                            float p0 = stack[stackpos + (0 * 4 + i) * 3 + axis];
                            float p1 = stack[stackpos + (1 * 4 + i) * 3 + axis];
                            float p2 = stack[stackpos + (2 * 4 + i) * 3 + axis];
                            float p3 = stack[stackpos + (3 * 4 + i) * 3 + axis];
                            // Split curve in the middle
                            float q0 = p0;
                            float q1 = (p0 + p1) * 0.5f;
                            float q2 = q1 * 0.5f + (p1 + p2) * 0.25f;
                            float r3 = p3;
                            float r2 = (p2 + p3) * 0.5f;
                            float r1 = r2 * 0.5f + (p1 + p2) * 0.25f;
                            float q3 = (q2 + r1) * 0.5f;
                            float r0 = q3;
                            // load new curve data into the stack
                            stack[stackpos + (0 * 4 + i) * 3 + axis] = q0;
                            stack[stackpos + (1 * 4 + i) * 3 + axis] = q1;
                            stack[stackpos + (2 * 4 + i) * 3 + axis] = q2;
                            stack[stackpos + (3 * 4 + i) * 3 + axis] = q3;
                            stack[stackpos + STACKSIZE + (0 * 4 + i) * 3 + axis] = r0;
                            stack[stackpos + STACKSIZE + (1 * 4 + i) * 3 + axis] = r1;
                            stack[stackpos + STACKSIZE + (2 * 4 + i) * 3 + axis] = r2;
                            stack[stackpos + STACKSIZE + (3 * 4 + i) * 3 + axis] = r3;
                        }
                    }
                    // copy current bbox size
                    stack[stackpos + 48] = stack[stackpos + STACKSIZE + 48] = size;
                    // finally - split uv ranges
                    float vmin = stack[stackpos + 50];
                    float vmax = stack[stackpos + 52];
                    stack[stackpos + STACKSIZE + 49] = stack[stackpos + 49];
                    stack[stackpos + 50] = vmin;
                    stack[stackpos + 52] = stack[stackpos + STACKSIZE + 50] = (vmin + vmax) * 0.5f;
                    stack[stackpos + STACKSIZE + 51] = stack[stackpos + 51];
                    stack[stackpos + STACKSIZE + 52] = vmax;
                }
                stackpos += STACKSIZE;
            }
        }