Example #1
0
        // Helpers
        // Intersection between a plane and a ray
        public bool Intersect( Ray _Ray, ref float3 _intersection )
        {
            float	fGradient = n.Dot( _Ray.Aim );
            if ( (float) System.Math.Abs( fGradient ) < float.Epsilon )
                return false;	// It cannot hit! (or very far away at least!)

            _Ray.Length = (-d - _Ray.Pos.Dot(n)) / fGradient;

            _intersection = _Ray.GetHitPos();
            return true;
        }
Example #2
0
        public AngleAxis( Quat _q )
        {
            Angle = (float) System.Math.Acos( _q.qs );
            float	fSine = (float) System.Math.Sin( Angle );
            Angle *= 2.0f;

            Quat	Temp = new Quat( _q );
            Temp.Normalize();

            if ( System.Math.Abs( fSine ) > float.Epsilon )
                Axis = Temp.qv / fSine;
            else
                Axis.Set( 0, 0, 0 );
        }
Example #3
0
        // Here, we choose the convention that the vertical axis defining THETA is the Y axis
        //  and the axes defining PHI are X and Z where PHI = 0 when the vector is aligned to the positive Z axis
        //
        // NOTE ==> The '_Direction' vector must be normalized!!
        //
        public static double ComputeZH( int l, float3 _Direction )
        {
            // Convert from cartesian to polar coords
            double	θ = 0.0;
            double	ϕ = 0.0f;
            CartesianToSpherical( _Direction, out θ, out ϕ );

            return	ComputeZH( l, θ );
        }
Example #4
0
        /// <summary>
        /// Encodes a function evaluated by the provided delegate into a series of ZH coefficients
        /// </summary>
        /// <param name="_Coefficients">The coefficients supposed to best fit the provided function (the length of the vector must be _Order²)</param>
        /// <param name="_SamplesCount">The amount of samples to use to fit the function</param>
        /// <param name="_RandomSeed">The random seed to initialize the RNG with when drawing random sample position</param>
        /// <param name="_Order">The order of the SH vector to encode</param>
        /// <param name="_Delegate">The delegate that will be called to evaluate the function to encode</param>
        public static void EncodeIntoSH( float3[] _Coefficients, int _SamplesCountTheta, int _SamplesCountPhi, int _RandomSeed, int _Order, EvaluateFunctionSHVector3 _Delegate )
        {
            Random	RNG = new Random( _RandomSeed );

            // Reset coefficients
            for ( int CoefficientIndex=0; CoefficientIndex < _Coefficients.Length; CoefficientIndex++ ) {
                _Coefficients[CoefficientIndex] = float3.Zero;
            }

            float3	Value = new float3();
            for ( int PhiIndex=0; PhiIndex < _SamplesCountPhi; PhiIndex++ )
                for ( int ThetaIndex=0; ThetaIndex < _SamplesCountTheta; ThetaIndex++ ) {
                    // Draw uniformly sampled θ and ϕ angles
                    double	θ = 2.0 * Math.Acos( Math.Sqrt( 1.0 - (ThetaIndex + RNG.NextDouble()) / _SamplesCountTheta ) );
                    double	ϕ = 2.0 * Math.PI * (PhiIndex + RNG.NextDouble()) / _SamplesCountPhi;

                    // Accumulate coefficients
                    _Delegate( θ, ϕ, Value );
                    for ( int l=0; l < _Order; l++ )
                        for ( int m=-l; m <= +l; m++ )
                            _Coefficients[l*(l+1)+m] += (float) Ylm( l, m, θ, ϕ ) * Value;
                }

            // Final normalizing
            float	Normalizer = 4.0f * (float) Math.PI / (_SamplesCountTheta * _SamplesCountPhi);
            for ( int CoefficientIndex=0; CoefficientIndex < _Order*_Order; CoefficientIndex++ )
                _Coefficients[CoefficientIndex] *= Normalizer;
        }
Example #5
0
 // Modulate all coefficients of degree l by scalar a.
 private static void Filter( float3[] _SH, int l, float a )
 {
     for ( int m=-l; m <= l; m++ )
         _SH[l*(l+1)+m] *= a;
 }
Example #6
0
 /// <summary>
 /// Converts a cartesian UNIT vector into spherical coordinates (θ,ϕ)
 /// </summary>
 /// <param name="_Direction">The cartesian unit vector to convert</param>
 /// <param name="_θ">The polar elevation</param>
 /// <param name="_ϕ">The azimuth</param>
 public static void CartesianToSpherical( float3 _Direction, out double _θ, out double _ϕ )
 {
     _θ = Math.Acos( Math.Max( -1.0f, Math.Min( +1.0f, _Direction.z ) ) );
     _ϕ = Math.Atan2( _Direction.y, _Direction.x );
 }
Example #7
0
        /// <summary>
        /// Applies a simple fast rotation about the Y axis
        /// </summary>
        /// <param name="_Vector">The vector to rotate</param>
        /// <param name="_ϕ">The rotation angle</param>
        /// <param name="_RotatedVector">The rotated vector</param>
        /// <param name="_Order">The order of the vectors (i.e. vectors must have a length of Order²)</param>
        public static void RotateY( float3[] _Vector, double _ϕ, float3[] _RotatedVector, int _Order )
        {
            for ( int l=0; l < _Order; l++ )
                for ( int m=-l; m <= l; m++ )
                    if ( m != 0 )
                    {
                        float	fCos = (float) Math.Cos( Math.Abs( m ) * _ϕ );
                        float	fSin = (float) Math.Sin( Math.Abs( m ) * _ϕ );

                        int		CoeffIndex0 = l*(l+1) + m;
                        int		CoeffIndex1 = l*(l+1) - m;

                        _RotatedVector[CoeffIndex0] = _Vector[CoeffIndex0] * fCos - Math.Sign( m ) * _Vector[CoeffIndex1] * fSin;
                    }
                    else
                        _RotatedVector[l*(l+1)] = _Vector[l*(l+1)];	// <= Don't rotate zonal harmonics
        }
