Esempio n. 1
0
 /// <summary>
 /// Returns intensity (incl. color) of the source contribution to the given scene point.
 /// Internal integration support.
 /// </summary>
 /// <param name="intersection">Scene point (only world coordinates and normal vector are needed).</param>
 /// <param name="rank">Rank of this sample, 0 <= rank < total (for integration).</param>
 /// <param name="total">Total number of samples (for integration).</param>
 /// <param name="rnd">Global (per-thread) instance of the random generator.</param>
 /// <param name="dir">Direction to the source is set here (zero vector for omnidirectional source).</param>
 /// <returns>Intensity vector in current color space or null if the point is not lit.</returns>
 public double[] GetIntensity( Intersection intersection, int rank, int total, RandomJames rnd, out Vector3d dir )
 {
     return GetIntensity( intersection, out dir );
 }
Esempio n. 2
0
 /// <summary>
 /// Complete all relevant items in the given Intersection object.
 /// </summary>
 /// <param name="inter">Intersection instance to complete.</param>
 public virtual void CompleteIntersection( Intersection inter )
 {
 }
Esempio n. 3
0
        /// <summary>
        /// Returns intensity (incl. color) of the source contribution to the given scene point.
        /// Simple variant, w/o an integration support.
        /// </summary>
        /// <param name="intersection">Scene point (only world coordinates and normal vector are needed).</param>
        /// <param name="dir">Direction to the source is set here (zero vector for omnidirectional source). Not normalized!</param>
        /// <returns>Intensity vector in current color space or null if the point is not lit.</returns>
        public virtual double[] GetIntensity( Intersection intersection, out Vector3d dir )
        {
            dir = position - intersection.CoordWorld;
              if ( Vector3d.Dot( dir, intersection.Normal ) <= 0.0 )
            return null;

              return intensity;
        }
Esempio n. 4
0
        /// <summary>
        /// Returns intensity (incl. color) of the source contribution to the given scene point.
        /// Internal integration support.
        /// </summary>
        /// <param name="intersection">Scene point (only world coordinates and normal vector are needed).</param>
        /// <param name="rank">Rank of this sample, 0 <= rank < total (for integration).</param>
        /// <param name="total">Total number of samples (for integration).</param>
        /// <param name="rnd">Global (per-thread) instance of the random generator.</param>
        /// <param name="dir">Direction to the source is set here (zero vector for omnidirectional source). Not normalized!</param>
        /// <returns>Intensity vector in current color space or null if the point is not lit.</returns>
        public override double[] GetIntensity( Intersection intersection, int rank, int total, RandomJames rnd, out Vector3d dir )
        {
            if ( rnd == null )
            return GetIntensity( intersection, out dir );

              SamplingState ss;
              lock ( states )
              {
            if ( !states.TryGetValue( rnd.GetHashCode(), out ss ) )
            {
              ss = new SamplingState( this, rnd );
              states.Add( rnd.GetHashCode(), ss );
            }
              }

              // generate a [new] sample:
              ss.generateSample( rank, total );
              dir = ss.sample - intersection.CoordWorld;
              if ( Vector3d.Dot( dir, intersection.Normal ) <= 0.0 )
            return null;

              if ( Dim == null || Dim.Length < 3 ) return intensity;

              double dist = dir.Length;
              double dimCoef = 1.0 / (Dim[0] + dist * (Dim[1] + dist * Dim[2]));
              int bands = intensity.Length;
              double[] result = new double[ bands ];
              for ( int i = 0; i < bands; i++ )
            result[ i ] = intensity[ i ] * dimCoef;

              return result;
        }
Esempio n. 5
0
 public double[] ColorReflection( Intersection intersection, Vector3d input, Vector3d output, ReflectionComponent comp )
 {
     return ColorReflection( intersection.Material, intersection.Normal, input, output, comp );
 }
Esempio n. 6
0
 /// <summary>
 /// Returns intensity (incl. color) of the source contribution to the given scene point.
 /// Simple variant, w/o an integration support.
 /// </summary>
 /// <param name="intersection">Scene point (only world coordinates and normal vector are needed).</param>
 /// <param name="dir">Direction to the source is set here (zero vector for omnidirectional source).</param>
 /// <returns>Intensity vector in current color space or null if the point is not lit.</returns>
 public double[] GetIntensity( Intersection intersection, out Vector3d dir )
 {
     dir = Vector3d.Zero;
       return intensity;
 }
