예제 #1
0
            public void intersectPrimitive(Ray r, int primID, IntersectionState state)
            {
                float uv00 = 0, uv01 = 0, uv10 = 0, uv11 = 0, uv20 = 0, uv21 = 0;
                switch (triangleMesh.uvs.interp)
                {
                    case ParameterList.InterpolationType.NONE:
                    case ParameterList.InterpolationType.FACE:
                    default:
                        return;
                    case ParameterList.InterpolationType.VERTEX:
                        {
                            int tri = 3 * primID;
                            int index0 = triangleMesh.triangles[tri + 0];
                            int index1 = triangleMesh.triangles[tri + 1];
                            int index2 = triangleMesh.triangles[tri + 2];
                            int i20 = 2 * index0;
                            int i21 = 2 * index1;
                            int i22 = 2 * index2;
                            float[] uvs = triangleMesh.uvs.data;
                            uv00 = uvs[i20 + 0];
                            uv01 = uvs[i20 + 1];
                            uv10 = uvs[i21 + 0];
                            uv11 = uvs[i21 + 1];
                            uv20 = uvs[i22 + 0];
                            uv21 = uvs[i22 + 1];
                            break;

                        }
                    case ParameterList.InterpolationType.FACEVARYING:
                        {
                            int idx = (3 * primID) << 1;
                            float[] uvs = triangleMesh.uvs.data;
                            uv00 = uvs[idx + 0];
                            uv01 = uvs[idx + 1];
                            uv10 = uvs[idx + 2];
                            uv11 = uvs[idx + 3];
                            uv20 = uvs[idx + 4];
                            uv21 = uvs[idx + 5];
                            break;
                        }
                }

                double edge1x = uv10 - uv00;
                double edge1y = uv11 - uv01;
                double edge2x = uv20 - uv00;
                double edge2y = uv21 - uv01;
                double pvecx = r.dy * 0 - r.dz * edge2y;
                double pvecy = r.dz * edge2x - r.dx * 0;
                double pvecz = r.dx * edge2y - r.dy * edge2x;
                double qvecx, qvecy, qvecz;
                double u, v;
                double det = edge1x * pvecx + edge1y * pvecy + 0 * pvecz;
                if (det > 0)
                {
                    double tvecx = r.ox - uv00;
                    double tvecy = r.oy - uv01;
                    double tvecz = r.oz;
                    u = (tvecx * pvecx + tvecy * pvecy + tvecz * pvecz);
                    if (u < 0.0 || u > det)
                        return;
                    qvecx = tvecy * 0 - tvecz * edge1y;
                    qvecy = tvecz * edge1x - tvecx * 0;
                    qvecz = tvecx * edge1y - tvecy * edge1x;
                    v = (r.dx * qvecx + r.dy * qvecy + r.dz * qvecz);
                    if (v < 0.0 || u + v > det)
                        return;
                }
                else if (det < 0)
                {
                    double tvecx = r.ox - uv00;
                    double tvecy = r.oy - uv01;
                    double tvecz = r.oz;
                    u = (tvecx * pvecx + tvecy * pvecy + tvecz * pvecz);
                    if (u > 0.0 || u < det)
                        return;
                    qvecx = tvecy * 0 - tvecz * edge1y;
                    qvecy = tvecz * edge1x - tvecx * 0;
                    qvecz = tvecx * edge1y - tvecy * edge1x;
                    v = (r.dx * qvecx + r.dy * qvecy + r.dz * qvecz);
                    if (v > 0.0 || u + v < det)
                        return;
                }
                else
                    return;
                double inv_det = 1.0 / det;
                float t = (float)((edge2x * qvecx + edge2y * qvecy + 0 * qvecz) * inv_det);
                if (r.isInside(t))
                {
                    r.setMax(t);
                    state.setIntersection(primID, (float)(u * inv_det), (float)(v * inv_det));
                }
            }