Example #8
0
 /// <summary>
 /// Converts spherical coordinates (θ,ϕ) into a cartesian UNIT vector
 /// </summary>
 /// <param name="_θ">The polar elevation</param>
 /// <param name="_ϕ">The azimuth</param>
 /// <param name="_Direction">The unit vector in cartesian coordinates</param>
 public static void SphericalToCartesian( double _θ, double _ϕ, float3 _Direction )
 {
     _Direction.x = (float) (Math.Sin( _θ ) * Math.Cos( _ϕ ));
     _Direction.y = (float) (Math.Sin( _θ ) * Math.Sin( _ϕ ));
     _Direction.z = (float) Math.Cos( _θ );
 }
Example #9
0
 /// <summary>
 /// Initializes the provided vector with the SH coefficients corresponding to the specified direction
 /// </summary>
 /// <param name="_Order">The order of the SH vector</param>
 /// <param name="_Direction">The direction of the SH sampling</param>
 /// <param name="_Coefficients">The array of coefficients to fill up</param>
 public static void InitializeSHCoefficients( int _Order, float3 _Direction, float3[] _Coefficients )
 {
     int	Index = 0;
     for ( int l=0; l < _Order; l++ )
         for ( int m=-l; m <= +l; m++ )
         {
             float	fCoeff = (float) Ylm( l, m, _Direction );
             _Coefficients[Index++].Set( fCoeff, fCoeff, fCoeff );
         }
 }
Example #10
0
 /// <summary>
 /// Applies a simple mirroring on the Y axis
 /// </summary>
 /// <param name="_Vector">The vector to mirror</param>
 /// <param name="_MirroredVector">The mirrored vector</param>
 /// <param name="_Order">The order of the vectors (i.e. vectors must have a length of Order²)</param>
 public static void MirrorY( float3[] _Vector, float3[] _MirroredVector, int _Order )
 {
     for ( int l=0; l < _Order; l++ )
         for ( int m=-l; m <= l; m++ )
         {
             int		k = l*(l+1) + m;
             _MirroredVector[k] = (((l+m) & 1) == 0 ? +1 : -1) * _Vector[k];
         }
 }
Example #11
0
		// Assignment operators
		public void				Set				( Ray _r )												{ m_Pos = _r.m_Pos; m_Aim = _r.m_Aim; m_Length = _r.m_Length; m_MarchedLength = _r.m_MarchedLength; m_Datum = _r.m_Datum; }
Example #12
0
 // Apply a Gaussian window of width w (usually the SH order).
 public static void FilterGaussian( float3[] _SH, int w )
 {
     for ( int l = 0; l < 3; l++ )
         Filter( _SH, l, (float) Math.Exp( -(Math.PI * l / w) * (Math.PI * l / w) / 2.0 ) );
 }
Example #13
0
		public Ray				Bend			( float3 _Axis, float _fBendFactor )					{ m_Aim += _fBendFactor * m_Aim.Dot(_Axis) * _Axis; m_Aim.Normalize(); return this; }
Example #14
0
		// Helpers
		public Ray				March			( float _fDelta )										{ m_Pos += _fDelta * m_Aim; m_Length -= _fDelta; m_MarchedLength += _fDelta; return this; }
Example #15
0
		public					Ray				( float3 _Pos, float3 _Aim, float _fLength, float _fMarchedLength ) : this( _Pos, _Aim, _fLength )	{ m_MarchedLength = _fMarchedLength; }
Example #16
0
		public					Ray				( float3 _Pos, float3 _Aim, float _fLength ): this( _Pos, _Aim )									{ m_Length = _fLength; }
Example #17
0
		public					Ray				( float3 _Pos, float3 _Aim )																		{ m_Pos = _Pos; m_Aim = _Aim; }
Example #18
0
 // Apply a Lanczos window of width w (usually the SH order).
 public static void FilterLanczos( float3[] _SH, int w )
 {
     for (int l = 0; l < 3; l++)
         if ( l == 0 )
             Filter( _SH, l, 1 );
         else
             Filter( _SH, l, (float) (Math.Sin(Math.PI * l / w) / (Math.PI * l / w)) );
 }
Example #19
0
 // Constructors/Destructor
 public BoundingSphere()
 {
     m_Center = new float3(); m_Radius = 0.0f;
 }
Example #20
0
 public void                                     Set(float3 _Source)
 {
     x = _Source.x; y = _Source.y;
 }
Example #21
0
 public BoundingSphere(float _X, float _Y, float _Z, float _Radius)
 {
     m_Center = new float3(_X, _Y, _Z); m_Radius = _Radius;
 }
Example #22
0
        /// <summary>
        /// Applies rotation to the specified 3-vector using the specified rotation matrix returned by the "BuildRotationMatrix()" method
        /// </summary>
        /// <param name="_Vector">The 3-vector to rotate</param>
        /// <param name="_RotationMatrix">The SH rotation matrix</param>
        /// <param name="_RotatedVector">The rotated vector</param>
        /// <param name="_Order">The order of the vectors (i.e. vectors must have a length of Order²)</param>
        public static void Rotate( float3[] _Vector, double[,] _RotationMatrix, float3[] _RotatedVector, int _Order )
        {
            int	MatrixSize = 1;
            int	SourceCoefficientIndex = 0;
            int	DestCoefficientIndex = 0;
            for ( int l=0; l < _Order; l++, MatrixSize+=2 )
            {
                int	BandOffset = l * l;
                for ( int n=0; n < MatrixSize; n++ )
                {
                    _RotatedVector[DestCoefficientIndex] = new float3( 0.0f, 0.0f, 0.0f );

                    for ( int m=0; m < MatrixSize; m++ )
                        _RotatedVector[DestCoefficientIndex] += _Vector[SourceCoefficientIndex+m] * (float) _RotationMatrix[BandOffset + m,BandOffset + n];

                    DestCoefficientIndex++;
                }
                SourceCoefficientIndex += MatrixSize;
            }
        }
