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; } }
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; } }