Пример #1
0
        /// standard object services ---------------------------------------------------
        public Scene(StreamReader infile, Vector eyePosition)
        {
            // read and condition default sky and ground values
            skyEmission = new Vector(infile);
            groundReflection = new Vector(infile);

            skyEmission = skyEmission.Clamp(Vector.ZERO, skyEmission);
            groundReflection = skyEmission * groundReflection.Clamp(Vector.ZERO, Vector.ONE);
            triangles = new List<Triangle>();
            emitters = new List<Triangle>();

            // read objects
            while (infile.EndOfStream == false)
                {
                Triangle t = new Triangle(infile);
                if (t.Area != 0)
                    triangles.Add(t);
                }

            // find emitting triangles
            foreach (Triangle t in triangles)
                {
                if (!t.Emitivity.IsZero() && (t.Area > 0.0f))
                    {
                    emitters.Add(t);
                    if (emitters.Count >= (1 << MAX_EMITTERS_P))
                        break;
                    }
                }

            // make index
            octtree = new Spatial(eyePosition, triangles);
        }
Пример #2
0
        public Vector GetRadiance(Vector rayOrigin, Vector rayDirection, Sampler random, Triangle lastHit)
        {
            // intersect ray with scene
            Triangle pHitObject;
            Vector hitPosition;
            scene.GetIntersection(rayOrigin, rayDirection, lastHit, out pHitObject, out hitPosition);

            Vector radiance;
            if (null != pHitObject)
            {
                // make surface point of intersection
                SurfacePoint surfacePoint = new SurfacePoint(pHitObject, hitPosition);

                // local emission only for first-hit
                if (lastHit != null)
                    radiance = Vector.ZERO;
                else
                    radiance = surfacePoint.GetEmission(rayOrigin, -rayDirection, false);

                // add emitter sample
                radiance = radiance + SampleEmitters(rayDirection, surfacePoint, random);

                // add recursive reflection
                //
                // single hemisphere sample, ideal diffuse BRDF:
                // reflected = (inradiance * pi) * (cos(in) / pi * color) * reflectance
                // -- reflectance magnitude is 'scaled' by the russian roulette, cos is
                // importance sampled (both done by SurfacePoint), and the pi and 1/pi
                // cancel out
                Vector nextDirection;
                Vector color;
                // check surface bounces ray, recurse
                if (surfacePoint.GetNextDirection(random, -rayDirection, out nextDirection, out color))
                    radiance = radiance + (color * GetRadiance(surfacePoint.Position, nextDirection, random, surfacePoint.Item));
            }
            else // no hit: default/background scene emission
                radiance = scene.GetDefaultEmission(-rayDirection);

            return radiance;
        }
Пример #3
0
        public void GetIntersection(
            Vector rayOrigin, Vector rayDirection, Triangle lastHit,
            out Triangle pHitObject, out Vector hitPosition, Vector pStart)
        {
            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
                Vector cellPosition = new Vector(pStart);
                for (; ; )
                {
                    if (null != spatial[subCell])
                    {
                        // intersect subcell
                        spatial[subCell].GetIntersection(rayOrigin, rayDirection, lastHit, out pHitObject, out hitPosition, cellPosition);
                        // 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] = (face - rayOrigin[i]) / 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 (Triangle item in triangles)
                {
                    // avoid false intersection with surface just come from
                    if (item != lastHit)
                    {
                        // intersect ray with item, and inspect if nearest so far
                        float distance = float.MaxValue;
                        if (item.GetIntersection(rayOrigin, rayDirection, ref distance) && (distance < nearestDistance))
                        {
                            // check intersection is inside cell bound (with tolerance)
                            Vector hit = rayOrigin + (rayDirection * distance);
                            float t = Triangle.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;
                            }
                        }
                    }
                }
            }
        }
Пример #4
0
        public void GetEmitter(Sampler random, out Vector position, out Triangle triangle)
        {
            if (emitters.Count != 0)
                {
                // select emitter
                // not using lower bits, by treating the random as fixed-point i.f bits
                int index = ((((int)(int.MaxValue*random.GetNextSample()) & ((1 << MAX_EMITTERS_P) - 1)) * emitters.Count) >> MAX_EMITTERS_P);

                // get position on triangle
                position = emitters[index].GetSamplePoint(random);
                triangle = emitters[index];
                }
            else
                {
                position = Vector.ZERO;
                triangle = null;
                }
        }
Пример #5
0
        public void GetIntersection(
		   Vector rayOrigin, Vector rayDirection, Triangle lastHit,
		   out Triangle pHitObject, out Vector hitPosition)
        {
            octtree.GetIntersection(rayOrigin, rayDirection, lastHit, out pHitObject, out hitPosition, null);
        }