Example #23
0
 public BoundingSphere(float3 _Center, float _Radius)
 {
     m_Center = _Center; m_Radius = _Radius;
 }
Example #24
0
 /// <summary>
 /// Converts spherical coordinates (θ,ϕ) into a cartesian UNIT vector
 /// </summary>
 /// <param name="_θ">The polar elevation</param>
 /// <param name="_ϕ">The azimuth</param>
 /// <returns>The unit vector in cartesian coordinates</returns>
 public static float3 SphericalToCartesian( double _θ, double _ϕ )
 {
     float3	Result = new float3();
     SphericalToCartesian( _θ, _ϕ, Result );
     return	Result;
 }
Example #25
0
 public float Distance( float3 _p )
 {
     return _p.Dot(n) + d;
 }
Example #26
0
        // Here, we choose the convention that the vertical axis defining THETA is the Y axis
        //  and the axes defining PHI are X and Z where PHI = 0 when the vector is aligned to the positive Z axis
        //
        // NOTE ==> The '_Direction' vector must be normalized!!
        //
        public static double Ylm( int l, int m, float3 _Direction )
        {
            // Convert from cartesian to polar coords
            double	θ = 0.0;
            double	ϕ = 0.0f;
            CartesianToSpherical( _Direction, out θ, out ϕ );

            return	Ylm( l, m, θ, ϕ );
        }
Example #27
0
        // Intersection between 2 planes
        public bool Intersect( Plane _p, Ray _ray )
        {
            // Check if both planes are coplanar
            if ( (float) System.Math.Abs( 1.0f - _p.n.Dot(n) ) < float.Epsilon )
                return	false;

            // Let's have fun!
            float3	I = new float3();
            _ray.Pos.Set( 0, 0, 0 );
            _ray.Aim = n;
            if ( !_p.Intersect( _ray, ref I ) )
                return	false;

            _ray.Aim = _p.n;
            if ( !_p.Intersect( _ray, ref I ) )
                return	false;
            _ray.Pos = I;

            _ray.Aim = I - _ray.Pos;
            if ( !Intersect( _ray, ref I ) )
                return	false;
            _ray.Pos = I;

            // We have at least one point belonging to both planes!
            _ray.Aim = n.Cross(_p.n).Normalized;

            return	true;
        }
Example #28
0
        /// <summary>
        /// Computes the 9 Ylm coefficients for order 2 SH evaluated in the requested direction
        /// </summary>
        /// <param name="_direction"></param>
        /// <param name="_SH"></param>
        static void Ylm( float3 _direction, double[] _SH )
        {
            const double	c0 = 0.28209479177387814347403972578039;	// 1/2 sqrt(1/pi)
            const double	c1 = 0.48860251190291992158638462283835;	// 1/2 sqrt(3/pi)
            const double	c2 = 1.09254843059207907054338570580270;	// 1/2 sqrt(15/pi)
            const double	c3 = 0.31539156525252000603089369029571;	// 1/4 sqrt(5/pi)

            float	x = _direction.x;
            float	y = _direction.y;
            float	z = _direction.z;

            _SH[0] = c0;
            _SH[1] = c1*y;
            _SH[2] = c1*z;
            _SH[3] = c1*x;
            _SH[4] = c2*x*y;
            _SH[5] = c2*y*z;
            _SH[6] = c3*(3.0*z*z - 1.0);
            _SH[7] = c2*x*z;
            _SH[8] = 0.5*c2*(x*x - y*y);
        }
Example #29
0
        /// <summary>
        /// Computes the ambient occlusion of the specified coordinate by shooting N rays in a lobe oriented in the specified light direction
        /// </summary>
        /// <param name="_Light"></param>
        /// <param name="_X"></param>
        /// <param name="_Y"></param>
        /// <param name="_Z2HeightScale">Scale factor to apply to world Z coordinate to be remapped into the heights' [0,1] range</param>
        /// <param name="_LobeExponent">1 is a simple cosine lobe</param>
        /// <returns></returns>
        /// 
        private float ComputeAO( int _LightIndex, uint _X, uint _Y, float _Z2HeightScale, float3[,] _rays )
        {
            int		RaysCount = _rays.GetLength( 1 );
            int		maxStepsCount = integerTrackbarControlMaxStepsCount.Value;

            float	Z0 = m_imageSourceHeightMap[_X,_Y].y;
            double	AO = 0.0f;
            int		samplesCount = 0;
            for ( int rayIndex=0; rayIndex < RaysCount; rayIndex++ ) {
                float3	wsRay = _rays[_LightIndex,rayIndex];
             				if ( wsRay.z < 0.0f ) {
            // AO += 1.0;
            // SamplesCount++;
             					continue;	// Pointing to the ground so don't account for it...
                }

                // Make sure the ray has a unit step so we always travel at least one pixel
            //				m_RayWorld.z *= _Z2HeightScale;
            // 				float	Normalizer = 1.0f / Math.Max( Math.Abs( m_RayWorld.x ), Math.Abs( m_RayWorld.y ) );
            // 				float	Normalizer = 1.0f;
            // 				Normalizer = Math.Max( Normalizer, (1.0f - Z) / (128.0f * m_RayWorld.z) );	// This makes sure we can't use more than 128 steps to escape the heightfield
            //
            // 				float	Normalizer = (1.0f - Z) / (128.0f * m_RayWorld.z);
            //
            // 				m_RayWorld.x *= Normalizer;
            // 				m_RayWorld.y *= Normalizer;
            // 				m_RayWorld.z *= Normalizer;

                // Start from the provided coordinates
                float	X = _X;
                float	Y = _Y;
                float	Z = Z0;

                // Compute intersection with the height field
                int	stepIndex = 0;
                while ( stepIndex < maxStepsCount && Z < 1.0f && X > 0.0f && Y > 0.0f && X < W && Y < H ) {
                    X += wsRay.x;
                    Y += wsRay.y;
                    Z += wsRay.z;

                    float	height = SampleHeightField( X, Y );
                    if ( height > Z ) {
                        // Hit!
                        AO += 1.0;
                        break;
                    }

                    stepIndex++;
                }

                samplesCount++;
            }
            AO /= samplesCount;

            return (float) (1.0 - AO);
        }