예제 #2
0
파일: Box.cs 프로젝트: rzel/sunflowsharp
 public void intersectPrimitive(Ray r, int primID, IntersectionState state)
 {
     float intervalMin = float.NegativeInfinity;
     float intervalMax = float.PositiveInfinity;
     float orgX = r.ox;
     float invDirX = 1 / r.dx;
     float t1, t2;
     t1 = (minX - orgX) * invDirX;
     t2 = (maxX - orgX) * invDirX;
     int sideIn = -1, sideOut = -1;
     if (invDirX > 0)
     {
         if (t1 > intervalMin)
         {
             intervalMin = t1;
             sideIn = 0;
         }
         if (t2 < intervalMax)
         {
             intervalMax = t2;
             sideOut = 1;
         }
     }
     else
     {
         if (t2 > intervalMin)
         {
             intervalMin = t2;
             sideIn = 1;
         }
         if (t1 < intervalMax)
         {
             intervalMax = t1;
             sideOut = 0;
         }
     }
     if (intervalMin > intervalMax)
         return;
     float orgY = r.oy;
     float invDirY = 1 / r.dy;
     t1 = (minY - orgY) * invDirY;
     t2 = (maxY - orgY) * invDirY;
     if (invDirY > 0)
     {
         if (t1 > intervalMin)
         {
             intervalMin = t1;
             sideIn = 2;
         }
         if (t2 < intervalMax)
         {
             intervalMax = t2;
             sideOut = 3;
         }
     }
     else
     {
         if (t2 > intervalMin)
         {
             intervalMin = t2;
             sideIn = 3;
         }
         if (t1 < intervalMax)
         {
             intervalMax = t1;
             sideOut = 2;
         }
     }
     if (intervalMin > intervalMax)
         return;
     float orgZ = r.oz;
     float invDirZ = 1 / r.dz;
     t1 = (minZ - orgZ) * invDirZ; // no front wall
     t2 = (maxZ - orgZ) * invDirZ;
     if (invDirZ > 0)
     {
         if (t1 > intervalMin)
         {
             intervalMin = t1;
             sideIn = 4;
         }
         if (t2 < intervalMax)
         {
             intervalMax = t2;
             sideOut = 5;
         }
     }
     else
     {
         if (t2 > intervalMin)
         {
             intervalMin = t2;
             sideIn = 5;
         }
         if (t1 < intervalMax)
         {
             intervalMax = t1;
             sideOut = 4;
         }
     }
     if (intervalMin > intervalMax)
         return;
     if (r.isInside(intervalMin))
     {
         r.setMax(intervalMin);
         state.setIntersection(sideIn, 0, 0);
     }
     else if (r.isInside(intervalMax))
     {
         r.setMax(intervalMax);
         state.setIntersection(sideOut, 0, 0);
     }
 }
예제 #3
0
 private void intersectTriangleKensler(Ray r, int primID, IntersectionState state)
 {
     int tri = 3 * primID;
     int a = 3 * triangles[tri + 0];
     int b = 3 * triangles[tri + 1];
     int c = 3 * triangles[tri + 2];
     float edge0x = points[b + 0] - points[a + 0];
     float edge0y = points[b + 1] - points[a + 1];
     float edge0z = points[b + 2] - points[a + 2];
     float edge1x = points[a + 0] - points[c + 0];
     float edge1y = points[a + 1] - points[c + 1];
     float edge1z = points[a + 2] - points[c + 2];
     float nx = edge0y * edge1z - edge0z * edge1y;
     float ny = edge0z * edge1x - edge0x * edge1z;
     float nz = edge0x * edge1y - edge0y * edge1x;
     float v = r.dot(nx, ny, nz);
     float iv = 1 / v;
     float edge2x = points[a + 0] - r.ox;
     float edge2y = points[a + 1] - r.oy;
     float edge2z = points[a + 2] - r.oz;
     float va = nx * edge2x + ny * edge2y + nz * edge2z;
     float t = iv * va;
     if (!r.isInside(t))
         return;
     float ix = edge2y * r.dz - edge2z * r.dy;
     float iy = edge2z * r.dx - edge2x * r.dz;
     float iz = edge2x * r.dy - edge2y * r.dx;
     float v1 = ix * edge1x + iy * edge1y + iz * edge1z;
     float beta = iv * v1;
     if (beta < 0)
         return;
     float v2 = ix * edge0x + iy * edge0y + iz * edge0z;
     if ((v1 + v2) * v > v * v)
         return;
     float gamma = iv * v2;
     if (gamma < 0)
         return;
     r.setMax(t);
     state.setIntersection(primID, beta, gamma);
 }
