public bool trace(RayContext rayContext) { double maxt = rayContext.ray.maxt; bool haveIntersection = false; foreach (GeomPrimitive primitive in m_primitives) { if (rayContext.ignorePrimitive == primitive) continue; //skip this primitive IntersectionData hitData = new IntersectionData(); if (primitive.intersect(rayContext.ray, hitData)) { if (maxt > hitData.hitT && hitData.hitT > rayContext.ray.mint) { maxt = hitData.hitT; rayContext.hitData = hitData; rayContext.hitData.hitPrimitive = primitive; haveIntersection = true; } if (haveIntersection) { rayContext.hitData.hitPos = rayContext.ray.p + rayContext.ray.dir * rayContext.hitData.hitT; } } }//foreach return haveIntersection; }
public override bool intersect( Ray ray, IntersectionData hitData ) { Vector3 d = ray.dir; Vector3 p = ray.p; //лъчът преминава в локални координати на сферата p = p - center; double A = d * d; double B = 2 * (d * p); double C = (p * p) - (radius * radius); //връщаме лъча в коодинати на сцената p = p + center; double D = (B * B) - (4 * A * C); if (D < 0) return false; else D = System.Math.Sqrt(D); double t0 = (-B - D) / (2 * A); double t1 = (-B + D) / (2 * A); if (t1 < t0) t0 = t1; hitData.hitT = t0; Vector3 wp = p + d * t0; hitData.hitPos = wp; hitData.hitNormal = wp - center; hitData.hitNormal.normalize(); double u = (System.Math.PI + System.Math.Atan2(wp.z - center.z, wp.x - center.x)) / (System.Math.PI * 2); double v = 1.0 - ((System.Math.PI / 2) + System.Math.Asin((wp.y - center.y) / radius)) / System.Math.PI; hitData.textureUVW = new Vector3(u, v, 0); return true; }
public abstract bool intersect( Ray ray, IntersectionData hitData );
public override bool intersect( Ray ray, IntersectionData hitData ) { Vector3 e1, e2; e1 = v[1] - v[0];// e1 = edge v0 to v1 e2 = v[2] - v[0];// e2 = edge v0 to v2 Vector3 pvec = ray.dir ^ e2;// pvec = cross(dir,e2) double det = e1 * pvec;// determinant = dot(e1,pvec) if (det < 1e-6f && det > -1e-6f) return false; // if det close to zero -> ray lies in the plane double inv_det = 1.0f / det;// inverse determinant Vector3 tvec = ray.p - v[0];// distance v0 to ray origin double u = inv_det * (tvec * pvec);// u = dot(tvec,pvec) / det if (u < -1e-6f || u > (1.0f + 1e-6f)) return false;// if u outside triangle return Vector3 qvec = tvec ^ e1;// qvec = cross(tvec,e1) double t = inv_det * (e2 * qvec);// t = dot(e2,qvec) / det if (t < ray.mint || t > ray.maxt) return false;// return false if t is outside range double uvV = inv_det * (ray.dir * qvec);// v = dot(dir,qvec) / det if (uvV < -1e-6f || (u + uvV) > (1.0f + 1e-6f)) return false;// if v outside triangle return hitData.hitT = t; hitData.hitNormal = e1 ^ e2; hitData.hitNormal.normalize(); hitData.textureUVW = ((1 - u - uvV) * tc[0]) + (u * tc[1]) + (uvV * tc[2]); hitData.shaderID = shaderID; return true; }
public void GetIntersection( Vector3 rayOrigin, Vector3 rayDirection, GeomPrimitive lastHit, out GeomPrimitive pHitObject, Vector3 pStart, RayContext rayContext) { //hitPosition = null; pHitObject = null; // is branch: step through subcells and recurse if (isBranch) { //if (pStart == null) // pStart = rayOrigin; // find which subcell holds ray origin (ray origin is inside cell) int subCell = 0; for (int i = 3; i-- > 0; ) { // compare dimension with center if (pStart[i] >= ((bound[i] + bound[i + 3]) * 0.5f)) subCell |= 1 << i; } // step through intersected subcells Vector3 cellPosition = new Vector3(pStart); for (; ; ) { if (null != spatial[subCell]) { // intersect subcell spatial[subCell].GetIntersection(rayOrigin, rayDirection, lastHit, out pHitObject, cellPosition, rayContext); // exit if item hit if (null != pHitObject) break; } // find next subcell ray moves to // (by finding which face of the corner ahead is crossed first) int axis = 2; float[] step = new float[3]; // todo - move this allocation? for (int i = 3; i-- > 0; axis = step[i] < step[axis] ? i : axis) { bool high = ((subCell >> i) & 1) != 0; float face = (rayDirection[i] < 0.0f) ^ high ? bound[i + ((high ? 1 : 0) * 3)] : (bound[i] + bound[i + 3]) * 0.5f; // distance to face // (div by zero produces infinity, which is later discarded) step[i] = (float)(face - rayOrigin[i]) / (float)rayDirection[i]; } // leaving branch if: subcell is low and direction is negative, // or subcell is high and direction is positive if ((((subCell >> axis) & 1) != 0) ^ (rayDirection[axis] < 0.0f)) break; // move to (outer face of) next subcell cellPosition = rayOrigin + (rayDirection * step[axis]); subCell = subCell ^ (1 << axis); } } else { // is leaf: exhaustively intersect contained items //float nearestDistance = float.MaxValue; // step through items foreach (GeomPrimitive item in triangles) { if (rayContext.ignorePrimitive == item) continue; //skip this primitive if (item == lastHit) continue; //skip this primitive IntersectionData hitData = new IntersectionData(); if (item.intersect(rayContext.ray, hitData)) { // check intersection is inside cell bound (with tolerance) Vector3 hit = rayOrigin + (rayDirection * hitData.hitT); float t = TOLERANCE; if ((bound[0] - hit[0] <= t) && (hit[0] - bound[3] <= t) && (bound[1] - hit[1] <= t) && (hit[1] - bound[4] <= t) && (bound[2] - hit[2] <= t) && (hit[2] - bound[5] <= t)) { pHitObject = item; //nearestDistance = distance; //hitPosition = hit; rayContext.hitData = hitData; rayContext.hitData.hitPrimitive = item; rayContext.hitData.hitPos = rayContext.ray.p + rayContext.ray.dir * rayContext.hitData.hitT; rayContext.hitData.hasIntersection = true; } } } } }