Example #30
0
        /// <summary>
        /// Computes the SH coefficients of originaly Y-aligned Zonal Harmonics coefficients rotated to match the provided axis
        /// </summary>
        /// <param name="_ZHCoefficients">The ZH coefficients to rotate</param>
        /// <param name="_TargetAxis">The target axis to match (the original axis being positive Y)</param>
        /// <param name="_RotatedSHCoefficients">The rotated SH coefficients</param>
        /// <remarks>Be careful the returned coefficients are SH coefficients, hence the _RotatedSHCoefficients vector should be N² if rotating an order N Zonal Harmonics vector</remarks>
        public static void ComputeRotatedZHCoefficients( double[] _ZHCoefficients, float3 _TargetAxis, double[] _RotatedSHCoefficients )
        {
            // Compute the convolution coefficients from input ZH coeffs
            double[]	ConvolutionCoefficients = new double[_ZHCoefficients.Length];
            for ( int ConvolutionCoefficientIndex=0; ConvolutionCoefficientIndex < _ZHCoefficients.Length; ConvolutionCoefficientIndex++ )
                ConvolutionCoefficients[ConvolutionCoefficientIndex] = Math.Sqrt( 4.0 * Math.PI / (2 * ConvolutionCoefficientIndex + 1) ) * _ZHCoefficients[ConvolutionCoefficientIndex];

            // Perform rotation
            for ( int l=0; l < _ZHCoefficients.Length; l++ )
                for ( int m=-l; m <= +l; m++ )
                    _RotatedSHCoefficients[l*(l+1)+m] = Ylm( l, m, _TargetAxis ) * ConvolutionCoefficients[l];
        }
Example #31
0
        private void GenerateRays( int _raysCount, StructuredBuffer<float3> _target )
        {
            _raysCount = Math.Min( MAX_THREADS, _raysCount );

            // Half-Life 2 basis
            float3[]	HL2Basis = new float3[] {
                new float3( (float) Math.Sqrt( 2.0 / 3.0 ), 0.0f, (float) Math.Sqrt( 1.0 / 3.0 ) ),
                new float3( -(float) Math.Sqrt( 1.0 / 6.0 ), (float) Math.Sqrt( 1.0 / 2.0 ), (float) Math.Sqrt( 1.0 / 3.0 ) ),
                new float3( -(float) Math.Sqrt( 1.0 / 6.0 ), -(float) Math.Sqrt( 1.0 / 2.0 ), (float) Math.Sqrt( 1.0 / 3.0 ) )
            };

            float	centerTheta = (float) Math.Acos( HL2Basis[0].z );
            float[]	centerPhi = new float[] {
                (float) Math.Atan2( HL2Basis[0].y, HL2Basis[0].x ),
                (float) Math.Atan2( HL2Basis[1].y, HL2Basis[1].x ),
                (float) Math.Atan2( HL2Basis[2].y, HL2Basis[2].x ),
            };

            for ( int rayIndex=0; rayIndex < _raysCount; rayIndex++ ) {
                double	phi = (Math.PI / 3.0) * (2.0 * SimpleRNG.GetUniform() - 1.0);

                // Stratified version
                double	theta = (Math.Acos( Math.Sqrt( (rayIndex + SimpleRNG.GetUniform()) / _raysCount ) ));

            // 				// Don't give a shit version (a.k.a. melonhead version)
            // //				double	Theta = Math.Acos( Math.Sqrt(WMath.SimpleRNG.GetUniform() ) );
            // 				double	Theta = 0.5 * Math.PI * WMath.SimpleRNG.GetUniform();

                theta = Math.Min( 0.499f * Math.PI, theta );

                double	cosTheta = Math.Cos( theta );
                double	sinTheta = Math.Sin( theta );

                double	lengthFactor = 1.0 / sinTheta;	// The ray is scaled so we ensure we always walk at least a texel in the texture
                cosTheta *= lengthFactor;
                sinTheta *= lengthFactor;	// Yeah, yields 1... :)

                _target.m[0*MAX_THREADS+rayIndex].Set(	(float) (Math.Cos( centerPhi[0] + phi ) * sinTheta),
                                                        (float) (Math.Sin( centerPhi[0] + phi ) * sinTheta),
                                                        (float) cosTheta );
                _target.m[1*MAX_THREADS+rayIndex].Set(	(float) (Math.Cos( centerPhi[1] + phi ) * sinTheta),
                                                        (float) (Math.Sin( centerPhi[1] + phi ) * sinTheta),
                                                        (float) cosTheta );
                _target.m[2*MAX_THREADS+rayIndex].Set(	(float) (Math.Cos( centerPhi[2] + phi ) * sinTheta),
                                                        (float) (Math.Sin( centerPhi[2] + phi ) * sinTheta),
                                                        (float) cosTheta );
            }

            _target.Write();
        }
