/// <summary>
		/// Calculate the square root of a complex number
		/// </summary>
		/// <param name="c"></param>
		/// <returns></returns>
		static public ComplexF	Sqrt( ComplexF c ) {
			double	x	= c.Re;
			double	y	= c.Im;

			double	modulus	= Math.Sqrt( x*x + y*y );
			int		sign	= ( y < 0 ) ? -1 : 1;

			c.Re		= (float)( _halfOfRoot2 * Math.Sqrt( modulus + x ) );
			c.Im	= (float)( _halfOfRoot2 * sign * Math.Sqrt( modulus - x ) );

			return	c;
		}
Example #2
0
        //---------------------------------------------------------------------------------------------------
        /// <summary>
        /// Calculate the power of a complex number
        /// </summary>
        /// <param name="c"></param>
        /// <param name="exponent"></param>
        /// <returns></returns>
        public static ComplexF Pow( ComplexF c, double exponent )
        {
            double	x	= c.Re;
            double	y	= c.Im;

            double	modulus		= Math.Pow( x*x + y*y, exponent * 0.5 );
            double	argument	= Math.Atan2( y, x ) * exponent;

            c.Re		= (float)( modulus * System.Math.Cos( argument ) );
            c.Im = (float)( modulus * System.Math.Sin( argument ) );

            return	c;
        }
Example #3
0
		static private ComplexF		SumRecursion( ComplexF[] data, int start, int end ) {
			Debug.Assert( 0 <= start, "start = " + start );
			Debug.Assert( start < end, "start = " + start + " and end = " + end );
			Debug.Assert( end <= data.Length, "end = " + end + " and data.Length = " + data.Length );
			if( ( end - start ) <= 1000 ) {
				ComplexF sum = ComplexF.Zero;
				for( int i = start; i < end; i ++ ) {
					sum += data[ i ];
				
				}
				return	sum;
			}
			else {
				int middle = ( start + end ) >> 1;
				return	SumRecursion( data, start, middle ) + SumRecursion( data, middle, end );
			}
		}
Example #4
0
		/// <summary>
		///  Determine whether the elements in the two arrays are the same
		/// </summary>
		/// <param name="array1"></param>
		/// <param name="array2"></param>
		/// <param name="tolerance"></param>
		/// <returns></returns>
		static public bool		IsEqual( ComplexF[] array1, ComplexF[] array2, float tolerance ) {
			if ( array1.Length != array2.Length ) {
				return false;
			}
			for( int i = 0; i < array1.Length; i ++ ) {
				if( ComplexF.IsEqual( array1[i], array2[i], tolerance ) == false ) {
					return false;
				}
			}
			return true;
		}
		/// <summary>
		/// Compute a 2D fast fourier transform on a data set of complex numbers
		/// </summary>
		/// <param name="data"></param>
		/// <param name="xLength"></param>
		/// <param name="yLength"></param>
		/// <param name="direction"></param>
		public static void	FFT2( ComplexF[] data, int xLength, int yLength, FourierDirection direction ) {

		int xInc = 1;
			int yInc = xLength;

			if( xLength > 1 ) {
				SyncLookupTableLength( xLength );
				for( int y = 0; y < yLength; y ++ ) {
					int xStart = y * yInc;
					LinearFFT_Quick( data, xStart, xInc, xLength, direction );
				}
			}
		
			if( yLength > 1 ) {
				SyncLookupTableLength( yLength );
				for( int x = 0; x < xLength; x ++ ) {
					int yStart = x * xInc;
					LinearFFT_Quick( data, yStart, yInc, yLength, direction );
				}
			}
		}
Example #6
0
		/// <summary>
		/// Shift (offset) the elements in the array
		/// </summary>
		/// <param name="array"></param>
		/// <param name="offset"></param>
		static public void Shift( ComplexF[] array, int offset ) {
			Debug.Assert( array != null );
			Debug.Assert( offset >= 0 );
			Debug.Assert( offset < array.Length );

			if( offset == 0 ) {
				return;
			}

			int			length		= array.Length;
			ComplexF[]	workspace	= null;
			ComplexArray.LockWorkspaceF( length, ref workspace );

			for( int i = 0; i < length; i ++ ) {
				workspace[ ( i + offset ) % length ] = array[ i ];
			}
			for( int i = 0; i < length; i ++ ) {
				array[ i ] = workspace[ i ];
			}

			ComplexArray.UnlockWorkspaceF( ref workspace );
		}
Example #7
0
 public static Complex ToSysComplex(ComplexF d)
 {
     return(new Complex(d.x, d.y));
 }
Example #8
0
 private static void mulComplex(ref ComplexF sourceA, ref ComplexF sourceB, ref ComplexF destination)
 {
     destination.Re = sourceA.Re * sourceB.Re;
     destination.Im = sourceA.Im * sourceB.Im;
 }
Example #9
0
		/// <summary>
		/// Divide each element in target array with corresponding element in rhs array
		/// </summary>
		/// <param name="target"></param>
		/// <param name="rhs"></param>
		static public void Divide( ComplexF[] target, ComplexF[] rhs ) {
			ComplexArray.Divide( target, rhs, target );
		}
Example #10
0
		/// <summary>
		/// Invert each element in the array
		/// </summary>
		/// <param name="array"></param>
		static public void Invert( ComplexF[] array ) {
			for( int i = 0; i < array.Length; i ++ ) {
				array[i] = ((ComplexF) 1 ) / array[i];
			}
		}
Example #11
0
 public CUBLASStatusv2 cublasCdotc(cublasHandle handle, int n, IntPtr x, int incx, IntPtr y, int incy, ref ComplexF result)
 {
     return(cublasCdotc_v2(handle, n, x, incx, y, incy, ref result));
 }
Example #12
0
 public CUBLASStatusv2 cublasCrot(cublasHandle handle, int n, IntPtr x, int incx, IntPtr y, int incy, ref float c, ref ComplexF s)
 {
     return(cublasCrot_v2(handle, n, x, incx, y, incy, ref c, ref s));
 }
Example #13
0
 private static extern CUBLASStatusv2 cublasCrotg_v2(cublasHandle handle, ref ComplexF a, ref ComplexF b, ref float c, ref ComplexF s);
Example #14
0
 public CUBLASStatusv2 cublasCaxpy(cublasHandle handle, int n, ref ComplexF alpha, IntPtr x, int incx, IntPtr y, int incy)
 {
     return(cublasCaxpy_v2(handle, n, ref alpha, x, incx, y, incy));
 }
Example #15
0
 private static extern CUBLASStatusv2 cublasCrot_v2(cublasHandle handle, int n, IntPtr x, int incx, IntPtr y, int incy, ref float c, ref ComplexF s);
Example #16
0
 private static extern CUBLASStatusv2 cublasCdotc_v2(cublasHandle handle, int n, IntPtr x, int incx, IntPtr y, int incy, ref ComplexF result);
Example #17
0
 private static extern CUBLASStatusv2 cublasCaxpy_v2(cublasHandle handle, int n, ref ComplexF alpha, IntPtr x, int incx, IntPtr y, int incy);
Example #18
0
		/// <summary>
		/// Multiply each element in the array by a specific value
		/// </summary>
		/// <param name="array"></param>
		/// <param name="scale"></param>
		static public void Scale( ComplexF[] array, ComplexF scale ) {
			Debug.Assert( array != null );

			int length = array.Length;
			for( int i = 0; i < length; i ++ ) {
				array[i] *= scale;
			}
		}
Example #19
0
 public CUBLASStatusv2 cublasCrotg(cublasHandle handle, ref ComplexF a, ref ComplexF b, ref float c, ref ComplexF s)
 {
     return(cublasCrotg_v2(handle, ref a, ref b, ref c, ref s));
 }
Example #20
0
		/// <summary>
		/// Multiply each element in target array with corresponding element in rhs array
		/// </summary>
		/// <param name="target"></param>
		/// <param name="rhs"></param>
		static public void Multiply( ComplexF[] target, ComplexF[] rhs ) {
			ComplexArray.Multiply( target, rhs, target );
		}
Example #21
0
 private static void convertComplexToMagnitude(ref ComplexF source, ref Gray <float> destination)
 {
     destination.Intensity = source.Magnitude();
 }
Example #22
0
		/// <summary>
		/// Copy an array
		/// </summary>
		/// <param name="dest"></param>
		/// <param name="source"></param>
		static public void Copy( ComplexF[] dest, ComplexF[] source ) {
			Debug.Assert( dest != null );
			Debug.Assert( source != null );
			Debug.Assert( dest.Length == source.Length );
			for( int i = 0; i < dest.Length; i ++ ) {
				dest[i] = source[i];
			}
		}
		static private void		LockBufferCF( int length, ref ComplexF[] buffer ) {
			
			if( length != _bufferCF.Length ) {
				_bufferCF	= new ComplexF[ length ];
			}
			buffer =	_bufferCF;
		}