예제 #4
0
 public void intersect(Ray r, int primID, IntersectionState state)
 {
     switch (k)
     {
         case 0:
             {
                 float det = 1.0f / (r.dx + nu * r.dy + nv * r.dz);
                 float t = (nd - r.ox - nu * r.oy - nv * r.oz) * det;
                 if (!r.isInside(t))
                     return;
                 float hu = r.oy + t * r.dy;
                 float hv = r.oz + t * r.dz;
                 float u = hu * bnu + hv * bnv + bnd;
                 if (u < 0.0f)
                     return;
                 float v = hu * cnu + hv * cnv + cnd;
                 if (v < 0.0f)
                     return;
                 if (u + v > 1.0f)
                     return;
                 r.setMax(t);
                 state.setIntersection(primID, u, v);
                 return;
             }
         case 1:
             {
                 float det = 1.0f / (r.dy + nu * r.dz + nv * r.dx);
                 float t = (nd - r.oy - nu * r.oz - nv * r.ox) * det;
                 if (!r.isInside(t))
                     return;
                 float hu = r.oz + t * r.dz;
                 float hv = r.ox + t * r.dx;
                 float u = hu * bnu + hv * bnv + bnd;
                 if (u < 0.0f)
                     return;
                 float v = hu * cnu + hv * cnv + cnd;
                 if (v < 0.0f)
                     return;
                 if (u + v > 1.0f)
                     return;
                 r.setMax(t);
                 state.setIntersection(primID, u, v);
                 return;
             }
         case 2:
             {
                 float det = 1.0f / (r.dz + nu * r.dx + nv * r.dy);
                 float t = (nd - r.oz - nu * r.ox - nv * r.oy) * det;
                 if (!r.isInside(t))
                     return;
                 float hu = r.ox + t * r.dx;
                 float hv = r.oy + t * r.dy;
                 float u = hu * bnu + hv * bnv + bnd;
                 if (u < 0.0f)
                     return;
                 float v = hu * cnu + hv * cnv + cnd;
                 if (v < 0.0f)
                     return;
                 if (u + v > 1.0f)
                     return;
                 r.setMax(t);
                 state.setIntersection(primID, u, v);
                 return;
             }
     }
 }
예제 #5
0
        public void intersectPrimitive(Ray r, int primID, IntersectionState state)
        {
            // intersect with bounding sphere
            float qc = ((r.ox * r.ox) + (r.oy * r.oy) + (r.oz * r.oz)) - BOUNDING_RADIUS2;
            float qt = r.getMin();
            if (qc > 0)
            {
                // we are starting outside the sphere, find intersection on the
                // sphere
                float qa = r.dx * r.dx + r.dy * r.dy + r.dz * r.dz;
                float qb = 2 * ((r.dx * r.ox) + (r.dy * r.oy) + (r.dz * r.oz));
                double[] t = Solvers.solveQuadric(qa, qb, qc);
                // early rejection
                if (t == null || t[0] >= r.getMax() || t[1] <= r.getMin())
                    return;
                qt = (float)t[0];
            }
            float dist = float.PositiveInfinity;
            float rox = r.ox + qt * r.dx;
            float roy = r.oy + qt * r.dy;
            float roz = r.oz + qt * r.dz;
            float invRayLength = (float)(1 / Math.Sqrt(r.dx * r.dx + r.dy * r.dy + r.dz * r.dz));
            // now we can start intersection
            while (true)
            {
                float zw = rox;
                float zx = roy;
                float zy = roz;
                float zz = 0;

                float zpw = 1;
                float zpx = 0;
                float zpy = 0;
                float zpz = 0;

                // run several iterations
                float dotz = 0;
                for (int i = 0; i < maxIterations; i++)
                {
                    {
                        // zp = 2 * (z * zp)
                        float nw = zw * zpw - zx * zpx - zy * zpy - zz * zpz;
                        float nx = zw * zpx + zx * zpw + zy * zpz - zz * zpy;
                        float ny = zw * zpy + zy * zpw + zz * zpx - zx * zpz;
                        zpz = 2 * (zw * zpz + zz * zpw + zx * zpy - zy * zpx);
                        zpw = 2 * nw;
                        zpx = 2 * nx;
                        zpy = 2 * ny;
                    }
                    {
                        // z = z*z + c
                        float nw = zw * zw - zx * zx - zy * zy - zz * zz + cw;
                        zx = 2 * zw * zx + cx;
                        zy = 2 * zw * zy + cy;
                        zz = 2 * zw * zz + cz;
                        zw = nw;
                    }
                    dotz = zw * zw + zx * zx + zy * zy + zz * zz;
                    if (dotz > ESCAPE_THRESHOLD)
                        break;

                }
                float normZ = (float)Math.Sqrt(dotz);
                dist = 0.5f * normZ * (float)Math.Log(normZ) / Length(zpw, zpx, zpy, zpz);
                rox += dist * r.dx;
                roy += dist * r.dy;
                roz += dist * r.dz;
                qt += dist;
                if (dist * invRayLength < epsilon)
                    break;
                if (rox * rox + roy * roy + roz * roz > BOUNDING_RADIUS2)
                    return;
            }
            // now test t value again
            if (!r.isInside(qt))
                return;
            if (dist * invRayLength < epsilon)
            {
                // valid hit
                r.setMax(qt);
                state.setIntersection(0, 0, 0);
            }
        }