Example #32
0
        /// <summary>
        /// Computes the convolution of 2 3-vectors of SH coefficients of the specified order using Clebsch-Gordan coefficients
        /// </summary>
        /// <param name="_Vector0">First 3-vector</param>
        /// <param name="_Vector1">Second 3-vector</param>
        /// <param name="_Order">The order of the vectors (i.e. vectors must have a length of Order²)</param>
        /// <returns>The convolution of the 2 vectors</returns>
        /// <remarks>This method is quite time-consuming as the convolution is computed using 5 loops but, as an optimisation, we can notice that most Clebsh-Gordan are 0
        /// and a vector of non-null coefficients could be precomputed as only the vectors' coefficients change</remarks>
        public static float3[] Convolve( float3[] _Vector0, float3[] _Vector1, int _Order )
        {
            if ( _Vector0 == null || _Vector1 == null )
                throw new Exception( "Invalid coefficients!" );
            if ( _Vector0.Length != _Vector1.Length )
                throw new Exception( "Coefficient vectors length mismatch!" );
            if ( _Order * _Order != _Vector0.Length )
                throw new Exception( "Coefficient vectors are not of the specified order!" );

            float3[]	ConvolvedCoeffs = new float3[_Vector0.Length];

            // Compute convolution
            int	TotalCoeffIndex = 0;
            for ( int l=0; l < _Order; l++ )
                for ( int m=-l; m <= +l; m++, TotalCoeffIndex++ )
                {
                    ConvolvedCoeffs[TotalCoeffIndex] = new float3( 0.0f, 0.0f, 0.0f );

                    int	InnerTotalCoeffIndex = 0;
                    for ( int l1=0; l1 < _Order; l1++ )
                        for ( int m1=-l1; m1 <= +l1; m1++, InnerTotalCoeffIndex++ )
                            for ( int l2=0; l2 < _Order; l2++ )
                            {
                                int	Bl2m1mIndex = l2*(l2+1) + m1 - m;
                                if ( Bl2m1mIndex < 0 || Bl2m1mIndex >= _Order * _Order )
                                    continue;

                                double	Sign = ((m1 - m) & 1) == 0 ? +1 : -1;
                                double	Sqrt = Math.Sqrt( (2.0 * l1 + 1) * (2.0 * l2 + 1) / (4.0 * Math.PI * (2.0 * l + 1)) );
                                double	CGC0 = ComputeClebschGordan( l1, l2, 0, 0, l, 0 );
                                if ( Math.Abs( CGC0 ) < 1e-4 )
                                    continue;
                                double	CGC1 = ComputeClebschGordan( l1, l2, m1, m - m1, l, m );
                                if ( Math.Abs( CGC1 ) < 1e-4 )
                                    continue;

                                float3	A = _Vector0[InnerTotalCoeffIndex];
                                float3	B = _Vector1[Bl2m1mIndex];

                                double	FinalCoeff = Sqrt * CGC0 * CGC1;

                                ConvolvedCoeffs[TotalCoeffIndex] += (float) (Sign * FinalCoeff) * A * B;
                            }
                }

            return	ConvolvedCoeffs;
        }