Example #24
0
    void InitWaveGenerator()
    {
        // Wind restricted to one direction, reduces calculations
        Vector2 wind = new Vector2 (windx, 0.0f);

        // Initialize wave generator
        for (int y=0; y<height; y++) {
            for (int x=0; x<width; x++) {
                float yc = y < height / 2f ? y : -height + y;
                float xc = x < width / 2f ? x : -width + x;
                Vector2 vec_k = new Vector2 (2.0f * Mathf.PI * xc / size.x, 2.0f * Mathf.PI * yc / size.z);
                h0 [width * y + x] = new ComplexF (GaussianRnd (), GaussianRnd ()) * 0.707f * (float)System.Math.Sqrt (P_spectrum (vec_k, wind));
            }
        }

        for (int y=0; y<n_height; y++) {
            for (int x=0; x<n_width; x++) {
                float yc = y < n_height / 2f ? y : -n_height + y;
                float xc = x < n_width / 2f ? x : -n_width + x;
                Vector2 vec_k = new Vector2 (2.0f * Mathf.PI * xc / (size.x / normal_scale), 2.0f * Mathf.PI * yc / (size.z / normal_scale));
                n0 [n_width * y + x] = new ComplexF (GaussianRnd (), GaussianRnd ()) * 0.707f * (float)System.Math.Sqrt (P_spectrum (vec_k, wind));
            }
        }
    }
		private static void	LinearFFT_Quick( ComplexF[] data, int start, int inc, int length, FourierDirection direction ) {
			
			// copy to buffer
			ComplexF[]	buffer = null;
			LockBufferCF( length, ref buffer );
			int j = start;
			for( int i = 0; i < length; i ++ ) {
				buffer[ i ] = data[ j ];
				j += inc;
			}

			FFT( buffer, length, direction );

			// copy from buffer
			j = start;
			for( int i = 0; i < length; i ++ ) {
				data[ j ] = buffer[ i ];
				j += inc;
			}
			UnlockBufferCF( ref buffer );
		}
		/// <summary>
		/// Swap two complex numbers
		/// </summary>
		/// <param name="a"></param>
		/// <param name="b"></param>
		static public void Swap( ref ComplexF a, ref ComplexF b ) {
			ComplexF temp = a;
			a = b;
			b = temp;
		}
Example #27
0
 private static void convertGrayToComplex(ref Gray <float> source, ref ComplexF destination)
 {
     destination.Re = source.Intensity;
 }
		//-------------------------------------------------------------------------------------



		static private void ReorderArray( ComplexF[] data ) {

			int length = data.Length;

			int[] reversedBits = GetReversedBits( Log2( length ) );
			for( int i = 0; i < length; i ++ ) {
				int swap = reversedBits[ i ];
				if( swap > i ) {
					ComplexF temp = data[ i ];
					data[ i ] = data[ swap ];
					data[ swap ] = temp;
				}
			}
		}
Example #29
0
        static void Main(string[] args)
        {
            bool showUsage = true;

            if (args.Length >= 3)
            {
                try
                {
                    // todo: generalize port parsing and throw new exceptions
                    int inputPort           = int.Parse(args[0]);
                    int amplitudeOutputPort = int.Parse(args[1]);
                    int phaseOutputPort     = int.Parse(args[2]);
                    if (inputPort > 0 && inputPort < 65536 &&
                        amplitudeOutputPort > 0 && amplitudeOutputPort < 65536 &&
                        phaseOutputPort > 0 && phaseOutputPort < 65536
                        )
                    {
                        showUsage = false;

                        String adrs = "127.0.0.1";
                        if (args.Length >= 4)
                        {
                            adrs = args[3];
                        }
                        // todo: generalize address parsing and throw new exceptions
                        Console.WriteLine("Sending on address " + adrs);
                        Console.WriteLine("Receiving UDP packets on port " + inputPort);
                        Console.WriteLine("Sending amplitude UDP packets on port " + amplitudeOutputPort);
                        Console.WriteLine("Sending phase UDP packets on port " + phaseOutputPort);
                        UdpClient inputUdpClient     = new UdpClient(inputPort);
                        UdpClient amplitudeUdpClient = new UdpClient(adrs, amplitudeOutputPort);
                        UdpClient phaseUdpClient     = new UdpClient(adrs, phaseOutputPort);

                        try
                        {
                            while (true)
                            {
                                //IPEndPoint object will allow us to read datagrams sent from any source.
                                IPEndPoint RemoteIpEndPoint = new IPEndPoint(IPAddress.Any, 0);

                                // Blocks until a message returns on this socket from a remote host.
                                Byte[] receiveBytes = inputUdpClient.Receive(ref RemoteIpEndPoint);

                                //todo:Size handling!!!
                                int size = 1024;

                                // prepare dataset from real data
                                List <ComplexF> cxList = new List <ComplexF>(size);
                                for (int i = 0; i < size; i++)
                                {
                                    // unsigned byte to R=[0..1],I=0 complex number
                                    //cxList.Add(new ComplexF((float)(receiveBytes[i]), 0));


                                    float t  = (float)(2 * Math.PI * size) / 16; // sampling rate is 16 samples/sec.
                                    float pt = (float)(1.1 + 1.0 * Math.Sin(t) + .5 * Math.Sin(1.5 * t));
                                    cxList.Add(new ComplexF(pt, 0));
                                    // * */
                                }

                                // Transform in the complex array
                                ComplexF[] cxArray = cxList.ToArray <ComplexF>();
                                Fourier.FFT(cxArray, FourierDirection.Forward);

                                // find boundaries
                                ComplexF maxCx = cxArray.Max <ComplexF>();
                                ComplexF minCx = cxArray.Min <ComplexF>();

                                // remap type
                                List <byte> abList = new List <byte>(size);
                                List <byte> pbList = new List <byte>(size);
                                for (int i = 0; i < size; i++)
                                {
                                    // also realign negative frequencies and flip amplitude
                                    int n = (i + size / 2) % size;
                                    abList.Add((byte)(255 - ((cxArray[n].GetModulus() * 255) / 1024)));             // Amplitude [0..255]
                                    pbList.Add((byte)((cxArray[n].GetArgument() + Math.PI) / (2 * Math.PI) * 256)); // Phase [0..255]
                                }
                                byte[] amplitude = abList.ToArray <Byte>();
                                byte[] phase     = pbList.ToArray <Byte>();

                                // and send!
                                amplitudeUdpClient.Send(amplitude, amplitude.Length);
                                phaseUdpClient.Send(phase, phase.Length);
                            }
                        }
                        catch (Exception e)
                        {
                            Console.WriteLine(e.ToString());
                        }
                        finally
                        {
                            inputUdpClient.Close();
                            amplitudeUdpClient.Close();
                            phaseUdpClient.Close();
                        }
                    }
                }
                catch (Exception e)
                {
                    // will show usage anyway...
                    Console.WriteLine(e.ToString());
                    // todo: a friendly detailed explanation of the failure should be displayed when failing
                }
            }
            if (showUsage)
            {
                Console.WriteLine("Compute spectrum. using FFT");
                Console.WriteLine("USAGE: UDPSpectrum inputPort amplitudeOutputPort phaseOutputPort [sendToAddress]\n");
                Console.WriteLine("Warning: This kind of transformation is don on 2^x sets, som truncation and padding may occurs!");
                // todo: make a strict flag in the arguments to optionnaly reject non-conform packets
                Console.WriteLine("Hit any key to exit");
                Console.Read();
            }
        }
		static private void		UnlockBufferCF( ref ComplexF[] buffer ) {
			buffer = null;
		}
