您最多选择25个主题
主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
90 行
4.0 KiB
90 行
4.0 KiB
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
|
|
namespace GerstnerWaves
|
|
{
|
|
public static class GerstnerWaves
|
|
{
|
|
public static int _WaveCount;
|
|
public static Vector4[] _WaveData = new Vector4[10];
|
|
public static Vector4[] _WaveData2 = new Vector4[10];
|
|
|
|
static WaveStruct tempWave = new WaveStruct();
|
|
public static WaveStruct GerstnerWave(Vector2 pos, int numWaves, float amplitude, float direction, float wavelength, bool omni, Vector2 omniPos)
|
|
{
|
|
//float noise = SimplexNoise2D.snoise(new Vector2(pos.x, pos.z) * 0.01f) * 2f;
|
|
//pos += new Vector3(noise, 0f, noise);// add noise here
|
|
////////////////////////////////wave value calculations//////////////////////////
|
|
Vector3 wave = Vector3.zero;//wave vector
|
|
float wSpeed = Mathf.Sqrt(9.8f * (6.28318f / wavelength));//frequency of the wave based off wavelength
|
|
float w = 6.28318f / wavelength;//2pi over wavelength(hardcoded)
|
|
float peak = 1;//peak value, 1 is the sharpest peaks
|
|
float qi = peak / (w * amplitude * numWaves);
|
|
|
|
Vector2 windDir = Vector2.zero;
|
|
float dir = 0;
|
|
if (!omni)
|
|
{
|
|
direction = direction * Mathf.Deg2Rad;//convert the incoming degrees to radians
|
|
windDir = new Vector2(Mathf.Sin(direction), Mathf.Cos(direction)).normalized;//calculate wind direction - TODO - currently radians
|
|
dir = Vector2.Dot(pos, windDir);//calculate a gradient along the wind direction
|
|
}
|
|
else
|
|
{
|
|
windDir = (pos - omniPos).normalized;
|
|
dir = Vector2.Dot(windDir, (pos - omniPos));
|
|
}
|
|
|
|
////////////////////////////position output calculations/////////////////////////
|
|
float calc = dir * w + -Time.time * wSpeed;//the wave calculation
|
|
float cosCalc = Mathf.Cos(calc);//cosine version(used for horizontal undulation)
|
|
float sinCalc = Mathf.Sin(calc);//sin version(used for vertical undulation)
|
|
|
|
//calculate the offsets for the current point
|
|
wave.x = qi * amplitude * windDir.x * cosCalc;
|
|
wave.z = qi * amplitude * windDir.y * cosCalc;
|
|
wave.y = (((sinCalc * 0.5f + 0.5f) * amplitude) - amplitude * 0.5f) / numWaves;//the height is divided by the number of waves
|
|
|
|
////////////////////////////normal output calculations/////////////////////////
|
|
float wa = w * amplitude;
|
|
//normal vector
|
|
Vector3 n = new Vector3(-(windDir.x * wa * cosCalc),
|
|
-(windDir.y * wa * cosCalc),
|
|
1 - (qi * wa * sinCalc));
|
|
|
|
////////////////////////////////assign to output///////////////////////////////
|
|
tempWave.position = wave * Mathf.Clamp01(amplitude * 10000);
|
|
tempWave.normal = (n / numWaves) * amplitude;
|
|
|
|
return tempWave;
|
|
}
|
|
|
|
static Vector2 tempPos = new Vector2();
|
|
static WaveStruct[] tempWaves = new WaveStruct[10];
|
|
static WaveStruct tempWaveOut = new WaveStruct();
|
|
|
|
public static WaveStruct SampleWaves(Vector3 position, float opacity)
|
|
{
|
|
tempPos.x = position.x;
|
|
tempPos.y = position.z;
|
|
tempWaveOut.position = Vector3.zero;
|
|
tempWaveOut.normal = Vector3.zero;
|
|
|
|
for (int i = 0; i < _WaveCount; i++)
|
|
{
|
|
tempWaves[i] = GerstnerWave(tempPos, _WaveCount, _WaveData[i].x * opacity, _WaveData[i].y, _WaveData[i].z, _WaveData[i].w == 0 ? false : true, new Vector2(_WaveData2[i].x, _WaveData2[i].y)); // calculate the wave
|
|
tempWaveOut.position += tempWaves[i].position; // add the position
|
|
tempWaveOut.normal += tempWaves[i].normal; // add the normal
|
|
}
|
|
return tempWaveOut;
|
|
}
|
|
|
|
}
|
|
|
|
public class WaveStruct
|
|
{
|
|
public Vector3 position;
|
|
public Vector3 normal;
|
|
}
|
|
}
|