Example #33
0
        private void Generate_CPU( int _RaysCount )
        {
            try {
                tabControlGenerators.Enabled = false;

                // Half-life basis (Z points outside of the surface, as in normal maps)
                float3[]	basis = new float3[] {
                    new float3( (float) Math.Sqrt( 2.0 / 3.0 ), 0.0f, (float) Math.Sqrt( 1.0 / 3.0 ) ),
                    new float3( (float) -Math.Sqrt( 1.0 / 6.0 ), (float) Math.Sqrt( 1.0 / 2.0 ), (float) Math.Sqrt( 1.0 / 3.0 ) ),
                    new float3( (float) -Math.Sqrt( 1.0 / 6.0 ), (float) -Math.Sqrt( 1.0 / 2.0 ), (float) Math.Sqrt( 1.0 / 3.0 ) ),
                };

            // 				// 1] Compute normal map
            // 				float3	dX = new float3();
            // 				float3	dY = new float3();
            // 				float3	N;
            // 				float			ddX = floatTrackbarControlPixelSize.Value;
            // 				float			ddH = floatTrackbarControlHeight.Value;
            // 				for ( int Y=0; Y < H; Y++ )
            // 				{
            // 					int	Y0 = Math.Max( 0, Y-1 );
            // 					int	Y1 = Math.Min( H-1, Y+1 );
            // 					for ( int X=0; X < W; X++ )
            // 					{
            // 						int	X0 = Math.Max( 0, X-1 );
            // 						int	X1 = Math.Min( W-1, X+1 );
            //
            // 						float	Hx0 = m_BitmapSource.ContentXYZ[X0,Y].y;
            // 						float	Hx1 = m_BitmapSource.ContentXYZ[X1,Y].y;
            // 						float	Hy0 = m_BitmapSource.ContentXYZ[X,Y0].y;
            // 						float	Hy1 = m_BitmapSource.ContentXYZ[X,Y1].y;
            //
            // 						dX.Set( 2.0f * ddX, 0.0f, ddH * (Hx1 - Hx0) );
            // 						dY.Set( 0.0f, 2.0f * ddX, ddH * (Hy1 - Hy0) );
            //
            // 						N = dX.Cross( dY ).Normalized;
            //
            // 						m_Normal[X,Y] = new float3(
            // 							N.Dot( Basis[0] ),
            // 							N.Dot( Basis[1] ),
            // 							N.Dot( Basis[2] ) );
            // 					}
            //
            // 					// Update and show progress
            // 					UpdateProgress( m_Normal, Y, true );
            // 				}
            // 				UpdateProgress( m_Normal, H, true );

                float	LobeExponent = 4.0f;//floatTrackbarControlLobeExponent.Value;

                float	PixelSize_mm = 1000.0f / floatTrackbarControlPixelDensity.Value;

                float	scale = 0.1f * PixelSize_mm / floatTrackbarControlHeight.Value;	// Scale factor to apply to pixel distances so they're renormalized in [0,1], our "heights space"...
            //						Scale *= floatTrackbarControlZFactor.Value;	// Cheat Z velocity so AO is amplified!

                // 2] Build local rays only once
                int			raysCount = integerTrackbarControlRaysCount.Value;
                float3[,]	rays = new float3[3,raysCount];

                // Create orthonormal bases to orient the lobe
                float3	Xr = basis[0].Cross( float3.UnitZ ).Normalized;	// We can safely use (0,0,1) as the "up" direction since the HL2 basis doesn't have any vertical direction
                float3	Yr = Xr.Cross( basis[0] );
                float3	Xg = basis[1].Cross( float3.UnitZ ).Normalized;	// We can safely use (0,0,1) as the "up" direction since the HL2 basis doesn't have any vertical direction
                float3	Yg = Xg.Cross( basis[1] );
                float3	Xb = basis[2].Cross( float3.UnitZ ).Normalized;	// We can safely use (0,0,1) as the "up" direction since the HL2 basis doesn't have any vertical direction
                float3	Yb = Xb.Cross( basis[2] );

                double	Exponent = 1.0 / (1.0 + LobeExponent);
                for ( int RayIndex=0; RayIndex < raysCount; RayIndex++ )
                {
            // 					if ( false ) {
            // 						double	Phi = 2.0 * Math.PI * WMath.SimpleRNG.GetUniform();
            // //						double	Theta = Math.Acos( Math.Pow( WMath.SimpleRNG.GetUniform(), Exponent ) );
            // 						double	Theta = Math.PI / 3.0 * WMath.SimpleRNG.GetUniform();
            //
            // 						float3	RayLocal = new float3(
            // 							(float) (Math.Cos( Phi ) * Math.Sin( Theta )),
            // 							(float) (Math.Sin( Phi ) * Math.Sin( Theta )),
            // 							(float) Math.Cos( Theta ) );
            //
            // 						Rays[0,RayIndex] = RayLocal.x * Xr + RayLocal.y * Yr + RayLocal.z * Basis[0];
            // 						Rays[1,RayIndex] = RayLocal.x * Xg + RayLocal.y * Yg + RayLocal.z * Basis[1];
            // 						Rays[2,RayIndex] = RayLocal.x * Xb + RayLocal.y * Yb + RayLocal.z * Basis[2];
            // 					} else
                    {
                        double	Phi = Math.PI / 3.0 * (2.0 * SimpleRNG.GetUniform() - 1.0);
                        double	Theta = 0.49 * Math.PI * SimpleRNG.GetUniform();
                        rays[0,RayIndex] = new float3(
                            (float) (Math.Cos( Phi ) * Math.Sin( Theta )),
                            (float) (Math.Sin( Phi ) * Math.Sin( Theta )),
                            (float) Math.Cos( Theta ) );

                        Phi = Math.PI / 3.0 * (2.0 * SimpleRNG.GetUniform() - 1.0 + 2.0);
                        Theta = 0.49 * Math.PI * SimpleRNG.GetUniform();
                        rays[1,RayIndex] = new float3(
                            (float) (Math.Cos( Phi ) * Math.Sin( Theta )),
                            (float) (Math.Sin( Phi ) * Math.Sin( Theta )),
                            (float) Math.Cos( Theta ) );

                        Phi = Math.PI / 3.0 * (2.0 * SimpleRNG.GetUniform() - 1.0 + 4.0);
                        Theta = 0.49 * Math.PI * SimpleRNG.GetUniform();
                        rays[2,RayIndex] = new float3(
                            (float) (Math.Cos( Phi ) * Math.Sin( Theta )),
                            (float) (Math.Sin( Phi ) * Math.Sin( Theta )),
                            (float) Math.Cos( Theta ) );
                    }

                    rays[0,RayIndex].z *= scale;
                    rays[1,RayIndex].z *= scale;
                    rays[2,RayIndex].z *= scale;
                }

                // 3] Compute directional occlusion
                float4[]	scanline = new float4[W];
                float4		gammaRGB = float4.Zero;
                for ( uint Y=0; Y < H; Y++ ) {
                    for ( uint X=0; X < W; X++ ) {
                        gammaRGB.x = ComputeAO( 0, X, Y, scale, rays );
                        gammaRGB.y = ComputeAO( 1, X, Y, scale, rays );
                        gammaRGB.z = ComputeAO( 2, X, Y, scale, rays );
                        gammaRGB.w = (gammaRGB.x+gammaRGB.y+gammaRGB.z) / 3.0f;
                        m_sRGBProfile.GammaRGB2LinearRGB( gammaRGB, ref scanline[X] );
                    }
                    m_imageResult.WriteScanline( Y, scanline );

                    // Update and show progress
                    UpdateProgress( m_imageResult, Y, true );
                }
                UpdateProgress( m_imageResult, H, true );

            //				m_BitmapResult.Save( "eye_generic_01_disp_hl2.png", ImageFormat.Png );
            }
            catch ( Exception _e )
            {
                MessageBox( "An error occurred during generation:\r\n" + _e.Message, MessageBoxButtons.OK, MessageBoxIcon.Error );
            }
            finally
            {
                tabControlGenerators.Enabled = true;
            }
        }
Example #34
0
        /// <summary>
        /// Evaluates the amplitude encoded by the Y-aligned ZH coefficients in the provided direction
        /// </summary>
        /// <param name="_Coefficients">The SH coefficients encoding an amplitude in various directions</param>
        /// <param name="_Direction">The direction where to evalute the ZH</param>
        /// <returns>The ZH evaluation in the provided direction</returns>
        public static double EvaluateZH( double[] _Coefficients, float3 _Direction )
        {
            // Convert from cartesian to polar coords
            double	θ = 0.0;
            double	ϕ = 0.0f;
            CartesianToSpherical( _Direction, out θ, out ϕ );

            return	EvaluateZH( _Coefficients, θ );
        }