Example #31
0
        /// <summary>
        /// Calculates the fast fourier transform of the image.
        /// </summary>
        /// <param name="image">The image to get calculate the FFT from.</param>
        /// <param name="shiftAxes">Whether to perform FFTShift on the Fourier image.</param>
        /// <param name="ignoreAlpha">Whether to ignore the alpha component of the image (if it is 32-bit).</param>
        /// <param name="disposeImage">Whether to dispose the image after use.</param>
        /// <param name="targetWidth">The height to resize the kernel to, or -1 to leave kernel same width. Can only be larger than the kernel width.</param>
        /// <param name="targetHeight">The height to resize the kernel to, or -1 to leave kernel same height. Can only be larger than the kernel height.</param>
        public FourierWorker(PixelWorker image, bool shiftAxes = true, bool ignoreAlpha = false, bool disposeImage = false, int targetWidth = -1, int targetHeight = -1)
        {
            if (image == null)
            {
                return;
            }
            int componentCount = image.ComponentCount, targetPixelCount = image.PixelCount;

            if (ignoreAlpha && componentCount == 4)
            {
                componentCount = 3;
                alphaReference = image;
                alphaReference.ShallowClone();
            }
            values                     = new ComplexF[componentCount][];
            ComponentCount             = componentCount;
            TargetWidth                = image.Width;
            TargetHeight               = image.Height;
            TargetPixelCount           = image.PixelCount;
            TargetPixelComponentCount  = image.PixelComponentCount;
            TargetSize                 = new Size(TargetWidth, TargetHeight);
            FourierWidth               = (int)Maths.CeilingPowerOfTwo((uint)(targetWidth <= TargetWidth ? TargetWidth : targetWidth));
            FourierHeight              = (int)Maths.CeilingPowerOfTwo((uint)(targetHeight <= TargetHeight ? TargetHeight : targetHeight));
            FourierSize                = new Size(FourierWidth, FourierHeight);
            FourierPixelCount          = FourierWidth * FourierHeight;
            FourierPixelComponentCount = FourierPixelCount * ComponentCount;
            fourierWidthLog2           = Maths.Log2((uint)FourierWidth);
            fourierHeightLog2          = Maths.Log2((uint)FourierHeight);
            ComplexF[] current;
            byte       comp;
            int        c, x = 0, y = 0, fourierWidth = FourierWidth, fourierHeight = FourierHeight, tw = TargetWidth;
            int        tcc = image.ComponentCount, txMinusOne = TargetWidth - 1, tyMinusOne = TargetHeight - 1;

            for (c = 0; c < componentCount; c++)
            {
                current   = new ComplexF[FourierPixelCount];
                values[c] = current;
                for (y = 0; y < fourierHeight; y++)
                {
                    for (x = 0; x < fourierWidth; x++)
                    {
                        comp = image.GetPixelBgra((Math.Min(y, tyMinusOne) * tw + Math.Min(x, txMinusOne)) * tcc)[c];
                        if (comp > OriginalMax)
                        {
                            OriginalMax = comp;
                        }
                        current[y * fourierWidth + x] = new ComplexF()
                        {
                            Real = comp,
                        };
                    }
                }
            }
            NormalizationCap = OriginalMax;
            FFT(true);
            if (shiftAxes)
            {
                ShiftAxes = true;
                FFTShift();
            }
            if (disposeImage)
            {
                image.Dispose();
            }
        }
		//======================================================================================
		 

		/// <summary>
		/// Compute a 1D fast Fourier transform of a dataset of complex numbers.
		/// </summary>
		/// <param name="data"></param>
		/// <param name="length"></param>
		/// <param name="direction"></param>
		public static void	FFT( ComplexF[] data, int length, FourierDirection direction ) {

			SyncLookupTableLength( length );

			int ln = Log2( length );
			
			// reorder array
			ReorderArray( data );
			
			// successive doubling
			int N = 1;
			int signIndex = ( direction == FourierDirection.Forward ) ? 0 : 1;
			
			for( int level = 1; level <= ln; level ++ ) {
				int M = N;
				N <<= 1;

				float[] uRLookup = _uRLookupF[ level, signIndex ];
				float[] uILookup = _uILookupF[ level, signIndex ];

				for( int j = 0; j < M; j ++ ) {
					float uR = uRLookup[j];
					float uI = uILookup[j];

					for( int even = j; even < length; even += N ) {
						int odd	 = even + M;
						
						float	r = data[ odd ].Re;
						float	i = data[ odd ].Im;

						float	odduR = r * uR - i * uI;
						float	odduI = r * uI + i * uR;

						r = data[ even ].Re;
						i = data[ even ].Im;
						
						data[ even ].Re	= r + odduR;
						data[ even ].Im	= i + odduI;
						
						data[ odd ].Re	= r - odduR;
						data[ odd ].Im	= i - odduI;
					}
				}
			}

		}
Example #33
0
        public FourierWorker(float[][][] kernel, bool shiftAxes = true, int targetWidth = -1, int targetHeight = -1)
        {
            int cc = kernel == null ? 0 : kernel.Length;

            ComponentCount = cc;
            float[][] k = cc == 0 ? null : kernel[0];
            if (targetWidth <= 0)
            {
                TargetWidth  = k == null ? 0 : k.Length;
                FourierWidth = (int)Maths.CeilingPowerOfTwo((uint)TargetWidth);
            }
            else
            {
                TargetWidth  = k == null ? 0 : k.Length;
                FourierWidth = (int)Maths.CeilingPowerOfTwo((uint)(targetWidth <= TargetWidth ? TargetWidth : targetWidth));
            }
            if (targetHeight <= 0)
            {
                TargetHeight  = (k == null || k.Length == 0) ? 0 : (k[0] == null ? 0 : k[0].Length);
                FourierHeight = (int)Maths.CeilingPowerOfTwo((uint)TargetHeight);
            }
            else
            {
                TargetHeight  = (k == null || k.Length == 0) ? 0 : (k[0] == null ? 0 : k[0].Length);
                FourierHeight = (int)Maths.CeilingPowerOfTwo((uint)(targetHeight <= TargetHeight ? TargetHeight : targetHeight));
            }
            OriginalMax                = 255;
            NormalizationCap           = 255;
            TargetPixelCount           = TargetWidth * TargetHeight;
            TargetPixelComponentCount  = TargetPixelCount * cc;
            FourierPixelCount          = FourierWidth * FourierHeight;
            FourierPixelComponentCount = FourierPixelCount * cc;
            fourierWidthLog2           = Maths.Log2((uint)FourierWidth);
            fourierHeightLog2          = Maths.Log2((uint)FourierHeight);
            TargetSize  = new Size(TargetWidth, TargetHeight);
            FourierSize = new Size(FourierWidth, FourierHeight);
            values      = new ComplexF[cc][];
            int c;

            for (c = 0; c < cc; c++)
            {
                values[c] = new ComplexF[FourierPixelCount];
            }
            if (kernel == null)
            {
                return;
            }
            targetWidth  = TargetWidth;
            targetHeight = TargetHeight;
            int fourierWidth = FourierWidth;

            float[]    temp;
            ComplexF[] current;
            int        x, y, xDiv, yDiv, xOffset, yOffset;

            for (c = 0; c < cc; c++)
            {
                current = values[c];
                k       = kernel[c];
                x       = 0;
                xDiv    = (targetWidth & 1) == 0 ? -1 : targetWidth / 2;
                xOffset = (fourierWidth - targetWidth) / 2;
                while (x < targetWidth)
                {
                    temp    = k[x];
                    y       = 0;
                    yOffset = (FourierHeight - targetHeight) / 2;
                    yDiv    = (targetHeight & 1) == 0 ? -1 : targetHeight / 2;
                    while (y < targetHeight)
                    {
                        current[(y + yOffset) * fourierWidth + x + xOffset] = new ComplexF()
                        {
                            Real = temp[y]
                        };
                        if (y == yDiv)
                        {
                            yDiv = -1;
                            yOffset++;
                        }
                        else
                        {
                            y++;
                        }
                    }
                    if (x == xDiv)
                    {
                        xDiv = -1;
                        xOffset++;
                    }
                    else
                    {
                        x++;
                    }
                }
            }
            FFT(true);
            if (shiftAxes)
            {
                ShiftAxes = true;
                FFTShift();
            }
        }
Example #34
0
		static private void		UnlockWorkspaceF( ref ComplexF[] workspace ) {
			Debug.Assert( _workspaceF == workspace );
			//Debug.Assert( _workspaceFLocked == true );
			//_workspaceFLocked = false;
			workspace = null;
		}
Example #35
0
        /// <summary>
        /// Computes an in-place complex-to-complex FFT.
        /// </summary>
        private static void FFT(ComplexF[] values, long indexMultiplier, long indexOffset, int log2Length, bool forward)
        {
            long     i, i1, k;
            double   u1, u2, z;
            ComplexF t, temp;
            long     nn = 1L << log2Length;
            long     i2 = nn >> 1;
            long     j = 0L;
            long     nMinusOne = nn - 1L;
            long     index1, index2;

            for (i = 0; i < nMinusOne; i++)
            {
                if (i < j)
                {
                    index1         = i * indexMultiplier + indexOffset;
                    index2         = j * indexMultiplier + indexOffset;
                    t              = values[index1];
                    values[index1] = values[index2];
                    values[index2] = t;
                }
                k = i2;
                while (k <= j)
                {
                    j  -= k;
                    k >>= 1;
                }
                j += k;
            }
            double c1 = -1.0;
            double c2 = 0.0;
            long   l1, l2 = 1L;
            double mult = forward ? -1.0 : 1.0;

            for (long l = 0L; l < log2Length; l++)
            {
                l1   = l2;
                l2 <<= 1;
                u1   = 1.0;
                u2   = 0.0;
                for (j = 0L; j < l1; j++)
                {
                    for (i = j; i < nn; i += l2)
                    {
                        i1             = i + l1;
                        index1         = i * indexMultiplier + indexOffset;
                        index2         = i1 * indexMultiplier + indexOffset;
                        t              = values[index2];
                        t              = new ComplexF((float)(u1 * t.Real - u2 * t.Imaginary), (float)(u1 * t.Imaginary + u2 * t.Real));
                        temp           = values[index1];
                        values[index2] = temp - t;
                        values[index1] = temp + t;
                    }
                    z  = u1 * c1 - u2 * c2;
                    u2 = u1 * c2 + u2 * c1;
                    u1 = z;
                }
                c2 = Math.Sqrt((1.0 - c1) * 0.5) * mult;
                c1 = Math.Sqrt((1.0 + c1) * 0.5);
            }
            if (forward)
            {
                float multiplier = 1f / nn;
                for (i = 0L; i < nn; i++)
                {
                    index1         = i * indexMultiplier + indexOffset;
                    temp           = values[index1];
                    values[index1] = new ComplexF(temp.Real * multiplier, temp.Imaginary * multiplier);
                }
            }
        }
