Example #1
0
 void Reset()
 {
     // Initialise with spectrum.
     _spectrum      = ScriptableObject.CreateInstance <OceanWaveSpectrum>();
     _spectrum.name = "Default Waves (auto)";
     _spectrum.Upgrade();
 }
Example #2
0
        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();
        }
Example #3
0
 void Start()
 {
     if (_spectrum == null)
     {
         _spectrum      = ScriptableObject.CreateInstance <OceanWaveSpectrum>();
         _spectrum.name = "Default Waves (auto)";
     }
 }
Example #4
0
        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;
        }
Example #5
0
        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)";
            }
        }
Example #6
0
        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)";
            }
        }
Example #10
0
        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();
        }
Example #12
0
        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);
            }
        }
Example #13
0
 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();
 }
Example #14
0
        /// <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);
            }
        }
Example #15
0
        /// <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));
        }
Example #16
0
        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);
        }