Example #35
0
        float4x4 ComputeCameraProjection()
        {
            float	t = (float) (DateTime.Now - m_startTime).TotalSeconds;

            // Make a camera orbiting around the cube
            float	T = t;
            float3	cameraPosition = 3.0f * new float3( (float) Math.Cos( T ), (float) Math.Cos( 3 * T ), (float) Math.Sin( T ) );
            float3	cameraTarget = new float3( 0, 0, 0 );

            float4x4	camera2World = new float4x4();
            camera2World.BuildRotLeftHanded( cameraPosition, cameraTarget, float3.UnitY );

            // Build the perspective projection matrix
            float4x4	camera2Proj = new float4x4();
            camera2Proj.BuildProjectionPerspective( 80.0f * (float) Math.PI / 180.0f, (float) Width / Height, 0.01f, 100.0f );

            // Compose the 2 matrices together to obtain the final matrix that transforms world coordinates into projected 2D coordinates
            return camera2World.Inverse * camera2Proj;
        }
Example #36
0
 // Filtering stolen from http://csc.lsu.edu/~kooima/sht/sh.hpp
 // Apply a Hanning window of width w (usually the SH order).
 public static void FilterHanning( float3[] _SH, int w )
 {
     for (int l = 0; l < 3; l++)
         if ( l > w )
             Filter( _SH, l, 0 );
         else
             Filter( _SH, l, (float) ((Math.Cos(Math.PI * l / w) + 1.0) * 0.5) );
 }
Example #37
0
        // 		void timer1_Tick(object sender, System.EventArgs e) {
        // 			throw new System.NotImplementedException();
        // 		}
        //////////////////////////////////////////////////////////////////////////
        // Test methods compile
        static void TestFloat3x3()
        {
            if ( System.Runtime.InteropServices.Marshal.SizeOf(typeof(float3x3)) != 36 )
            throw new Exception( "Not the appropriate size!" );

            float3x3	test1 = new float3x3( new float[9] { 9, 8, 7, 6, 5, 4, 3, 2, 1 } );
            float3x3	test2 = new float3x3( new float3( 1, 0, 0 ), new float3( 0, 1, 0 ), new float3( 0, 0, 1 ) );
            float3x3	test3 = new float3x3( 0, 1, 2, 3, 4, 5, 6, 7, 8 );
            float3x3	test0;
                test0 = test3;
            test2.Scale( new float3( 2, 2, 2 ) );
            float3x3	mul0 = test1 * test2;
            float3x3	mul1 = 3.0f * test2;
            float3		mul2 = new float3( 1, 1, 1 ) * test3;
            float3		access0 = test3[2];
            test3[1] = new float3( 12, 13, 14 );
            float		access1 = test3[1,2];
            test3[1,2] = 18;
            //	float		coFactor = test3.CoFactor( 0, 2 );
            float		det = test3.Determinant;
            float3x3	inv = test2.Inverse;
            float3x3	id = float3x3.Identity;

            test3.BuildRotationX( 0.5f );
            test3.BuildRotationY( 0.5f );
            test3.BuildRotationZ( 0.5f );
            test3.BuildFromAngleAxis( 0.5f, float3.UnitY );
        }
Example #38
0
 /// <summary>
 /// Initializes the provided vector with the SH coefficients corresponding to the specified direction
 /// </summary>
 /// <param name="_Order">The order of the SH vector</param>
 /// <param name="_Direction">The direction of the SH sampling</param>
 /// <param name="_Coefficients">The array of coefficients to fill up</param>
 public static void InitializeSHCoefficients( int _Order, float3 _Direction, double[] _Coefficients )
 {
     int	Index = 0;
     for ( int l=0; l < _Order; l++ )
         for ( int m=-l; m <= +l; m++ )
             _Coefficients[Index++] = Ylm( l, m, _Direction );
 }