Example #36
0
		/// <summary>
		/// Get the range of element lengths
		/// </summary>
		/// <param name="array"></param>
		/// <param name="minimum"></param>
		/// <param name="maximum"></param>
		static public void GetLengthRange( ComplexF[] array, ref float minimum, ref float maximum ) {
			minimum = +float.MaxValue;
			maximum = -float.MaxValue;
			for( int i = 0; i < array.Length; i ++ ) {
				float temp = array[i].GetModulus();
				minimum = Math.Min( temp, minimum );
				maximum = Math.Max( temp, maximum );
			}
		}
Example #37
0
    // Use this for initialization
    void Start()
    {
        //oceansize= width * s * scale * ( max_LOD * 2 + 1 );
        // normal map size
        n_width  = 256;
        n_height = 256;

        textureA            = new Texture2D(n_width, n_height);
        textureB            = new Texture2D(n_width, n_height);
        textureA.filterMode = FilterMode.Bilinear;
        textureB.filterMode = FilterMode.Bilinear;

        if (!SetupOffscreenRendering())
        {
            material_ocean.SetTexture("_BumpMap", textureA);
            material_ocean.SetTextureScale("_BumpMap", new Vector2(normal_scale, normal_scale));

            material_ocean.SetTexture("_BumpMap2", textureB);
            material_ocean.SetTextureScale("_BumpMap2", new Vector2(normal_scale, normal_scale));
        }

        pixelData = new Color[n_width * n_height];

        // Init the water height matrix
        data = new ComplexF[width * height];
        // lateral offset matrix to get the choppy waves
        data_x = new ComplexF[width * height];

        // tangent
        t_x = new ComplexF[width * height];
        t_y = new ComplexF[width * height];

        n_x = new ComplexF[n_width * n_height];
        n_y = new ComplexF[n_width * n_height];

        // Geometry size
        g_height = height + 1;
        g_width  = width + 1;

        tiles_LOD = new List <List <Mesh> >();

        for (int LOD = 0; LOD < max_LOD * max_LOD; LOD++)
        {
            tiles_LOD.Add(new List <Mesh>());
        }


        GameObject tile;
        int        chDist; // Chebychev distance

        for (int y = 0; y < tiles_y; y++)
        {
            for (int x = 0; x < tiles_x; x++)
            {
                chDist = (int)Mathf.Max(Mathf.Abs(tiles_y / 2 - y), Mathf.Abs(tiles_x / 2 - x));
                chDist = chDist > 0 ? chDist - 1 : 0;
                //Debug.Log(chDist);
                float cy = y - tiles_y / 2;
                float cx = x - tiles_x / 2;
                tile = new GameObject("Tile" + chDist);

                //~ tile.transform.position.x = ;
                //~ tile.transform.position.y = ;
                //~ tile.transform.position.z = ;
                tile.transform.position = new Vector3(Mathf.RoundToInt(cx * size.x * s), Mathf.RoundToInt(-2.0f * chDist), Mathf.RoundToInt(cy * size.z * s));
                //~ tile.transform.localScale.x = s;
                //~ tile.transform.localScale.y = s;
                //~ tile.transform.localScale.z = s;
                tile.transform.localScale = new Vector3(s, s, s);
                MeshFilter filter = tile.AddComponent(typeof(MeshFilter)) as MeshFilter;
                tile.AddComponent("MeshRenderer");
                //~ tile.AddComponent("MeshCollider");
                //~ MeshCollider col = tile.AddComponent(typeof(MeshCollider)) as MeshCollider;
                //~ col.sharedMesh = filter.mesh;
                //~ col.smoothSphereCollisions = true;
                //~ col.convex = true;
                //~ tile.AddComponent(typeof(RecalculateBounds));


                tile.renderer.material = material_ocean;

                //Make child of this object, so we don't clutter up the
                //scene hierarchy more than necessary.
                tile.transform.parent = transform;

                //Also we don't want these to be drawn while doing refraction/reflection passes,
                //so we'll add the to the water layer for easy filtering.
                tile.layer = LayerMask.NameToLayer("Water");

                // Determine which LOD the tile belongs
                //~ tiles_LOD[chDist].Add ((tile.GetComponent(typeof(MeshFilter)) as MeshFilter).mesh);
                tiles_LOD[chDist].Add(filter.mesh);
            }
        }


        // Init wave spectra. One for vertex offset and another for normal map
        h0 = new ComplexF[width * height];
        n0 = new ComplexF[n_width * n_height];

        // Wind restricted to one direction, reduces calculations
        Vector2 wind = new Vector2(0.0f, windx);

        // Initialize wave generator
        for (int y = 0; y < height; y++)
        {
            for (int x = 0; x < width; x++)
            {
                float   yc    = y < height / 2 ? y : -height + y;
                float   xc    = x < width / 2 ? x : -width + x;
                Vector2 vec_k = new Vector2(2.0f * Mathf.PI * xc / size.x, 2.0f * Mathf.PI * yc / size.z);
                h0[width * y + x] = new ComplexF(GaussianRnd(x, y), GaussianRnd(x, y)) * 0.707f * Mathf.Sqrt(P_spectrum(vec_k, wind));
            }
        }

        for (int y = 0; y < n_height; y++)
        {
            for (int x = 0; x < n_width; x++)
            {
                float   yc    = y < n_height / 2 ? y : -n_height + y;
                float   xc    = x < n_width / 2 ? x : -n_width + x;
                Vector2 vec_k = new Vector2(2.0f * Mathf.PI * xc / (size.x / normal_scale), 2.0f * Mathf.PI * yc / (size.z / normal_scale));
                n0[n_width * y + x] = new ComplexF(GaussianRnd(x, y), GaussianRnd(x, y)) * 0.707f * Mathf.Sqrt(P_spectrum(vec_k, wind));
            }
        }

        GenerateHeightmap();
        GenerateBumpmaps();
    }
Example #38
0
		/// <summary>
		/// Add a specific value to each element in the array
		/// </summary>
		/// <param name="array"></param>
		/// <param name="offset"></param>
		static public void Offset( ComplexF[] array, ComplexF offset ) {
			int length = array.Length;
			for( int i = 0; i < length; i ++ ) {
				array[i] += offset;
			}
		}
