public IntersectionData()
 {
     hitT = double.MaxValue;
     hitPos = new Vector3();
     hitNormal = new Vector3();
     hitUV = new Vector3();
     hitPrimitive = null;
     hasIntersection = false;
     textureUVW = new Vector3();
     shaderID = 0;
 }
        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;
                        }
                    }

                }
            }
        }
 public void removePrimitive(GeomPrimitive primitive)
 {
     primitives.Remove(primitive);
 }
 public void addPrimitive(GeomPrimitive primitive)
 {
     primitives.Add(primitive);
 }