Exemple #1
0
        protected void  GetSHCoefficients(WMath.Vector _Direction, ref double[] _Coefficients)
        {
            float x = -_Direction.z;
            float y = _Direction.y;
            float z = _Direction.x;

            // Build the SH coefficients from analytical formulae given in http://www-graphics.stanford.edu/papers/envmap/
            _Coefficients[0] = 0.282095;                                        // Y00

            _Coefficients[1] = 0.488603 * z;                                    // Y1-1
            _Coefficients[2] = 0.488603 * y;                                    // Y10
            _Coefficients[3] = 0.488603 * x;                                    // Y1+1

            _Coefficients[4] = 1.092548 * x * z;                                // Y2-2
            _Coefficients[5] = 1.092548 * y * z;                                // Y2-1
            _Coefficients[6] = 0.315392 * (3 * y * y - 1);                      // Y20
            _Coefficients[7] = 1.092548 * x * y;                                // Y2+1
            _Coefficients[8] = 0.546274 * (x * x - z * z);                      // Y2+2
        }
        /// <summary>
        /// Initializes the collection of samples
        /// </summary>
        /// <param name="_Order">The order of the SH</param>
        /// <param name="_ThetaSamplesCount">The amount of samples on Theta (total samples count will be 2*N*N)</param>
        /// <param name="_Up">The vector to use as the Up direction (use [0,1,0] if not sure)</param>
        public void                     Initialize(int _Order, int _ThetaSamplesCount, WMath.Vector _Up)
        {
            m_Order             = _Order;
            m_ThetaSamplesCount = _ThetaSamplesCount;
            m_SamplesCount      = 2 * m_ThetaSamplesCount * m_ThetaSamplesCount;
            m_Random            = new Random(m_RandomSeed);

            // Compute the rotation matrix
            Matrix3x3 Rotation = new Matrix3x3();
            Vector    Ortho    = new Vector(0, 1, 0) ^ _Up;
            float     fNorm    = Ortho.SquareMagnitude();

            if (fNorm < 1e-6f)
            {
                Rotation.MakeIdentity();
            }
            else
            {
                Ortho /= (float)Math.Sqrt(fNorm);
                Rotation.SetRow0(Ortho);
                Rotation.SetRow1(_Up);
                Rotation.SetRow2(Ortho ^ _Up);
            }

            // Initialize the SH samples
            m_SHSamples = new SHSample[m_SamplesCount];

            // Build the samples using stratified sampling
            int SampleIndex = 0;

            for (int ThetaIndex = 0; ThetaIndex < m_ThetaSamplesCount; ThetaIndex++)
            {
                for (int PhiIndex = 0; PhiIndex < 2 * m_ThetaSamplesCount; PhiIndex++)
                {
                    double fTheta = 2.0 * System.Math.Acos(System.Math.Sqrt(1.0 - (ThetaIndex + m_Random.NextDouble()) / m_ThetaSamplesCount));
                    double fPhi   = System.Math.PI * (PhiIndex + m_Random.NextDouble()) / m_ThetaSamplesCount;

                    // Compute direction, rotate it then cast it back to sphercial coordinates
                    Vector Direction = SphericalHarmonics.SHFunctions.SphericalToCartesian(fTheta, fPhi);
                    Direction *= Rotation;

                    SphericalHarmonics.SHFunctions.CartesianToSpherical(Direction, out fTheta, out fPhi);

                    // Fill up the new sample
                    m_SHSamples[SampleIndex]             = new SHSample((float)fPhi, (float)fTheta);
                    m_SHSamples[SampleIndex].m_SHFactors = new double[m_Order * m_Order];

                    // Build the SH Factors
                    SHFunctions.InitializeSHCoefficients(m_Order, fTheta, fPhi, m_SHSamples[SampleIndex].m_SHFactors);

                    SampleIndex++;
                }
            }
        }