예제 #6
0
파일: Hair.cs 프로젝트: rzel/sunflowsharp
 public void intersectPrimitive(Ray r, int primID, IntersectionState state)
 {
     int hair = primID / numSegments;
     int line = primID % numSegments;
     int vRoot = hair * 3 * (numSegments + 1);
     int v0 = vRoot + line * 3;
     int v1 = v0 + 3;
     float vx = points[v1 + 0] - points[v0 + 0];
     float vy = points[v1 + 1] - points[v0 + 1];
     float vz = points[v1 + 2] - points[v0 + 2];
     float ux = r.dy * vz - r.dz * vy;
     float uy = r.dz * vx - r.dx * vz;
     float uz = r.dx * vy - r.dy * vx;
     float nx = uy * vz - uz * vy;
     float ny = uz * vx - ux * vz;
     float nz = ux * vy - uy * vx;
     float tden = 1 / (nx * r.dx + ny * r.dy + nz * r.dz);
     float tnum = nx * (points[v0 + 0] - r.ox) + ny * (points[v0 + 1] - r.oy) + nz * (points[v0 + 2] - r.oz);
     float t = tnum * tden;
     if (r.isInside(t))
     {
         int vn = hair * (numSegments + 1) + line;
         float px = r.ox + t * r.dx;
         float py = r.oy + t * r.dy;
         float pz = r.oz + t * r.dz;
         float qx = px - points[v0 + 0];
         float qy = py - points[v0 + 1];
         float qz = pz - points[v0 + 2];
         float q = (vx * qx + vy * qy + vz * qz) / (vx * vx + vy * vy + vz * vz);
         if (q <= 0)
         {
             // don't included rounded tip at root
             if (line == 0)
                 return;
             float dx = points[v0 + 0] - px;
             float dy = points[v0 + 1] - py;
             float dz = points[v0 + 2] - pz;
             float d2 = dx * dx + dy * dy + dz * dz;
             float width = getWidth(vn);
             if (d2 < (width * width * 0.25f))
             {
                 r.setMax(t);
                 state.setIntersection(primID, 0, 0);
             }
         }
         else if (q >= 1)
         {
             float dx = points[v1 + 0] - px;
             float dy = points[v1 + 1] - py;
             float dz = points[v1 + 2] - pz;
             float d2 = dx * dx + dy * dy + dz * dz;
             float width = getWidth(vn + 1);
             if (d2 < (width * width * 0.25f))
             {
                 r.setMax(t);
                 state.setIntersection(primID, 0, 1);
             }
         }
         else
         {
             float dx = points[v0 + 0] + q * vx - px;
             float dy = points[v0 + 1] + q * vy - py;
             float dz = points[v0 + 2] + q * vz - pz;
             float d2 = dx * dx + dy * dy + dz * dz;
             float width = (1 - q) * getWidth(vn) + q * getWidth(vn + 1);
             if (d2 < (width * width * 0.25f))
             {
                 r.setMax(t);
                 state.setIntersection(primID, 0, q);
             }
         }
     }
 }