Esempio n. 7
0
        /// <summary>
        /// Apply the relevant value-modulation in the given Intersection instance.
        /// Simple variant, w/o an integration support.
        /// </summary>
        /// <param name="inter">Data object to modify.</param>
        /// <returns>Hash value (texture signature) for adaptive subsampling.</returns>
        public long Apply( Intersection inter )
        {
            double u = inter.TextureCoord.X * Fu;
              double v = inter.TextureCoord.Y * Fv;

              long ui = (long)Math.Floor( u );
              long vi = (long)Math.Floor( v );

              if ( ((ui + vi) & 1) != 0 )
            Array.Copy( Color2, inter.SurfaceColor, Math.Min( Color2.Length, inter.SurfaceColor.Length ) );

              return (ui + RandomStatic.numericRecipes( vi ));
        }
Esempio n. 8
0
 /// <summary>
 /// Apply the relevant value-modulation in the given Intersection instance.
 /// Internal integration support.
 /// </summary>
 /// <param name="inter">Data object to modify.</param>
 /// <param name="rank">Rank of this sample, 0 <= rank < total (for integration).</param>
 /// <param name="total">Total number of samples (for integration).</param>
 /// <param name="rnd">Global (per-thread) instance of the random generator.</param>
 /// <returns>Hash value (texture signature) for adaptive subsampling.</returns>
 public long Apply( Intersection inter, int rank, int total, RandomJames rnd )
 {
     return Apply( inter );
 }
        /// <summary>
        /// Computes the complete intersection of the given ray with the object.
        /// </summary>
        /// <param name="p0">Ray origin.</param>
        /// <param name="p1">Ray direction vector.</param>
        /// <returns>Sorted list of intersection records.</returns>
        public override LinkedList <Intersection> Intersect(Vector3d p0, Vector3d p1)
        {
            if (children == null || children.Count == 0)
            {
                return(null);
            }

            if (BoundingVolume != null)
            {
                countBoundingBoxes++;
                if (BoundingVolume.Intersect(p0, p1) < -0.5)
                {
                    return(null);
                }
            }

            LinkedList <Intersection> result = null;
            LinkedList <Intersection> left   = null; // I'm going to reuse these two..

            bool leftOp = true;                      // the 1st pass => left operand

            foreach (ISceneNode child in children)
            {
                Vector3d origin = Vector3d.TransformPosition(p0, child.FromParent);
                Vector3d dir    = Vector3d.TransformVector(p1, child.FromParent);
                // ray in local child's coords: [ origin, dir ]

                LinkedList <Intersection> partial = child.Intersect(origin, dir);
                if (partial == null)
                {
                    partial = leftOp ? new LinkedList <Intersection>() : emptyResult;
                }
                else
                if (child is ISolid)
                {
                    Intersection.countIntersections += partial.Count;
                }

                if (leftOp)
                {
                    leftOp = false;
                    result = partial;
                    left   = new LinkedList <Intersection>();
                }
                else
                {
                    if (trivial && partial.Count == 0)
                    {
                        continue;
                    }

                    // resolve one binary operation (result := left # partial):
                    {
                        LinkedList <Intersection> tmp = left;
                        left   = result;
                        result = tmp;
                    }
                    // result .. empty so far
                    result.Clear();

                    double       lowestT    = Double.NegativeInfinity;
                    Intersection leftFirst  = (left.First == null) ? null : left.First.Value;
                    Intersection rightFirst = (partial.First == null) ? null : partial.First.Value;
                    // initial inside status values:
                    bool insideLeft   = (leftFirst != null && !leftFirst.Enter);
                    bool insideRight  = (rightFirst != null && !rightFirst.Enter);
                    bool insideResult = bop(insideLeft, insideRight);
                    // merge behavior:
                    bool minLeft  = (leftFirst != null && leftFirst.T == lowestT);
                    bool minRight = (rightFirst != null && rightFirst.T == lowestT);

                    while (leftFirst != null || rightFirst != null)
                    {
                        double leftVal  = (leftFirst != null) ? leftFirst.T : double.PositiveInfinity;
                        double rightVal = (rightFirst != null) ? rightFirst.T : double.PositiveInfinity;
                        lowestT = Math.Min(leftVal, rightVal);
                        Debug.Assert(!Double.IsInfinity(lowestT));

                        minLeft  = leftVal == lowestT;
                        minRight = rightVal == lowestT;

                        Intersection first = null;
                        if (minRight)
                        {
                            first = rightFirst;
                            partial.RemoveFirst();
                            rightFirst  = (partial.First == null) ? null : partial.First.Value;
                            insideRight = first.Enter;
                        }
                        if (minLeft)
                        {
                            first = leftFirst;
                            left.RemoveFirst();
                            leftFirst  = (left.First == null) ? null : left.First.Value;
                            insideLeft = first.Enter;
                        }
                        bool newResult = bop(insideLeft, insideRight);

                        if (newResult != insideResult)
                        {
                            first.Enter = insideResult = newResult;
                            result.AddLast(first);
                        }
                    }
                }
                if (shortCurcuit && result.Count == 0)
                {
                    break;
                }
            }

            return(result);
        }
 /// <summary>
 /// Complete all relevant items in the given Intersection object.
 /// </summary>
 /// <param name="inter">Intersection instance to complete.</param>
 public virtual void CompleteIntersection(Intersection inter)
 {
 }