Example #39
0
        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);

            // Initialize the device
            m_device.Init( panelOutput1.Handle, false, true );

            // Build cube primitive
            {
                float3	colorXp = new float3( 1, 0, 0 );
                float3	colorXn = new float3( 1, 1, 0 );
                float3	colorYp = new float3( 0, 1, 0 );
                float3	colorYn = new float3( 0, 1, 1 );
                float3	colorZp = new float3( 0, 0, 1 );
                float3	colorZn = new float3( 1, 0, 1 );

                VertexP3N3G3T2[]	vertices = new VertexP3N3G3T2[6*4] {
                    // +X
                    new VertexP3N3G3T2() { P = new float3(  1,  1,  1 ), N = new float3(  1, 0, 0 ), T = colorXp, UV = new float2( 0, 0 ) },
                    new VertexP3N3G3T2() { P = new float3(  1, -1,  1 ), N = new float3(  1, 0, 0 ), T = colorXp, UV = new float2( 0, 1 ) },
                    new VertexP3N3G3T2() { P = new float3(  1, -1, -1 ), N = new float3(  1, 0, 0 ), T = colorXp, UV = new float2( 1, 1 ) },
                    new VertexP3N3G3T2() { P = new float3(  1,  1, -1 ), N = new float3(  1, 0, 0 ), T = colorXp, UV = new float2( 1, 0 ) },
                    // -X
                    new VertexP3N3G3T2() { P = new float3( -1,  1, -1 ), N = new float3( -1, 0, 0 ), T = colorXn, UV = new float2( 0, 0 ) },
                    new VertexP3N3G3T2() { P = new float3( -1, -1, -1 ), N = new float3( -1, 0, 0 ), T = colorXn, UV = new float2( 0, 1 ) },
                    new VertexP3N3G3T2() { P = new float3( -1, -1,  1 ), N = new float3( -1, 0, 0 ), T = colorXn, UV = new float2( 1, 1 ) },
                    new VertexP3N3G3T2() { P = new float3( -1,  1,  1 ), N = new float3( -1, 0, 0 ), T = colorXn, UV = new float2( 1, 0 ) },
                    // +Y
                    new VertexP3N3G3T2() { P = new float3( -1,  1, -1 ), N = new float3( 0,  1, 0 ), T = colorYp, UV = new float2( 0, 0 ) },
                    new VertexP3N3G3T2() { P = new float3( -1,  1,  1 ), N = new float3( 0,  1, 0 ), T = colorYp, UV = new float2( 0, 1 ) },
                    new VertexP3N3G3T2() { P = new float3(  1,  1,  1 ), N = new float3( 0,  1, 0 ), T = colorYp, UV = new float2( 1, 1 ) },
                    new VertexP3N3G3T2() { P = new float3(  1,  1, -1 ), N = new float3( 0,  1, 0 ), T = colorYp, UV = new float2( 1, 0 ) },
                    // -Y
                    new VertexP3N3G3T2() { P = new float3( -1, -1,  1 ), N = new float3( 0, -1, 0 ), T = colorYn, UV = new float2( 0, 0 ) },
                    new VertexP3N3G3T2() { P = new float3( -1, -1, -1 ), N = new float3( 0, -1, 0 ), T = colorYn, UV = new float2( 0, 1 ) },
                    new VertexP3N3G3T2() { P = new float3(  1, -1, -1 ), N = new float3( 0, -1, 0 ), T = colorYn, UV = new float2( 1, 1 ) },
                    new VertexP3N3G3T2() { P = new float3(  1, -1,  1 ), N = new float3( 0, -1, 0 ), T = colorYn, UV = new float2( 1, 0 ) },
                    // +Z
                    new VertexP3N3G3T2() { P = new float3( -1,  1,  1 ), N = new float3( 0, 0,  1 ), T = colorZp, UV = new float2( 0, 0 ) },
                    new VertexP3N3G3T2() { P = new float3( -1, -1,  1 ), N = new float3( 0, 0,  1 ), T = colorZp, UV = new float2( 0, 1 ) },
                    new VertexP3N3G3T2() { P = new float3(  1, -1,  1 ), N = new float3( 0, 0,  1 ), T = colorZp, UV = new float2( 1, 1 ) },
                    new VertexP3N3G3T2() { P = new float3(  1,  1,  1 ), N = new float3( 0, 0,  1 ), T = colorZp, UV = new float2( 1, 0 ) },
                    // -Z
                    new VertexP3N3G3T2() { P = new float3(  1,  1, -1 ), N = new float3( 0, 0, -1 ), T = colorZn, UV = new float2( 0, 0 ) },
                    new VertexP3N3G3T2() { P = new float3(  1, -1, -1 ), N = new float3( 0, 0, -1 ), T = colorZn, UV = new float2( 0, 1 ) },
                    new VertexP3N3G3T2() { P = new float3( -1, -1, -1 ), N = new float3( 0, 0, -1 ), T = colorZn, UV = new float2( 1, 1 ) },
                    new VertexP3N3G3T2() { P = new float3( -1,  1, -1 ), N = new float3( 0, 0, -1 ), T = colorZn, UV = new float2( 1, 0 ) },
                };
                uint[]	indices = new uint[3*2*6] {
                    4*0+0, 4*0+1, 4*0+2, 4*0+0, 4*0+2, 4*0+3,
                    4*1+0, 4*1+1, 4*1+2, 4*1+0, 4*1+2, 4*1+3,
                    4*2+0, 4*2+1, 4*2+2, 4*2+0, 4*2+2, 4*2+3,
                    4*3+0, 4*3+1, 4*3+2, 4*3+0, 4*3+2, 4*3+3,
                    4*4+0, 4*4+1, 4*4+2, 4*4+0, 4*4+2, 4*4+3,
                    4*5+0, 4*5+1, 4*5+2, 4*5+0, 4*5+2, 4*5+3,
                };

                m_prim_cube = new Primitive( m_device, 6*4, VertexP3N3G3T2.FromArray( vertices ), indices, Primitive.TOPOLOGY.TRIANGLE_LIST, VERTEX_FORMAT.P3N3G3T2 );
            }

            // Build the shader to render the cube
            m_shader_renderCube = new Shader( m_device, new ShaderFile( new System.IO.FileInfo( @".\Shaders\RenderCube.hlsl" ) ), VERTEX_FORMAT.P3N3G3T2, "VS", null, "PS", null );

            // Build constant buffer to provide camera transform
            m_CB_Camera = new ConstantBuffer<CBCamera>( m_device, 0 );

            Application.Idle += Application_Idle;
        }
Example #40
0
        public float3[] MapSequenceToSphere( double[,] _Sequence, double _MaxTheta )
        {
            if ( _Sequence.GetLength( 1 ) != 2 )
                throw new Exception( "Expecting a 2-dimensional sequence !" );

            double		cosMaxTheta = Math.Cos( _MaxTheta );

            float3[]	Result = new float3[_Sequence.GetLength( 0 )];
            for ( int i=0; i < Result.Length; i++ )
            {
                //  Pick a uniformly random VDOT, which must be between -1 and 1.
                //  This represents the dot product of the random vector with the Y unit vector.
                //
                //  Note: this works because the surface area of the sphere between
                //  Y and Y + dY is independent of Y.  So choosing Y uniformly chooses
                //  a patch of area uniformly.
                //
                double vdot = cosMaxTheta + (1.0 - cosMaxTheta) * _Sequence[i,0];
                double theta = Math.Acos( vdot );

                //  Pick a uniformly random rotation between 0 and 2 Pi around the axis of the Y vector.
                //
                double phi = 2.0 * Math.PI * _Sequence[i,1];

                Result[i] = new float3()
                {
                    x = (float) (Math.Sin( phi ) * Math.Sin( theta )),
                    y = (float) Math.Cos( theta ),
                    z = (float) (Math.Cos( phi ) * Math.Sin( theta ))
                };
            }

            return Result;
        }
Example #41
0
 public Point2D(float3 _Source)
 {
     Set(_Source);
 }