void Reset() { // Initialise with spectrum. _spectrum = ScriptableObject.CreateInstance <OceanWaveSpectrum>(); _spectrum.name = "Default Waves (auto)"; _spectrum.Upgrade(); }
private void OnGUIPlacing() { _scrollPosition = EditorGUILayout.BeginScrollView(_scrollPosition); EditorGUI.BeginChangeCheck(); EditorGUILayout.LabelField("Placement", EditorStyles.boldLabel); _position = EditorGUILayout.Vector3Field("Center position", _position); _sizeX = EditorGUILayout.FloatField("Size X", _sizeX); _sizeZ = EditorGUILayout.FloatField("Size Z", _sizeZ); _rotation = EditorGUILayout.FloatField("Rotation", _rotation); EditorGUILayout.Space(); _createDepthCache = EditorGUILayout.BeginToggleGroup("Create Depth Cache", _createDepthCache); _depthCacheLayerName = EditorGUILayout.TextField("Layer for cache", _depthCacheLayerName); EditorGUILayout.EndToggleGroup(); EditorGUILayout.Space(); _createGerstnerWaves = EditorGUILayout.BeginToggleGroup("Create Gerstner Waves", _createGerstnerWaves); _gerstnerWindDirection = EditorGUILayout.FloatField("Wind direction angle", _gerstnerWindDirection); _gerstnerWaveSpectrum = EditorGUILayout.ObjectField("Wave spectrum", _gerstnerWaveSpectrum, typeof(OceanWaveSpectrum), false) as OceanWaveSpectrum; _gerstnerMaterial = EditorGUILayout.ObjectField("Gerstner material", _gerstnerMaterial, typeof(Material), false) as Material; EditorGUILayout.EndToggleGroup(); EditorGUILayout.Space(); _createClipArea = EditorGUILayout.BeginToggleGroup("Create Clip Area", _createClipArea); _clipMaterial = EditorGUILayout.ObjectField("Clip material", _clipMaterial, typeof(Material), false) as Material; if (_createClipArea) { EditorGUILayout.HelpBox("Create Clip Surface Data should be enabled on the OceanRnederer component, and the Default Clipping State should be set to Everything Clipped.", MessageType.Info); } EditorGUILayout.EndToggleGroup(); if (EditorGUI.EndChangeCheck()) { UpdateProxy(); SceneView.RepaintAll(); } EditorGUILayout.Space(); if (GUILayout.Button("Create")) { CreateWaterBody(); } if (GUILayout.Button("Done")) { _state = State.Idle; // Refresh scene view GetWindow <SceneView>(); } EditorGUILayout.EndScrollView(); }
void Start() { if (_spectrum == null) { _spectrum = ScriptableObject.CreateInstance <OceanWaveSpectrum>(); _spectrum.name = "Default Waves (auto)"; } }
public FFTCompute(int resolution, float windSpeed, float windTurbulence, float windDirRad, OceanWaveSpectrum spectrum) { Debug.Assert(Mathf.NextPowerOfTwo(resolution) == resolution, "FFTCompute resolution must be power of 2"); _resolution = resolution; _windSpeed = windSpeed; _windTurbulence = windTurbulence; _windDirRad = windDirRad; _spectrum = spectrum; }
void Start() { _waveShader = Shader.Find("Crest/Inputs/Animated Waves/Gerstner Batch"); Debug.Assert(_waveShader, "Could not load Gerstner wave shader, make sure it is packaged in the build."); if (_spectrum == null) { _spectrum = ScriptableObject.CreateInstance <OceanWaveSpectrum>(); _spectrum.name = "Default Waves (auto)"; } }
float MaxSimDt(int lodIdx) { var ocean = OceanRenderer.Instance; // Limit timestep based on Courant constant: https://www.uio.no/studier/emner/matnat/ifi/nedlagte-emner/INF2340/v05/foiler/sim04.pdf var Cmax = Settings._courantNumber; var minWavelength = ocean._lodTransform.MaxWavelength(lodIdx) / 2f; var waveSpeed = OceanWaveSpectrum.ComputeWaveSpeed(minWavelength, Settings._gravityMultiplier); // 0.5f because its 2D var maxDt = 0.5f * Cmax * ocean.CalcGridSize(lodIdx) / waveSpeed; return(maxDt); }
void Start() { if (_spectrum == null) { _spectrum = ScriptableObject.CreateInstance <OceanWaveSpectrum>(); _spectrum.name = "Default Waves (auto)"; } #if UNITY_EDITOR _spectrum.Upgrade(); #endif InitBatches(); }
void Start() { if (OceanRenderer.Instance == null) { enabled = false; return; } if (_spectrum == null) { _spectrum = ScriptableObject.CreateInstance <OceanWaveSpectrum>(); _spectrum.name = "Default Waves (auto)"; } }
void Start() { if (OceanRenderer.Instance == null) { enabled = false; return; } _waveShader = Shader.Find("Crest/Inputs/Animated Waves/Gerstner Batch"); if (_spectrum == null) { _spectrum = ScriptableObject.CreateInstance <OceanWaveSpectrum>(); _spectrum.name = "Default Waves (auto)"; } }
private void OnEnable() { #if UNITY_EDITOR // Initialise with spectrum if (_spectrum == null) { _spectrum = ScriptableObject.CreateInstance <OceanWaveSpectrum>(); _spectrum.name = "Default Waves (auto)"; } if (EditorApplication.isPlaying && !Validate(OceanRenderer.Instance, ValidatedHelper.DebugLog)) { enabled = false; return; } _spectrum.Upgrade(); #endif InitBatches(); }
public override void OnInspectorGUI() { base.OnInspectorGUI(); var showAdvancedControls = serializedObject.FindProperty("_showAdvancedControls").boolValue; // preamble - styles for toggle buttons. this code and the below was based off the useful info provided by user Lasse here: // https://gamedev.stackexchange.com/questions/98920/how-do-i-create-a-toggle-button-in-unity-inspector if (ToggleButtonStyleNormal == null) { ToggleButtonStyleNormal = "Button"; ToggleButtonStyleToggled = new GUIStyle(ToggleButtonStyleNormal); ToggleButtonStyleToggled.normal.background = ToggleButtonStyleToggled.active.background; } EditorGUILayout.Space(); var spDisabled = serializedObject.FindProperty("_powerDisabled"); EditorGUILayout.BeginHorizontal(); bool allEnabled = true; for (int i = 0; i < spDisabled.arraySize; i++) { if (spDisabled.GetArrayElementAtIndex(i).boolValue) { allEnabled = false; } } bool toggle = allEnabled; if (toggle != EditorGUILayout.Toggle(toggle, GUILayout.Width(13f))) { for (int i = 0; i < spDisabled.arraySize; i++) { spDisabled.GetArrayElementAtIndex(i).boolValue = toggle; } } EditorGUILayout.LabelField("Spectrum", EditorStyles.boldLabel); EditorGUILayout.EndHorizontal(); var spec = target as OceanWaveSpectrum; var spPower = serializedObject.FindProperty("_powerLog"); var spChopScales = serializedObject.FindProperty("_chopScales"); var spGravScales = serializedObject.FindProperty("_gravityScales"); for (int i = 0; i < spPower.arraySize; i++) { EditorGUILayout.BeginHorizontal(); var spDisabled_i = spDisabled.GetArrayElementAtIndex(i); spDisabled_i.boolValue = !EditorGUILayout.Toggle(!spDisabled_i.boolValue, GUILayout.Width(15f)); float smallWL = OceanWaveSpectrum.SmallWavelength(i); var spPower_i = spPower.GetArrayElementAtIndex(i); if (showAdvancedControls) { EditorGUILayout.LabelField(string.Format("{0}", smallWL), EditorStyles.boldLabel); EditorGUILayout.EndHorizontal(); EditorGUILayout.Slider(spPower_i, OceanWaveSpectrum.MIN_POWER_LOG, OceanWaveSpectrum.MAX_POWER_LOG, " Power"); } else { EditorGUILayout.LabelField(string.Format("{0}", smallWL), GUILayout.Width(30f)); spPower_i.floatValue = GUILayout.HorizontalSlider(spPower_i.floatValue, OceanWaveSpectrum.MIN_POWER_LOG, OceanWaveSpectrum.MAX_POWER_LOG); EditorGUILayout.EndHorizontal(); } if (showAdvancedControls) { EditorGUILayout.Slider(spChopScales.GetArrayElementAtIndex(i), 0f, 4f, " Chop Scale"); EditorGUILayout.Slider(spGravScales.GetArrayElementAtIndex(i), 0f, 4f, " Grav Scale"); } } EditorGUILayout.Space(); EditorGUILayout.LabelField("Empirical Spectra", EditorStyles.boldLabel); EditorGUILayout.BeginHorizontal(); float spd_kmh = _windSpeed * 3.6f; EditorGUILayout.LabelField("Wind speed (km/h)", GUILayout.Width(120f)); spd_kmh = EditorGUILayout.Slider(spd_kmh, 0f, 60f); _windSpeed = spd_kmh / 3.6f; EditorGUILayout.EndHorizontal(); // descriptions from this very useful paper: https://hal.archives-ouvertes.fr/file/index/docid/307938/filename/frechot_realistic_simulation_of_ocean_surface_using_wave_spectra.pdf if (GUILayout.Button(new GUIContent("Phillips", "Base of modern parametric wave spectra"), _applyPhillipsSpectrum ? ToggleButtonStyleToggled : ToggleButtonStyleNormal)) { _applyPhillipsSpectrum = !_applyPhillipsSpectrum; } if (_applyPhillipsSpectrum) { _applyJONSWAPSpectrum = _applyPiersonMoskowitzSpectrum = false; Undo.RecordObject(this, "Apply Phillips Spectrum"); spec.ApplyPhillipsSpectrum(_windSpeed); } if (GUILayout.Button(new GUIContent("Pierson-Moskowitz", "Fully developed sea with infinite fetch"), _applyPiersonMoskowitzSpectrum ? ToggleButtonStyleToggled : ToggleButtonStyleNormal)) { _applyPiersonMoskowitzSpectrum = !_applyPiersonMoskowitzSpectrum; } if (_applyPiersonMoskowitzSpectrum) { _applyPhillipsSpectrum = _applyJONSWAPSpectrum = false; Undo.RecordObject(this, "Apply Pierson-Moskowitz Spectrum"); spec.ApplyPiersonMoskowitzSpectrum(_windSpeed); } _fetch = EditorGUILayout.Slider("Fetch", _fetch, 0f, 1000000f); if (GUILayout.Button(new GUIContent("JONSWAP", "Fetch limited sea where waves continue to grow"), _applyJONSWAPSpectrum ? ToggleButtonStyleToggled : ToggleButtonStyleNormal)) { _applyJONSWAPSpectrum = !_applyJONSWAPSpectrum; } if (_applyJONSWAPSpectrum) { _applyPhillipsSpectrum = _applyPiersonMoskowitzSpectrum = false; Undo.RecordObject(this, "Apply JONSWAP Spectrum"); spec.ApplyJONSWAPSpectrum(_windSpeed, _fetch); } serializedObject.ApplyModifiedProperties(); }
public override void OnInspectorGUI() { base.OnInspectorGUI(); var showAdvancedControls = serializedObject.FindProperty("_showAdvancedControls").boolValue; var spSpectrumModel = serializedObject.FindProperty("_model"); var spectrumModel = (OceanWaveSpectrum.SpectrumModel)serializedObject.FindProperty("_model").enumValueIndex; EditorGUILayout.Space(); var spDisabled = serializedObject.FindProperty("_powerDisabled"); UpgradeSpectrum(spDisabled, false); EditorGUILayout.BeginHorizontal(); bool allEnabled = true; for (int i = 0; i < spDisabled.arraySize; i++) { if (spDisabled.GetArrayElementAtIndex(i).boolValue) { allEnabled = false; } } bool toggle = allEnabled; if (toggle != EditorGUILayout.Toggle(toggle, GUILayout.Width(13f))) { for (int i = 0; i < spDisabled.arraySize; i++) { spDisabled.GetArrayElementAtIndex(i).boolValue = toggle; } } EditorGUILayout.LabelField("Spectrum", EditorStyles.boldLabel); EditorGUILayout.EndHorizontal(); var spec = target as OceanWaveSpectrum; var spPower = serializedObject.FindProperty("_powerLog"); UpgradeSpectrum(spPower, OceanWaveSpectrum.MIN_POWER_LOG); var spChopScales = serializedObject.FindProperty("_chopScales"); UpgradeSpectrum(spChopScales, 1f); var spGravScales = serializedObject.FindProperty("_gravityScales"); UpgradeSpectrum(spGravScales, 1f); // Disable sliders if authoring with model. var canEditSpectrum = spectrumModel != OceanWaveSpectrum.SpectrumModel.None; for (int i = 0; i < spPower.arraySize; i++) { EditorGUILayout.BeginHorizontal(); var spDisabled_i = spDisabled.GetArrayElementAtIndex(i); spDisabled_i.boolValue = !EditorGUILayout.Toggle(!spDisabled_i.boolValue, GUILayout.Width(15f)); float smallWL = OceanWaveSpectrum.SmallWavelength(i); var spPower_i = spPower.GetArrayElementAtIndex(i); var isPowerDisabled = spDisabled_i.boolValue; var powerValue = isPowerDisabled ? OceanWaveSpectrum.MIN_POWER_LOG : spPower_i.floatValue; if (showAdvancedControls) { EditorGUILayout.LabelField(string.Format("{0}", smallWL), EditorStyles.boldLabel); EditorGUILayout.EndHorizontal(); // Disable slider if authoring with model. GUI.enabled = !canEditSpectrum && !spDisabled_i.boolValue; powerValue = EditorGUILayout.Slider(" Power", powerValue, OceanWaveSpectrum.MIN_POWER_LOG, OceanWaveSpectrum.MAX_POWER_LOG); GUI.enabled = true; } else { EditorGUILayout.LabelField(string.Format("{0}", smallWL), GUILayout.Width(30f)); // Disable slider if authoring with model. GUI.enabled = !canEditSpectrum && !spDisabled_i.boolValue; powerValue = GUILayout.HorizontalSlider(powerValue, OceanWaveSpectrum.MIN_POWER_LOG, OceanWaveSpectrum.MAX_POWER_LOG); GUI.enabled = true; EditorGUILayout.EndHorizontal(); // This will create a tooltip for slider. GUI.Label(GUILayoutUtility.GetLastRect(), new GUIContent("", powerValue.ToString())); } // If the power is disabled, we are using the MIN_POWER_LOG value so we don't want to store it. if (!isPowerDisabled) { spPower_i.floatValue = powerValue; } if (showAdvancedControls) { EditorGUILayout.Slider(spChopScales.GetArrayElementAtIndex(i), 0f, 4f, " Chop Scale"); EditorGUILayout.Slider(spGravScales.GetArrayElementAtIndex(i), 0f, 4f, " Grav Scale"); } } EditorGUILayout.Space(); EditorGUILayout.LabelField("Empirical Spectra", EditorStyles.boldLabel); EditorGUILayout.BeginHorizontal(); spectrumModel = (OceanWaveSpectrum.SpectrumModel)EditorGUILayout.EnumPopup(spectrumModel); spSpectrumModel.enumValueIndex = (int)spectrumModel; EditorGUILayout.EndHorizontal(); EditorGUILayout.Space(); EditorGUILayout.HelpBox(modelDescriptions[(int)spectrumModel], MessageType.Info); EditorGUILayout.Space(); if (spectrumModel == OceanWaveSpectrum.SpectrumModel.None) { Undo.RecordObject(spec, "Change Spectrum"); } else { // It doesn't seem to matter where this is called. Undo.RecordObject(spec, $"Apply {ObjectNames.NicifyVariableName(spectrumModel.ToString())} Spectrum"); var labelWidth = 170f; EditorGUILayout.BeginHorizontal(); float spd_kmh = spec._windSpeed * 3.6f; EditorGUILayout.LabelField("Wind speed (km/h)", GUILayout.Width(labelWidth)); spd_kmh = EditorGUILayout.Slider(spd_kmh, 0f, 120f); spec._windSpeed = spd_kmh / 3.6f; EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); EditorGUILayout.LabelField(s_labelSWM, GUILayout.Width(labelWidth)); spec._smallWavelengthMultiplier = EditorGUILayout.Slider(spec._smallWavelengthMultiplier, 0f, 10f); EditorGUILayout.EndHorizontal(); if (spectrumModel == OceanWaveSpectrum.SpectrumModel.JONSWAP) { spec._fetch = EditorGUILayout.Slider(s_labelFetch, spec._fetch, 0f, 1000000f); } // Descriptions from this very useful paper: // https://hal.archives-ouvertes.fr/file/index/docid/307938/filename/frechot_realistic_simulation_of_ocean_surface_using_wave_spectra.pdf switch (spectrumModel) { case OceanWaveSpectrum.SpectrumModel.Phillips: spec.ApplyPhillipsSpectrum(spec._windSpeed, spec._smallWavelengthMultiplier); break; case OceanWaveSpectrum.SpectrumModel.PiersonMoskowitz: spec.ApplyPiersonMoskowitzSpectrum(spec._windSpeed, spec._smallWavelengthMultiplier); break; case OceanWaveSpectrum.SpectrumModel.JONSWAP: spec.ApplyJONSWAPSpectrum(spec._windSpeed, spec._fetch, spec._smallWavelengthMultiplier); break; } } serializedObject.ApplyModifiedProperties(); if (GUI.changed) { // We need to call this otherwise any property which has HideInInspector won't save. EditorUtility.SetDirty(spec); } }
public static void OnGUI(int resolution, float windTurbulence, float windDirRad, float windSpeed, OceanWaveSpectrum spectrum) { _generators.TryGetValue(CalculateWaveConditionsHash(resolution, windTurbulence, windDirRad, windSpeed, spectrum), out var generator); generator?.OnGUIInternal(); }
/// <summary> /// Changing wave gen data can result in creating lots of new generators. This gives a way to notify /// that a parameter has changed. If there is no existing generator for the new param values, but there /// is one for the old param values, this old generator is repurposed. /// </summary> public static void OnGenerationDataUpdated(int resolution, float windTurbulenceOld, float windDirRadOld, float windSpeedOld, OceanWaveSpectrum spectrumOld, float windTurbulenceNew, float windDirRadNew, float windSpeedNew, OceanWaveSpectrum spectrumNew) { // If multiple wave components share one FFT, then one of them changes its settings, it will // actually steal the generator from the rest. Then the first from the rest which request the // old settings will trigger creation of a new generator, and the remaining ones will use this // new generator. In the end one new generator is created, but it's created for the old settings. // Generators are requested single threaded so there should not be a race condition. Odd pattern // but I don't think any other way works without ugly checks to see if old generators are still // used, or other complicated things. // Check if no generator exists for new values var newHash = CalculateWaveConditionsHash(resolution, windTurbulenceNew, windDirRadNew, windSpeedNew, spectrumNew); if (!_generators.TryGetValue(newHash, out _)) { // Try to adapt an existing generator rather than default to creating a new one var oldHash = CalculateWaveConditionsHash(resolution, windTurbulenceOld, windDirRadOld, windSpeedOld, spectrumOld); FFTCompute generator; if (_generators.TryGetValue(oldHash, out generator)) { // Hash will change for this generator, so remove the current one _generators.Remove(oldHash); // Update params generator._windTurbulence = windTurbulenceNew; generator._windDirRad = windDirRadNew; generator._windSpeed = windSpeedNew; generator._spectrum = spectrumNew; // Trigger generator to re-init the spectrum generator._spectrumInitialised = false; // Re-add with new hash _generators.Add(newHash, generator); } } else { // There is already a new generator which will be used. Remove the previous one - if it really is needed // then it will be created later. var oldHash = CalculateWaveConditionsHash(resolution, windTurbulenceOld, windDirRadOld, windSpeedOld, spectrumOld); _generators.Remove(oldHash); } }
/// <summary> /// Computes water surface displacement, with wave components split across slices of the output texture array /// </summary> public static RenderTexture GenerateDisplacements(CommandBuffer buf, int resolution, float windTurbulence, float windDirRad, float windSpeed, float time, OceanWaveSpectrum spectrum, bool updateSpectrum) { // All static data arguments should be hashed here and passed to the generator constructor var conditionsHash = CalculateWaveConditionsHash(resolution, windTurbulence, windDirRad, windSpeed, spectrum); FFTCompute generator; if (!_generators.TryGetValue(conditionsHash, out generator)) { // No generator for these params - create one generator = new FFTCompute(resolution, windSpeed, windTurbulence, windDirRad, spectrum); _generators.Add(conditionsHash, generator); } // The remaining dynamic data arguments should be passed in to the generation here return(generator.GenerateDisplacementsInternal(buf, time, updateSpectrum)); }
static int CalculateWaveConditionsHash(int resolution, float windTurbulence, float windDirRad, float windSpeed, OceanWaveSpectrum spectrum) { var conditionsHash = Hashy.CreateHash(); Hashy.AddInt(resolution, ref conditionsHash); Hashy.AddFloat(windSpeed, ref conditionsHash); Hashy.AddFloat(windTurbulence, ref conditionsHash); Hashy.AddFloat(windDirRad, ref conditionsHash); if (spectrum != null) { Hashy.AddObject(spectrum, ref conditionsHash); } return(conditionsHash); }