Example #39
0
    // Update is called once per frame
    void Update()
    {
        if (Input.GetKeyDown(KeyCode.P))
        {
            Application.CaptureScreenshot("Screenshot.png");
        }

        for (int y = 0; y < height; y++)
        {
            for (int x = 0; x < width; x++)
            {
                int     idx   = width * y + x;
                float   yc    = y < height / 2 ? y : -height + y;
                float   xc    = x < width / 2 ? x : -width + x;
                Vector2 vec_k = new Vector2(2.0f * Mathf.PI * xc / size.x, 2.0f * Mathf.PI * yc / size.z);

                float    iwkt   = disp(vec_k) * Time.time;
                ComplexF coeffA = new ComplexF(Mathf.Cos(iwkt), Mathf.Sin(iwkt));
                ComplexF coeffB = coeffA.GetConjugate();

                int ny = y > 0 ? height - y : 0;
                int nx = x > 0 ? width - x : 0;

                data[idx] = h0[idx] * coeffA + h0[width * ny + nx].GetConjugate() * coeffB;
                t_x[idx]  = data[idx] * new ComplexF(0.0f, vec_k.x) - data[idx] * vec_k.y;

                // Choppy wave calcuations
                if (x + y > 0)
                {
                    data[idx] += data[idx] * vec_k.x / vec_k.magnitude;
                }
            }
        }
        material_ocean.SetFloat("_BlendA", Mathf.Cos(Time.time) * 0.1f);
        material_ocean.SetFloat("_BlendB", Mathf.Sin(Time.time) * 0.5f);

        Fourier.FFT2(data, width, height, FourierDirection.Backward);
        Fourier.FFT2(t_x, width, height, FourierDirection.Backward);

        // Get base values for vertices and uv coordinates.
        if (baseHeight == null)
        {
            Mesh mesh = baseMesh;
            baseHeight = mesh.vertices;
            baseUV     = mesh.uv;

            int itemCount = baseHeight.Length;
            uvs      = new Vector2[itemCount];
            vertices = new Vector3[itemCount];
            normals  = new Vector3[itemCount];
            tangents = new Vector4[itemCount];
        }

        //Vector3 vertex;
        Vector3 uv;
        //Vector3 normal;
        float n_scale = size.x / width / scale;

        float scaleA    = choppy_scale / (width * height);
        float scaleB    = scale / (width * height);
        float scaleBinv = 1.0f / scaleB;

        for (int i = 0; i < width * height; i++)
        {
            int iw = i + i / width;
            vertices[iw]    = baseHeight[iw];
            vertices[iw].x += data[i].Im * scaleA;
            vertices[iw].y  = data[i].Re * scaleB;

            normals[iw] = new Vector3(t_x[i].Re, scaleBinv, t_x[i].Im).normalized;

            uv      = baseUV[iw];
            uv.x    = uv.x + Time.time * uv_speed;
            uvs[iw] = uv;


            if (!((i + 1) % width > 0))
            {
                vertices[iw + 1]    = baseHeight[iw + 1];
                vertices[iw + 1].x += data[i + 1 - width].Im * scaleA;
                vertices[iw + 1].y  = data[i + 1 - width].Re * scaleB;

                normals[iw + 1] = new Vector3(t_x[i + 1 - width].Re, scaleBinv, t_x[i + 1 - width].Im).normalized;

                uv          = baseUV[iw + 1];
                uv.x        = uv.x + Time.time * uv_speed;
                uvs[iw + 1] = uv;
            }
        }

        int offset = g_width * (g_height - 1);

        for (int i = 0; i < g_width; i++)
        {
            vertices[i + offset]    = baseHeight[i + offset];
            vertices[i + offset].x += data[i % width].Im * scaleA;
            vertices[i + offset].y  = data[i % width].Re * scaleB;

            normals[i + offset] = new Vector3(t_x[i % width].Re, scaleBinv, t_x[i % width].Im).normalized;

            uv              = baseUV[i + offset];
            uv.x            = uv.x - Time.time * uv_speed;
            uvs[i + offset] = uv;
        }

        for (int i = 0; i < g_width * g_height - 1; i++)
        {
            //Need to preserve w in refraction/reflection mode
            if (!reflectionRefractionEnabled)
            {
                if (((i + 1) % g_width) == 0)
                {
                    tangents[i] = (vertices[i - width + 1] + new Vector3(size.x, 0.0f, 0.0f) - vertices[i]).normalized;
                }
                else
                {
                    tangents[i] = (vertices[i + 1] - vertices[i]).normalized;
                }

                tangents[i].w = 1.0f;
            }
            else
            {
                Vector3 tmp = Vector3.zero;

                if (((i + 1) % g_width) == 0)
                {
                    tmp = (vertices[i - width + 1] + new Vector3(size.x, 0.0f, 0.0f) - vertices[i]).normalized;
                }
                else
                {
                    tmp = (vertices[i + 1] - vertices[i]).normalized;
                }

                tangents[i] = new Vector4(tmp.x, tmp.y, tmp.z, tangents[i].w);
            }
        }

        //In reflection mode, use tangent w for foam strength
        if (reflectionRefractionEnabled)
        {
            for (int y = 0; y < g_height; y++)
            {
                for (int x = 0; x < g_width; x++)
                {
                    if (x + 1 >= g_width)
                    {
                        tangents[x + g_width * y].w = tangents[g_width * y].w;

                        continue;
                    }

                    if (y + 1 >= g_height)
                    {
                        tangents[x + g_width * y].w = tangents[x].w;

                        continue;
                    }

                    Vector3 right = vertices[(x + 1) + g_width * y] - vertices[x + g_width * y];
                    Vector3 back  = vertices[x + g_width * y] - vertices[x + g_width * (y + 1)];

                    float foam = right.x / (size.x / g_width);


                    if (foam < 0.0f)
                    {
                        tangents[x + g_width * y].w = 1;
                    }
                    else if (foam < 0.5f)
                    {
                        tangents[x + g_width * y].w += 2 * Time.deltaTime;
                    }
                    else
                    {
                        tangents[x + g_width * y].w -= 0.5f * Time.deltaTime;
                    }

                    tangents[x + g_width * y].w = Mathf.Clamp(tangents[x + g_width * y].w / foamTime, 0.0f, 2.0f);
                }
            }
        }

        tangents[g_width * g_height - 1] = (vertices[g_width * g_height - 1] + new Vector3(size.x, 0.0f, 0.0f) - vertices[1]).normalized;

        //~ LOD=0;
        for (int LOD = 0; LOD < max_LOD; LOD++)
        {
            int den       = (int)Mathf.Pow(2, LOD);
            int itemcount = (height / den + 1) * (width / den + 1);

            Vector4[] tangentsLOD = new Vector4[itemcount];
            Vector3[] verticesLOD = new Vector3[itemcount];
            Vector3[] normalsLOD  = new Vector3[itemcount];
            Vector2[] uvLOD       = new Vector2[(height / (int)Mathf.Pow(2, LOD) + 1) * (width / (int)Mathf.Pow(2, LOD) + 1)];
            int       idx         = 0;

            for (int y = 0; y < g_height; y += den)
            {
                for (int x = 0; x < g_width; x += den)
                {
                    int idx2 = g_width * y + x;
                    verticesLOD[idx]  = vertices[idx2];
                    uvLOD[idx]        = uvs[g_width * y + x];
                    tangentsLOD[idx]  = tangents[idx2];
                    normalsLOD[idx++] = normals[idx2];
                }
            }
            for (int k = 0; k < tiles_LOD[LOD].Count; k++)
            {
                Mesh meshLOD = tiles_LOD[LOD][k];
                meshLOD.vertices = verticesLOD;
                meshLOD.normals  = normalsLOD;
                meshLOD.uv       = uvLOD;
                meshLOD.tangents = tangentsLOD;
            }
        }
        //oceansize=width*(max_LOD*2+1);
        float width_LOD2 = 175 * s;
        //transform.position.x=mycam.transform.localPosition.x;
        float tmpx = Mathf.RoundToInt(mycam.transform.position.x / width_LOD2);
        float tmpz = Mathf.RoundToInt(mycam.transform.position.z / width_LOD2);

        tmpx = tmpx * width_LOD2 - (width_LOD2 / 2);
        tmpz = tmpz * width_LOD2 - (width_LOD2 / 2);
        //tmpx-=Mathf.RoundToInt(width_LOD2);
        //tmpz-=Mathf.RoundToInt(width_LOD2);

        //~ transform.position.x=tmpx;
        //~ transform.position.z=tmpz;

        transform.position = new Vector3(tmpx, transform.position.y, tmpz);

        //transform.position.z=mycam.transform.localPosition.z*1000;
    }
Example #40
0
		/// <summary>
		/// Multiply each element in the array by a specific value 
		/// </summary>
		/// <param name="array"></param>
		/// <param name="scale"></param>
		/// <param name="start"></param>
		/// <param name="length"></param>
		static public void Scale( ComplexF[] array, ComplexF scale, int start, int length ) {
			Debug.Assert( array != null );
			Debug.Assert( start >= 0 );
			Debug.Assert( length >= 0 );
			Debug.Assert( ( start + length ) < array.Length );

			for( int i = 0; i < length; i ++ ) {
				array[i + start] *= scale;
			}
		}