Esempio n. 11
0
        /// <summary>
        /// Canonic sort order: by a T value.
        /// </summary>
        /// <param name="obj">Instance to be compared to..</param>
        /// <returns>-1, 0 or 1.</returns>
        public int CompareTo(object obj)
        {
            Intersection i = (Intersection)obj;

            return(T.CompareTo(i.T));
        }
Esempio n. 12
0
        /// <summary>
        /// Recursive shading function - computes color contribution of the given ray (shot from the
        /// origin 'p0' into direction vector 'p1''). Recursion is stopped
        /// by a hybrid method: 'importance' and 'level' are checked.
        /// Internal integration support.
        /// </summary>
        /// <param name="level">Current recursion depth.</param>
        /// <param name="importance">Importance of the current ray.</param>
        /// <param name="p0">Ray origin.</param>
        /// <param name="p1">Ray direction vector.</param>
        /// <param name="color">Result color.</param>
        /// <returns>Hash-value (ray sub-signature) used for adaptive subsampling.</returns>
        protected override long shade(int level, double importance, ref Vector3d p0, ref Vector3d p1,
                                      double[] color)
        {
            int bands = color.Length;
            LinkedList <Intersection> intersections = scene.Intersectable.Intersect(p0, p1);

            Intersection.countRays++;
            Intersection i = Intersection.FirstIntersection(intersections, ref p1);
            int          b;

            if (i == null)      // no intersection -> background color
            {
                Array.Copy(scene.BackgroundColor, color, bands);
                return(1L);
            }

            // there was at least one intersection
            i.Complete();

            // hash code for adaptive supersampling:
            long hash = i.Solid.GetHashCode();

            // apply all the textures fist..
            if (i.Textures != null)
            {
                foreach (ITexture tex in i.Textures)
                {
                    hash = hash * HASH_TEXTURE + tex.Apply(i);
                }
            }

            p1 = -p1; // viewing vector
            p1.Normalize();

            if (scene.Sources == null || scene.Sources.Count < 1)
            {
                // no light sources at all
                Array.Copy(i.SurfaceColor, color, bands);
            }
            else
            {
                // apply the reflectance model for each source
                i.Material       = (IMaterial)i.Material.Clone();
                i.Material.Color = i.SurfaceColor;
                Array.Clear(color, 0, bands);

                foreach (ILightSource source in scene.Sources)
                {
                    Vector3d dir;
                    double[] intensity = source.GetIntensity(i, out dir);
                    if (intensity != null)
                    {
                        if (DoShadows && dir != Vector3d.Zero)
                        {
                            intersections = scene.Intersectable.Intersect(i.CoordWorld, dir);
                            Intersection.countRays++;
                            Intersection si = Intersection.FirstIntersection(intersections, ref dir);
                            // Better shadow testing: intersection between 0.0 and 1.0 kills the lighting
                            if (si != null && !si.Far(1.0, ref dir))
                            {
                                continue;
                            }
                        }

                        double[] reflection = i.ReflectanceModel.ColorReflection(i, dir, p1, ReflectionComponent.ALL);
                        if (reflection != null)
                        {
                            for (b = 0; b < bands; b++)
                            {
                                color[b] += intensity[b] * reflection[b];
                            }
                            hash = hash * HASH_LIGHT + source.GetHashCode();
                        }
                    }
                }
            }

            // check the recursion depth:
            if (level++ >= MaxLevel ||
                !DoReflections && !DoRefractions)
            {
                return(hash);               // no further recursion
            }
            Vector3d r;
            double   maxK;

            double[] comp = new double[bands];
            double   newImportance;

            if (DoReflections)
            {
                // !!!{{ TODO: cast the reflected ray to a bit random direction (variance should be based on Phong material's exponent H)..
                Geometry.SpecularReflection(ref i.Normal, ref p1, out r);
                double[] ks = i.ReflectanceModel.ColorReflection(i, p1, r, ReflectionComponent.SPECULAR_REFLECTION);
                // !!!}}

                if (ks != null)
                {
                    maxK = ks[0];
                    for (b = 1; b < bands; b++)
                    {
                        if (ks[b] > maxK)
                        {
                            maxK = ks[b];
                        }
                    }

                    newImportance = importance * maxK;
                    if (newImportance >= MinImportance) // do compute the reflected ray
                    {
                        hash += HASH_REFLECT * shade(level, newImportance, ref i.CoordWorld, ref r, comp);
                        for (b = 0; b < bands; b++)
                        {
                            color[b] += ks[b] * comp[b];
                        }
                    }
                }
            }

            if (DoRefractions)                 // trying to shoot a refracted ray..
            {
                maxK          = i.Material.Kt; // simple solution, no influence of reflectance model yet
                newImportance = importance * maxK;
                if (newImportance < MinImportance)
                {
                    return(hash);
                }

                // refracted ray:
                if ((r = Geometry.SpecularRefraction(i.Normal, i.Material.n, p1)) == null)
                {
                    return(hash);
                }

                // !!!{{ TODO: tweak the refracted ray as well?
                // !!!}}

                hash += HASH_REFRACT * shade(level, newImportance, ref i.CoordWorld, ref r, comp);
                for (b = 0; b < bands; b++)
                {
                    color[b] += maxK * comp[b];
                }
            }

            return(hash);
        }