예제 #7
0
        public void intersectPrimitive(Ray r, int primID, IntersectionState state)
        {
            // ray/bilinear patch intersection adapted from "Production Rendering:
            // Design and Implementation" by Ian Stephenson (Ed.)
            int quad = 4 * primID;
            int p0 = 3 * quads[quad + 0];
            int p1 = 3 * quads[quad + 1];
            int p2 = 3 * quads[quad + 2];
            int p3 = 3 * quads[quad + 3];
            // transform patch into Hilbert space
            float[] A = {
                points[p2 + 0] - points[p3 + 0] - points[p1 + 0] + points[p0 + 0],
                points[p2 + 1] - points[p3 + 1] - points[p1 + 1] + points[p0 + 1],
                points[p2 + 2] - points[p3 + 2] - points[p1 + 2] + points[p0 + 2] };
            float[] B = { points[p1 + 0] - points[p0 + 0],
                points[p1 + 1] - points[p0 + 1],
                points[p1 + 2] - points[p0 + 2] };
            float[] C = { points[p3 + 0] - points[p0 + 0],
                points[p3 + 1] - points[p0 + 1],
                points[p3 + 2] - points[p0 + 2] };
            float[] R = { r.ox - points[p0 + 0], r.oy - points[p0 + 1],
                r.oz - points[p0 + 2] };
            float[] Q = { r.dx, r.dy, r.dz };

            // pick major direction
            float absqx = Math.Abs(r.dx);
            float absqy = Math.Abs(r.dy);
            float absqz = Math.Abs(r.dz);

            int X = 0, Y = 1, Z = 2;
            if (absqx > absqy && absqx > absqz)
            {
                // X = 0, Y = 1, Z = 2
            }
            else if (absqy > absqz)
            {
                // X = 1, Y = 0, Z = 2
                X = 1;
                Y = 0;
            }
            else
            {
                // X = 2, Y = 1, Z = 0
                X = 2;
                Z = 0;
            }

            float Cxz = C[X] * Q[Z] - C[Z] * Q[X];
            float Cyx = C[Y] * Q[X] - C[X] * Q[Y];
            float Czy = C[Z] * Q[Y] - C[Y] * Q[Z];
            float Rxz = R[X] * Q[Z] - R[Z] * Q[X];
            float Ryx = R[Y] * Q[X] - R[X] * Q[Y];
            float Rzy = R[Z] * Q[Y] - R[Y] * Q[Z];
            float Bxy = B[X] * Q[Y] - B[Y] * Q[X];
            float Byz = B[Y] * Q[Z] - B[Z] * Q[Y];
            float Bzx = B[Z] * Q[X] - B[X] * Q[Z];
            float a = A[X] * Byz + A[Y] * Bzx + A[Z] * Bxy;
            if (a == 0)
            {
                // setup for linear equation
                float b = B[X] * Czy + B[Y] * Cxz + B[Z] * Cyx;
                float c = C[X] * Rzy + C[Y] * Rxz + C[Z] * Ryx;
                float u = -c / b;
                if (u >= 0 && u <= 1)
                {
                    float v = (u * Bxy + Ryx) / Cyx;
                    if (v >= 0 && v <= 1)
                    {
                        float t = (B[X] * u + C[X] * v - R[X]) / Q[X];
                        if (r.isInside(t))
                        {
                            r.setMax(t);
                            state.setIntersection(primID, u, v);
                        }
                    }
                }
            }
            else
            {
                // setup for quadratic equation
                float b = A[X] * Rzy + A[Y] * Rxz + A[Z] * Ryx + B[X] * Czy + B[Y] * Cxz + B[Z] * Cyx;
                float c = C[X] * Rzy + C[Y] * Rxz + C[Z] * Ryx;
                float discrim = b * b - 4 * a * c;
                // reject trivial cases
                if (c * (a + b + c) > 0 && (discrim < 0 || a * c < 0 || b / a > 0 || b / a < -2))
                    return;
                // solve quadratic
                float q = b > 0 ? -0.5f * (b + (float)Math.Sqrt(discrim)) : -0.5f * (b - (float)Math.Sqrt(discrim));
                // check first solution
                float Axy = A[X] * Q[Y] - A[Y] * Q[X];
                float u = q / a;
                if (u >= 0 && u <= 1)
                {
                    float d = u * Axy - Cyx;
                    float v = -(u * Bxy + Ryx) / d;
                    if (v >= 0 && v <= 1)
                    {
                        float t = (A[X] * u * v + B[X] * u + C[X] * v - R[X]) / Q[X];
                        if (r.isInside(t))
                        {
                            r.setMax(t);
                            state.setIntersection(primID, u, v);
                        }
                    }
                }
                u = c / q;
                if (u >= 0 && u <= 1)
                {
                    float d = u * Axy - Cyx;
                    float v = -(u * Bxy + Ryx) / d;
                    if (v >= 0 && v <= 1)
                    {
                        float t = (A[X] * u * v + B[X] * u + C[X] * v - R[X]) / Q[X];
                        if (r.isInside(t))
                        {
                            r.setMax(t);
                            state.setIntersection(primID, u, v);
                        }
                    }
                }
            }
        }