Example #41
0
    void Update()
    {
        //If player null, search for player by Player tag
        if (player == null)
        {
            player = GameObject.FindGameObjectWithTag("Player").GetComponent <Transform>();
        }

        //Get sun reflection dir from sun object
        if (sun != null)
        {
            SunDir = sun.transform.forward;
            material.SetVector("_SunDir", SunDir);
        }

        if (this.renderReflection)
        {
            RenderObject();
        }

        if (followMainCamera)
        {
            Vector3 centerOffset;

            //centerOffset.x = Mathf.Floor (player.position.x / size.x) * size.x;
            //centerOffset.z = Mathf.Floor (player.position.z / size.z) * size.z;
            centerOffset.y = transform.position.y;
            //centerOffset.x =  (((int)player.position.x + 64) & ~127);
            //centerOffset.z =  (((int)player.position.z + 64) & ~127);

            //Optimized ocean tiles movement
            centerOffset.x = Mathf.Floor((player.position.x + size.x * 0.5f) * sizeInv.x) * size.x;
            centerOffset.z = Mathf.Floor((player.position.z + size.z * 0.5f) * sizeInv.y) * size.z;
            if (transform.position != centerOffset)
            {
                transform.position = centerOffset;
            }
        }


        float hhalf = height / 2f;
        float whalf = width / 2f;
        float time  = Time.time;

        for (int y = 0; y < height; y++)
        {
            for (int x = 0; x < width; x++)
            {
                int     idx   = width * y + x;
                float   yc    = y < hhalf ? y : -height + y;
                float   xc    = x < whalf ? x : -width + x;
                Vector2 vec_k = new Vector2(2.0f * Mathf.PI * xc / size.x, 2.0f * Mathf.PI * yc / size.z);

                float    sqrtMagnitude = (float)System.Math.Sqrt((vec_k.x * vec_k.x) + (vec_k.y * vec_k.y));
                float    iwkt          = (float)System.Math.Sqrt(9.81f * sqrtMagnitude) * time * speed;
                ComplexF coeffA        = new ComplexF((float)System.Math.Cos(iwkt), (float)System.Math.Sin(iwkt));
                ComplexF coeffB;
                coeffB.Re = coeffA.Re;
                coeffB.Im = -coeffA.Im;

                int ny = y > 0 ? height - y : 0;
                int nx = x > 0 ? width - x : 0;

                data [idx] = h0 [idx] * coeffA + h0[width * ny + nx].GetConjugate() * coeffB;
                t_x [idx]  = data [idx] * new ComplexF(0.0f, vec_k.x) - data [idx] * vec_k.y;

                // Choppy wave calculations
                if (x + y > 0)
                {
                    data [idx] += data [idx] * vec_k.x / sqrtMagnitude;
                }
            }
        }

        Fourier.FFT2(data, width, height, FourierDirection.Backward);
        Fourier.FFT2(t_x, width, height, FourierDirection.Backward);


        // Get base values for vertices and uv coordinates.
        if (baseHeight == null)
        {
            baseHeight = baseMesh.vertices;
            vertices   = new Vector3[baseHeight.Length];
            normals    = new Vector3[baseHeight.Length];
            tangents   = new Vector4[baseHeight.Length];
        }

        int   wh        = width * height;
        float scaleA    = choppy_scale / wh;
        float scaleB    = scale / wh;
        float scaleBinv = 1.0f / scaleB;

        for (int i = 0; i < wh; i++)
        {
            int iw = i + i / width;
            vertices [iw]    = baseHeight [iw];
            vertices [iw].x += data [i].Im * scaleA;
            vertices [iw].y  = data [i].Re * scaleB;

            normals [iw] = Vector3.Normalize(new Vector3(t_x [i].Re, scaleBinv, t_x [i].Im));

            if (((i + 1) % width) == 0)
            {
                int iwi    = iw + 1;
                int iwidth = i + 1 - width;
                vertices [iwi]    = baseHeight [iwi];
                vertices [iwi].x += data [iwidth].Im * scaleA;
                vertices [iwi].y  = data [iwidth].Re * scaleB;

                normals [iwi] = Vector3.Normalize(new Vector3(t_x [iwidth].Re, scaleBinv, t_x [iwidth].Im));
            }
        }

        int offset = g_width * (g_height - 1);

        for (int i = 0; i < g_width; i++)
        {
            int io  = i + offset;
            int mod = i % width;
            vertices [io]    = baseHeight [io];
            vertices [io].x += data [mod].Im * scaleA;
            vertices [io].y  = data [mod].Re * scaleB;

            normals [io] = Vector3.Normalize(new Vector3(t_x [mod].Re, scaleBinv, t_x [mod].Im));
        }

        int gwgh = g_width * g_height - 1;

        for (int i = 0; i < gwgh; i++)
        {
            //Need to preserve w in refraction/reflection mode
            if (!reflectionRefractionEnabled)
            {
                if (((i + 1) % g_width) == 0)
                {
                    tangents [i] = Vector3.Normalize((vertices [i - width + 1] + new Vector3(size.x, 0.0f, 0.0f) - vertices [i]));
                }
                else
                {
                    tangents [i] = Vector3.Normalize((vertices [i + 1] - vertices [i]));
                }

                tangents [i].w = 1.0f;
            }
            else
            {
                Vector3 tmp;                // = Vector3.zero;

                if (((i + 1) % g_width) == 0)
                {
                    tmp = Vector3.Normalize(vertices[i - width + 1] + new Vector3(size.x, 0.0f, 0.0f) - vertices [i]);
                }
                else
                {
                    tmp = Vector3.Normalize(vertices [i + 1] - vertices [i]);
                }

                tangents [i] = new Vector4(tmp.x, tmp.y, tmp.z, tangents [i].w);
            }
        }



        //Vector3 playerRelPos =  player.position - transform.position;

        //In reflection mode, use tangent w for foam strength
        if (reflectionRefractionEnabled)
        {
            for (int y = 0; y < g_height; y++)
            {
                for (int x = 0; x < g_width; x++)
                {
                    int item = x + g_width * y;
                    if (x + 1 >= g_width)
                    {
                        tangents [item].w = tangents [g_width * y].w;

                        continue;
                    }

                    if (y + 1 >= g_height)
                    {
                        tangents [item].w = tangents [x].w;

                        continue;
                    }

                    float right = vertices[(x + 1) + g_width * y].x - vertices[item].x;

                    float foam = right / (size.x / g_width);


                    if (foam < 0.0f)
                    {
                        tangents [item].w = 1f;
                    }
                    else if (foam < 0.5f)
                    {
                        tangents [item].w += 3.0f * Time.deltaTime;
                    }
                    else
                    {
                        tangents [item].w -= 0.4f * Time.deltaTime;
                    }

                    if (player != null)
                    {
                        Vector3 player2Vertex = (player.position - vertices[item] - transform.position);
                        // foam around boat
                        if (player2Vertex.x >= size.x)
                        {
                            player2Vertex.x -= size.x;
                        }

                        if (player2Vertex.x <= -size.x)
                        {
                            player2Vertex.x += size.x;
                        }

                        if (player2Vertex.z >= size.z)
                        {
                            player2Vertex.z -= size.z;
                        }

                        if (player2Vertex.z <= -size.z)
                        {
                            player2Vertex.z += size.z;
                        }
                        player2Vertex.y = 0;

                        if (player2Vertex.sqrMagnitude < wakeDistance * wakeDistance)
                        {
                            tangents[item].w += 3.0f * Time.deltaTime;
                        }
                    }


                    tangents [item].w = Mathf.Clamp(tangents[item].w, 0.0f, 2.0f);
                }
            }
        }

        tangents [gwgh] = Vector4.Normalize(vertices [gwgh] + new Vector3(size.x, 0.0f, 0.0f) - vertices [1]);

        for (int L0D = 0; L0D < max_LOD; L0D++)
        {
            int den       = (int)System.Math.Pow(2f, L0D);
            int itemcount = (int)((height / den + 1) * (width / den + 1));

            Vector4[] tangentsLOD = new Vector4[itemcount];
            Vector3[] verticesLOD = new Vector3[itemcount];
            Vector3[] normalsLOD  = new Vector3[itemcount];

            int idx = 0;

            for (int y = 0; y < g_height; y += den)
            {
                for (int x = 0; x < g_width; x += den)
                {
                    int idx2 = g_width * y + x;
                    verticesLOD [idx]  = vertices [idx2];
                    tangentsLOD [idx]  = tangents [idx2];
                    normalsLOD [idx++] = normals [idx2];
                }
            }
            for (int k = 0; k < tiles_LOD[L0D].Count; k++)
            {
                Mesh meshLOD = tiles_LOD [L0D][k];
                meshLOD.vertices = verticesLOD;
                meshLOD.normals  = normalsLOD;
                meshLOD.tangents = tangentsLOD;
            }
        }
    }
Example #42
0
		/// <summary>
		/// Multiply each element in lhs array with corresponding element in rhs array and
		/// put product in result array
		/// </summary>
		/// <param name="lhs"></param>
		/// <param name="rhs"></param>
		/// <param name="result"></param>
		static public void Multiply( ComplexF[] lhs, ComplexF[] rhs, ComplexF[] result ) {
			Debug.Assert( lhs != null );
			Debug.Assert( rhs != null );
			Debug.Assert( result != null );
			Debug.Assert( lhs.Length == rhs.Length );
			Debug.Assert( lhs.Length == result.Length );

			int length = lhs.Length;
			for( int i = 0; i < length; i ++ ) {
				result[i] = lhs[i] * rhs[i];
			}
		}
Example #43
0
 public float mag2db(ComplexF y)
 {
     return(20.0f * (float)Math.Log10(Math.Sqrt(y.Re * y.Re + y.Im * y.Im) / .02));
 }
Example #44
0
		/// <summary>
		/// Divide each element in lhs array with corresponding element in rhs array and
		/// put product in result array
		/// </summary>
		/// <param name="lhs"></param>
		/// <param name="rhs"></param>
		/// <param name="result"></param>
		static public void Divide( ComplexF[] lhs, ComplexF[] rhs, ComplexF[] result ) {
			Debug.Assert( lhs != null );
			Debug.Assert( rhs != null );
			Debug.Assert( result != null );
			Debug.Assert( lhs.Length == rhs.Length );
			Debug.Assert( lhs.Length == result.Length );

			ComplexF zero = ComplexF.Zero;
			int length = lhs.Length;
			for( int i = 0; i < length; i ++ ) {
				if( rhs[i] != zero ) {
					result[i] = lhs[i] / rhs[i];
				}
				else {
					result[i] = zero;
				}
			}
		}
Example #45
0
		static private void Swap( ref ComplexF a, ref ComplexF b ) {
			ComplexF temp = a;
			a = b;
			b = temp;
		}
Example #46
0
		/// <summary>
		/// Scale and offset the elements in the array so that the
		/// overall range is [0, 1]
		/// </summary>
		/// <param name="array"></param>
		static public void Normalize( ComplexF[] array ) {
			float min = 0, max = 0;
			GetLengthRange( array, ref min, ref max );
			Scale( array, ( 1 / ( max - min ) ) );
			Offset( array, ( - min / ( max - min ) ) );
		}