Esempio n. 13
0
        /// <summary>
        /// Recursive shading function - computes color contribution of the given ray (shot from the
        /// origin 'p0' into direction vector 'p1''). Recursion is stopped
        /// by a hybrid method: 'importance' and 'level' are checked.
        /// Internal integration support.
        /// </summary>
        /// <param name="level">Current recursion depth.</param>
        /// <param name="importance">Importance of the current ray.</param>
        /// <param name="p0">Ray origin.</param>
        /// <param name="p1">Ray direction vector.</param>
        /// <param name="color">Result color.</param>
        /// <returns>Hash-value (ray sub-signature) used for adaptive subsampling.</returns>
        protected virtual long shade(int level,
                                     double importance,
                                     ref Vector3d p0,
                                     ref Vector3d p1,
                                     double[] color)
        {
            Vector3d direction = p1;

            int bands = color.Length;
            LinkedList <Intersection> intersections = scene.Intersectable.Intersect(p0, p1);

            // If the ray is primary, increment both counters
            Statistics.IncrementRaysCounters(1, level == 0);

            Intersection i = Intersection.FirstIntersection(intersections, ref p1);
            int          b;

            if (i == null)
            {
                // No intersection -> background color
                rayRegisterer?.RegisterRay(AbstractRayRegisterer.RayType.rayVisualizerNormal, level, p0, direction * 100000);

                Array.Copy(scene.BackgroundColor, color, bands);
                return(1L);
            }

            // There was at least one intersection
            i.Complete();

            rayRegisterer?.RegisterRay(AbstractRayRegisterer.RayType.unknown, level, p0, i);

            // Hash code for adaptive supersampling
            long hash = i.Solid.GetHashCode();

            // Apply all the textures first
            if (i.Textures != null)
            {
                foreach (ITexture tex in i.Textures)
                {
                    hash = hash * HASH_TEXTURE + tex.Apply(i);
                }
            }

            if (MT.pointCloudCheckBox && !MT.pointCloudSavingInProgress && !MT.singleRayTracing)
            {
                foreach (Intersection intersection in intersections)
                {
                    if (!intersection.completed)
                    {
                        intersection.Complete();
                    }

                    if (intersection.Textures != null && !intersection.textureApplied)
                    {
                        foreach (ITexture tex in intersection.Textures)
                        {
                            tex.Apply(intersection);
                        }
                    }

                    double[] vertexColor = new double[3];
                    Array.Copy(intersection.SurfaceColor, vertexColor, vertexColor.Length);
                    Master.singleton?.pointCloud?.AddToPointCloud(intersection.CoordWorld, vertexColor, intersection.Normal, MT.threadID);
                }
            }

            p1 = -p1; // viewing vector
            p1.Normalize();

            if (scene.Sources == null || scene.Sources.Count < 1)
            {
                // No light sources at all.
                Array.Copy(i.SurfaceColor, color, bands);
            }
            else
            {
                // Apply the reflectance model for each source.
                i.Material       = (IMaterial)i.Material.Clone();
                i.Material.Color = i.SurfaceColor;
                Array.Clear(color, 0, bands);

                foreach (ILightSource source in scene.Sources)
                {
                    double[] intensity = source.GetIntensity(i, out Vector3d dir);

                    if (MT.singleRayTracing && source.position != null)
                    {
                        // Register shadow ray for RayVisualizer.
                        rayRegisterer?.RegisterRay(AbstractRayRegisterer.RayType.rayVisualizerShadow, i.CoordWorld, (Vector3d)source.position);
                    }

                    if (intensity != null)
                    {
                        if (DoShadows && dir != Vector3d.Zero)
                        {
                            intersections = scene.Intersectable.Intersect(i.CoordWorld, dir);
                            Statistics.allRaysCount++;
                            Intersection si = Intersection.FirstIntersection(intersections, ref dir);
                            // Better shadow testing: intersection between 0.0 and 1.0 kills the lighting.
                            if (si != null && !si.Far(1.0, ref dir))
                            {
                                continue;
                            }
                        }

                        double[] reflection = i.ReflectanceModel.ColorReflection(i, dir, p1, ReflectionComponent.ALL);
                        if (reflection != null)
                        {
                            for (b = 0; b < bands; b++)
                            {
                                color[b] += intensity[b] * reflection[b];
                            }
                            hash = hash * HASH_LIGHT + source.GetHashCode();
                        }
                    }
                }
            }

            // Check the recursion depth.
            if (level++ >= MaxLevel || !DoReflections && !DoRefractions)
            {
                // No further recursion.
                return(hash);
            }

            Vector3d r;
            double   maxK;

            double[] comp = new double[bands];
            double   newImportance;

            if (DoReflections)
            {
                // Shooting a reflected ray.
                Geometry.SpecularReflection(ref i.Normal, ref p1, out r);
                double[] ks = i.ReflectanceModel.ColorReflection(i, p1, r, ReflectionComponent.SPECULAR_REFLECTION);
                if (ks != null)
                {
                    maxK = ks[0];
                    for (b = 1; b < bands; b++)
                    {
                        if (ks[b] > maxK)
                        {
                            maxK = ks[b];
                        }
                    }

                    newImportance = importance * maxK;
                    if (newImportance >= MinImportance)
                    {
                        // Do compute the reflected ray.
                        hash += HASH_REFLECT * shade(level, newImportance, ref i.CoordWorld, ref r, comp);
                        for (b = 0; b < bands; b++)
                        {
                            color[b] += ks[b] * comp[b];
                        }
                    }
                }
            }

            if (DoRefractions)
            {
                // Shooting a refracted ray.
                maxK          = i.Material.Kt; // simple solution - no influence of reflectance model yet
                newImportance = importance * maxK;
                if (newImportance < MinImportance)
                {
                    return(hash);
                }

                // Refracted ray.
                if ((r = Geometry.SpecularRefraction(i.Normal, i.Material.n, p1)) == Vector3d.Zero)
                {
                    return(hash);
                }

                hash += HASH_REFRACT * shade(level, newImportance, ref i.CoordWorld, ref r, comp);
                for (b = 0; b < bands; b++)
                {
                    color[b] += maxK * comp[b];
                }
            }

            return(hash);
        }