Example #47
0
		/// <summary>
		/// Compute a 1D fast Fourier transform of a dataset of complex numbers.
		/// </summary>
		/// <param name="data"></param>
		/// <param name="length"></param>
		/// <param name="direction"></param>
		public static void	FFT_Quick( ComplexF[] data, int length, FourierDirection direction ) {
			/*if( data == null ) {
				throw new ArgumentNullException( "data" );
			}
			if( data.Length < length ) {
				throw new ArgumentOutOfRangeException( "length", length, "must be at least as large as 'data.Length' parameter" );
			}
			if( Fourier.IsPowerOf2( length ) == false ) {
				throw new ArgumentOutOfRangeException( "length", length, "must be a power of 2" );
			}

			Fourier.SyncLookupTableLength( length );*/

			int ln = Fourier.Log2( length );
			
			// reorder array
			Fourier.ReorderArray( data );
			
			// successive doubling
			int N = 1;
			int signIndex = ( direction == FourierDirection.Forward ) ? 0 : 1;
			
			for( int level = 1; level <= ln; level ++ ) {
				int M = N;
				N <<= 1;

				float[] uRLookup = _uRLookupF[ level, signIndex ];
				float[] uILookup = _uILookupF[ level, signIndex ];

				for( int j = 0; j < M; j ++ ) {
					float uR = uRLookup[j];
					float uI = uILookup[j];

					for( int even = j; even < length; even += N ) {
						int odd	 = even + M;
						
						float	r = data[ odd ].Re;
						float	i = data[ odd ].Im;

						float	odduR = r * uR - i * uI;
						float	odduI = r * uI + i * uR;

						r = data[ even ].Re;
						i = data[ even ].Im;
						
						data[ even ].Re	= r + odduR;
						data[ even ].Im	= i + odduI;
						
						data[ odd ].Re	= r - odduR;
						data[ odd ].Im	= i - odduI;
					}
				}
			}

		}
Example #48
0
		static private void		LockWorkspaceF( int length, ref ComplexF[] workspace ) {
			//Debug.Assert( _workspaceFLocked == false );
			//_workspaceFLocked = true;
			if( length >= _workspaceF.Length ) {
				_workspaceF	= new ComplexF[ length ];
			}
			workspace =	_workspaceF;
		}
Example #49
0
		/// <summary>
		/// Compute a 1D fast Fourier transform of a dataset of complex numbers.
		/// </summary>
		/// <param name="data"></param>
		/// <param name="direction"></param>
		public static void	FFT( ComplexF[] data, FourierDirection direction ) {
			if( data == null ) {
				throw new ArgumentNullException( "data" );
			}
			Fourier.FFT( data, data.Length, direction );
		}
Example #50
0
    void Update()
    {
        //If player null, search for player by Player tag
        if(player == null)
            player = GameObject.FindGameObjectWithTag("Player").GetComponent<Transform>();

        //Get sun reflection dir from sun object
        if(sun != null){
            SunDir = sun.transform.forward;
            material.SetVector ("_SunDir", SunDir);
        }

        if (this.renderReflection)
            RenderObject ();

        if (followMainCamera) {

            Vector3 centerOffset;

            //centerOffset.x = Mathf.Floor (player.position.x / size.x) * size.x;
            //centerOffset.z = Mathf.Floor (player.position.z / size.z) * size.z;
            centerOffset.y = transform.position.y;
            //centerOffset.x =  (((int)player.position.x + 64) & ~127);
            //centerOffset.z =  (((int)player.position.z + 64) & ~127);

            //Optimized ocean tiles movement
            centerOffset.x = Mathf.Floor( (player.position.x + size.x * 0.5f)  * sizeInv.x )   *  size.x;
            centerOffset.z = Mathf.Floor( (player.position.z + size.z * 0.5f)  * sizeInv.y )   *  size.z;
            if(transform.position != centerOffset)
                transform.position = centerOffset;

        }

        float hhalf=height/2f;
        float whalf=width/2f;
        float time=Time.time;
        for (int y = 0; y<height; y++) {
            for (int x = 0; x<width; x++) {
                int idx = width * y + x;
                float yc = y < hhalf ? y : -height + y;
                float xc = x < whalf ? x : -width + x;
                Vector2 vec_k = new Vector2 (2.0f * Mathf.PI * xc / size.x, 2.0f * Mathf.PI * yc / size.z);

                float sqrtMagnitude=(float)System.Math.Sqrt((vec_k.x * vec_k.x) + (vec_k.y * vec_k.y));
                float iwkt = (float)System.Math.Sqrt(9.81f * sqrtMagnitude) * time * speed;
                ComplexF coeffA = new ComplexF ((float)System.Math.Cos(iwkt), (float)System.Math.Sin(iwkt));
                ComplexF coeffB;
                coeffB.Re = coeffA.Re;
                coeffB.Im = -coeffA.Im;

                int ny = y > 0 ? height - y : 0;
                int nx = x > 0 ? width - x : 0;

                data [idx] = h0 [idx] * coeffA + h0[width * ny + nx].GetConjugate() * coeffB;
                t_x [idx] = data [idx] * new ComplexF (0.0f, vec_k.x) - data [idx] * vec_k.y;

                // Choppy wave calculations
                if (x + y > 0)
                    data [idx] += data [idx] * vec_k.x / sqrtMagnitude;
            }
        }

        Fourier.FFT2 (data, width, height, FourierDirection.Backward);
        Fourier.FFT2 (t_x, width, height, FourierDirection.Backward);

        // Get base values for vertices and uv coordinates.
        if (baseHeight == null) {
            baseHeight = baseMesh.vertices;
            vertices = new Vector3[baseHeight.Length];
            normals = new Vector3[baseHeight.Length];
            tangents = new Vector4[baseHeight.Length];
        }

        int wh=width*height;
        float scaleA = choppy_scale / wh;
        float scaleB = scale / wh;
        float scaleBinv = 1.0f / scaleB;

        for (int i=0; i<wh; i++) {
            int iw = i + i / width;
            vertices [iw] = baseHeight [iw];
            vertices [iw].x += data [i].Im * scaleA;
            vertices [iw].y = data [i].Re * scaleB;

            normals [iw] = Vector3.Normalize(new Vector3 (t_x [i].Re, scaleBinv, t_x [i].Im));

            if (((i + 1) % width)==0) {
                int iwi=iw+1;
                int iwidth=i+1-width;
                vertices [iwi] = baseHeight [iwi];
                vertices [iwi].x += data [iwidth].Im * scaleA;
                vertices [iwi].y = data [iwidth].Re * scaleB;

                normals [iwi] = Vector3.Normalize(new Vector3 (t_x [iwidth].Re, scaleBinv, t_x [iwidth].Im));

            }
        }

        int offset = g_width * (g_height - 1);

        for (int i=0; i<g_width; i++) {
            int io=i+offset;
            int mod=i % width;
            vertices [io] = baseHeight [io];
            vertices [io].x += data [mod].Im * scaleA;
            vertices [io].y = data [mod].Re * scaleB;

            normals [io] = Vector3.Normalize(new Vector3 (t_x [mod].Re, scaleBinv, t_x [mod].Im));
        }

        int gwgh=g_width*g_height-1;
        for (int i=0; i<gwgh; i++) {

            //Need to preserve w in refraction/reflection mode
            if (!reflectionRefractionEnabled) {
                if (((i + 1) % g_width) == 0) {
                    tangents [i] = Vector3.Normalize((vertices [i - width + 1] + new Vector3 (size.x, 0.0f, 0.0f) - vertices [i]));
                } else {
                    tangents [i] = Vector3.Normalize((vertices [i + 1] - vertices [i]));
                }

                tangents [i].w = 1.0f;
            } else {
                Vector3 tmp;// = Vector3.zero;

                if (((i + 1) % g_width) == 0) {
                    tmp = Vector3.Normalize(vertices[i - width + 1] + new Vector3 (size.x, 0.0f, 0.0f) - vertices [i]);
                } else {
                    tmp = Vector3.Normalize(vertices [i + 1] - vertices [i]);
                }

                tangents [i] = new Vector4 (tmp.x, tmp.y, tmp.z, tangents [i].w);
            }
        }

        //Vector3 playerRelPos =  player.position - transform.position;

        //In reflection mode, use tangent w for foam strength
        if (reflectionRefractionEnabled) {
            for (int y = 0; y < g_height; y++) {
                for (int x = 0; x < g_width; x++) {
                    int item=x + g_width * y;
                    if (x + 1 >= g_width) {
                        tangents [item].w = tangents [g_width * y].w;

                        continue;
                    }

                    if (y + 1 >= g_height) {
                        tangents [item].w = tangents [x].w;

                        continue;
                    }

                    float right = vertices[(x + 1) + g_width * y].x - vertices[item].x;

                    float foam = right/(size.x / g_width);

                    if (foam < 0.0f)
                        tangents [item].w = 1f;
                    else if (foam < 0.5f)
                        tangents [item].w += 3.0f * Time.deltaTime;
                    else
                        tangents [item].w -= 0.4f * Time.deltaTime;

                    if (player != null )
                    {
                        Vector3 player2Vertex = (player.position - vertices[item] - transform.position);
                        // foam around boat
                        if (player2Vertex.x >= size.x)
                            player2Vertex.x -= size.x;

                        if (player2Vertex.x<= -size.x)
                            player2Vertex.x += size.x;

                        if (player2Vertex.z >= size.z)
                            player2Vertex.z -= size.z;

                        if (player2Vertex.z<= -size.z)
                            player2Vertex.z += size.z;
                        player2Vertex.y = 0;

                        if (player2Vertex.sqrMagnitude < wakeDistance * wakeDistance)
                            tangents[item].w += 3.0f * Time.deltaTime;
                    }

                    tangents [item].w = Mathf.Clamp (tangents[item].w, 0.0f, 2.0f);
                }
            }
        }

        tangents [gwgh] = Vector4.Normalize(vertices [gwgh] + new Vector3 (size.x, 0.0f, 0.0f) - vertices [1]);

        for (int L0D=0; L0D<max_LOD; L0D++) {
            int den = (int)System.Math.Pow (2f, L0D);
            int itemcount = (int)((height / den + 1) * (width / den + 1));

            Vector4[] tangentsLOD = new Vector4[itemcount];
            Vector3[] verticesLOD = new Vector3[itemcount];
            Vector3[] normalsLOD = new Vector3[itemcount];

            int idx = 0;

            for (int y=0; y<g_height; y+=den) {
                for (int x=0; x<g_width; x+=den) {
                    int idx2 = g_width * y + x;
                    verticesLOD [idx] = vertices [idx2];
                    tangentsLOD [idx] = tangents [idx2];
                    normalsLOD [idx++] = normals [idx2];
                }
            }
            for (int k=0; k< tiles_LOD[L0D].Count; k++) {
                Mesh meshLOD = tiles_LOD [L0D][k];
                meshLOD.vertices = verticesLOD;
                meshLOD.normals = normalsLOD;
                meshLOD.tangents = tangentsLOD;
            }
        }
    }
Example #51
0
        /// <summary>
        /// Update is called once per frame.
        /// </summary>
        private void Update()
        {
            if (!simulationEnabled)
            {
                return;
            }

            // Calculate mesh vertices, uv and tangents.
            float halfWidth  = tilePolygonWidth / 2.0f;
            float halfHeight = tilePolygonHeight / 2.0f;
            float time       = Time.time;

            for (int y = 0; y < tilePolygonHeight; ++y)
            {
                for (int x = 0; x < tilePolygonWidth; ++x)
                {
                    int     idx   = tilePolygonWidth * y + x;
                    float   yCopy = y < halfHeight ? y : y - tilePolygonHeight;
                    float   xCopy = x < halfWidth ? x : x - tilePolygonWidth;
                    Vector2 vecK  = new Vector2(2.0f * Mathf.PI * xCopy / oceanTileSize.x, 2.0f * Mathf.PI * yCopy / oceanTileSize.z);

                    float    sqrtMagnitude = (float)Math.Sqrt(Mathf.Pow(vecK.x, 2.0f) + Mathf.Pow(vecK.y, 2.0f));
                    float    offset        = Mathf.Sqrt(GRAVITY_ACCELERATION * sqrtMagnitude) * time * waveSpeed;
                    ComplexF complexFA     = new ComplexF(Mathf.Cos(offset), Mathf.Sin(offset));
                    ComplexF complexFB;
                    complexFB.Re = complexFA.Re;
                    complexFB.Im = -complexFA.Im;

                    int nY = y > 0 ? tilePolygonHeight - y : 0;
                    int nX = x > 0 ? tilePolygonWidth - x : 0;

                    waterHeightData[idx] = vertexSpectra[idx] * complexFA + vertexSpectra[tilePolygonWidth * nY + nX].GetConjugate() * complexFB;
                    tangentX[idx]        = waterHeightData[idx] * new ComplexF(0.0f, vecK.x) - waterHeightData[idx] * vecK.y;

                    // Choppy wave calculation.
                    if (x + y > 0)
                    {
                        waterHeightData[idx] += waterHeightData[idx] * vecK.x / sqrtMagnitude;
                    }
                }
            }

            Fourier.FFT2(waterHeightData, tilePolygonWidth, tilePolygonHeight, FourierDirection.Backward);
            Fourier.FFT2(tangentX, tilePolygonWidth, tilePolygonHeight, FourierDirection.Backward);

            // Get base values for vertices and uv coordinates.
            if (baseHeights == null)
            {
                baseHeights = baseMesh.vertices;
                vertices    = new Vector3[baseHeights.Length];
                normals     = new Vector3[baseHeights.Length];
                tangents    = new Vector4[baseHeights.Length];
            }

            int   area             = tilePolygonWidth * tilePolygonHeight;
            float scaleX           = choppyScale / area;
            float scaleY           = waveScaleRealTime / area;
            float scaleYReciprocal = MathUtility.GetReciprocal(scaleY);

            for (int i = 0; i < area; ++i)
            {
                int index = i + i / tilePolygonWidth;
                vertices[index]    = baseHeights[index];
                vertices[index].x += waterHeightData[i].Im * scaleX;
                vertices[index].y  = waterHeightData[i].Re * scaleY;

                normals[index] = Vector3.Normalize(new Vector3(tangentX[i].Re, scaleYReciprocal, tangentX[i].Im));

                if ((i + 1) % tilePolygonWidth == 0)
                {
                    int indexPlus = index + 1;
                    int iWidth    = i + 1 - tilePolygonWidth;
                    vertices[indexPlus]    = baseHeights[indexPlus];
                    vertices[indexPlus].x += waterHeightData[iWidth].Im * scaleX;
                    vertices[indexPlus].y  = waterHeightData[iWidth].Re * scaleY;

                    normals[indexPlus] = Vector3.Normalize(new Vector3(tangentX[iWidth].Re, scaleYReciprocal, tangentX[iWidth].Im));
                }
            }

            int indexOffset = geometryWidth * (geometryHeight - 1);

            for (int i = 0; i < geometryWidth; ++i)
            {
                int index = i + indexOffset;
                int mod   = i % tilePolygonWidth;

                vertices[index]    = baseHeights[index];
                vertices[index].x += waterHeightData[mod].Im * scaleX;
                vertices[index].y  = waterHeightData[mod].Re * scaleY;

                normals[index] = Vector3.Normalize(new Vector3(tangentX[mod].Re, scaleYReciprocal, tangentX[mod].Im));
            }

            int geometryArea = geometryWidth * geometryHeight - 1;

            for (int i = 0; i < geometryArea; ++i)
            {
                Vector3 tmp;

                if ((i + 1) % geometryWidth == 0)
                {
                    tmp = Vector3.Normalize(vertices[i - tilePolygonWidth + 1] + new Vector3(oceanTileSize.x, 0.0f, 0.0f) - vertices[i]);
                }
                else
                {
                    tmp = Vector3.Normalize(vertices[i + 1] - vertices[i]);
                }

                tangents[i] = new Vector4(tmp.x, tmp.y, tmp.z, tangents[i].w);
            }

            for (int y = 0; y < geometryHeight; ++y)
            {
                for (int x = 0; x < geometryWidth; ++x)
                {
                    int index = x + geometryWidth * y;

                    if (x + 1 >= geometryWidth)
                    {
                        tangents[index].w = tangents[geometryWidth * y].w;
                        continue;
                    }

                    if (y + 1 >= geometryHeight)
                    {
                        tangents[index].w = tangents[x].w;
                        continue;
                    }

                    float right = vertices[x + 1 + geometryWidth * y].x - vertices[index].x;
                    float foam  = right / (oceanTileSize.x / geometryWidth);

                    if (foam < 0.0f)
                    {
                        tangents[index].w = 1.0f;
                    }
                    else if (foam < 0.5f)
                    {
                        tangents[index].w += 3.0f * Time.deltaTime;
                    }
                    else
                    {
                        tangents[index].w -= 0.4f * Time.deltaTime;
                    }

                    tangents[index].w = Mathf.Clamp(tangents[index].w, 0.0f, 2.0f);
                }
            }

            tangents[geometryArea] = Vector4.Normalize(vertices[geometryArea] + new Vector3(oceanTileSize.x, 0.0f, 0.0f) - vertices[1]);

            for (int level = 0; level < MAX_LOD; ++level)
            {
                int pow    = (int)Math.Pow(2.0f, level);
                int length = (int)((tilePolygonHeight / pow + 1) * (tilePolygonWidth / pow + 1));

                Vector4[] tangentsLOD = new Vector4[length];
                Vector3[] verticesLOD = new Vector3[length];
                Vector3[] normalsLOD  = new Vector3[length];

                int index = 0;

                for (int y = 0; y < geometryHeight; y += pow)
                {
                    for (int x = 0; x < geometryWidth; x += pow)
                    {
                        int indexTemp = geometryWidth * y + x;
                        verticesLOD[index]  = vertices[indexTemp];
                        tangentsLOD[index]  = tangents[indexTemp];
                        normalsLOD[index++] = normals[indexTemp];
                    }
                }

                for (int i = 0, count = tilesLOD[level].Count; i < count; ++i)
                {
                    Mesh meshLOD = tilesLOD[level][i];
                    meshLOD.vertices = verticesLOD;
                    meshLOD.normals  = normalsLOD;
                    meshLOD.tangents = tangentsLOD;
                }
            }

            if (reflectionEnabled)
            {
                RenderReflectionAndRefraction();
            }
        }