升级6.4.升级水,升级天气
This commit is contained in:
@@ -9,6 +9,7 @@ using System.Collections.Generic;
|
||||
using Unity.Collections;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering;
|
||||
using WaveHarmonic.Crest.Internal;
|
||||
|
||||
namespace WaveHarmonic.Crest
|
||||
{
|
||||
@@ -22,8 +23,9 @@ namespace WaveHarmonic.Crest
|
||||
/// <param name="minimumLength">The minimum spatial length of the object, such as the width of a boat. Useful for filtering out detail when not needed. Set to zero to get full available detail.</param>
|
||||
/// <param name="points">The world space points that will be queried.</param>
|
||||
/// <param name="layer">The layer this query targets.</param>
|
||||
/// <param name="center">The center of all the query positions. Used to choose the closest query provider.</param>
|
||||
/// <returns>The status of the query.</returns>
|
||||
internal static int Query(int hash, float minimumLength, Vector3[] points, int layer) => 0;
|
||||
internal static int Query(int hash, float minimumLength, Vector3[] points, int layer, Vector3? center) => throw new System.NotImplementedException("Crest: this method is for documentation reuse only. Do not invoke.");
|
||||
|
||||
/// <summary>
|
||||
/// Check if the query results could be retrieved successfully using the return code
|
||||
@@ -45,6 +47,12 @@ namespace WaveHarmonic.Crest
|
||||
void UpdateQueries(WaterRenderer water);
|
||||
void SendReadBack(WaterRenderer water);
|
||||
void CleanUp();
|
||||
void Initialize(WaterRenderer water);
|
||||
}
|
||||
|
||||
interface IQueryableSimple : IQueryable
|
||||
{
|
||||
int Query(int hash, float minimumLength, Vector3[] queries, Vector3[] results, Vector3? center);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -64,6 +72,7 @@ namespace WaveHarmonic.Crest
|
||||
const int k_NormalAdditionalQueryCount = 2;
|
||||
|
||||
readonly WaterRenderer _Water;
|
||||
readonly IQueryableLod<IQueryProvider> _Lod;
|
||||
|
||||
readonly PropertyWrapperCompute _Wrapper;
|
||||
|
||||
@@ -85,8 +94,8 @@ namespace WaveHarmonic.Crest
|
||||
|
||||
internal const int k_DefaultMaximumQueryCount = 4096;
|
||||
|
||||
readonly int _MaximumQueryCount = k_DefaultMaximumQueryCount;
|
||||
readonly Vector3[] _QueryPositionXZ_MinimumGridSize = new Vector3[k_DefaultMaximumQueryCount];
|
||||
readonly int _MaximumQueryCount;
|
||||
readonly Vector3[] _QueryPositionXZ_MinimumGridSize;
|
||||
|
||||
/// <summary>
|
||||
/// Holds information about all query points. Maps from unique hash code to position in point array.
|
||||
@@ -147,8 +156,9 @@ namespace WaveHarmonic.Crest
|
||||
// queries are often made from FixedUpdate(), and at high framerates this may not be called, which would mean
|
||||
// the query would get lost and this leads to stuttering and other artifacts.
|
||||
{
|
||||
_Segments[_SegmentAcquire]._QueryCount = 0;
|
||||
_Segments[_SegmentAcquire]._Segments.Clear();
|
||||
var registrar = _Segments[_SegmentAcquire];
|
||||
registrar._QueryCount = 0;
|
||||
registrar._Segments.Clear();
|
||||
|
||||
foreach (var segment in _Segments[lastIndex]._Segments)
|
||||
{
|
||||
@@ -160,11 +170,10 @@ namespace WaveHarmonic.Crest
|
||||
// Compute a new segment range - we may have removed some segments that were too old, so this ensures
|
||||
// we have a nice compact array of queries each frame rather than accumulating persistent air bubbles
|
||||
var newSegment = segment.Value;
|
||||
newSegment.x = _Segments[_SegmentAcquire]._QueryCount;
|
||||
newSegment.x = registrar._QueryCount;
|
||||
newSegment.y = newSegment.x + (segment.Value.y - segment.Value.x);
|
||||
_Segments[_SegmentAcquire]._QueryCount = newSegment.y + 1;
|
||||
|
||||
_Segments[_SegmentAcquire]._Segments.Add(segment.Key, newSegment);
|
||||
registrar._QueryCount = newSegment.y + 1;
|
||||
registrar._Segments.Add(segment.Key, newSegment);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -253,17 +262,15 @@ namespace WaveHarmonic.Crest
|
||||
InvalidDtForVelocity = 16,
|
||||
}
|
||||
|
||||
public QueryBase(WaterRenderer water)
|
||||
public QueryBase(IQueryableLod<IQueryProvider> lod)
|
||||
{
|
||||
_Water = water;
|
||||
_Water = lod.Water;
|
||||
_Lod = lod;
|
||||
|
||||
_DataArrivedAction = new(DataArrived);
|
||||
|
||||
if (_MaximumQueryCount != water._AnimatedWavesLod.MaximumQueryCount)
|
||||
{
|
||||
_MaximumQueryCount = water._AnimatedWavesLod.MaximumQueryCount;
|
||||
_QueryPositionXZ_MinimumGridSize = new Vector3[_MaximumQueryCount];
|
||||
}
|
||||
_MaximumQueryCount = lod.MaximumQueryCount;
|
||||
_QueryPositionXZ_MinimumGridSize = new Vector3[_MaximumQueryCount];
|
||||
|
||||
_ComputeBufferQueries = new(_MaximumQueryCount, 12, ComputeBufferType.Default);
|
||||
_ComputeBufferResults = new(_MaximumQueryCount, 12, ComputeBufferType.Default);
|
||||
@@ -277,7 +284,13 @@ namespace WaveHarmonic.Crest
|
||||
Debug.LogError($"Crest: Could not load Query compute shader");
|
||||
return;
|
||||
}
|
||||
_Wrapper = new(water.SimulationBuffer, shader, Kernel);
|
||||
|
||||
_Wrapper = new(_Water.SimulationBuffer, shader, Kernel);
|
||||
}
|
||||
|
||||
void LogMaximumQueryCountExceededError()
|
||||
{
|
||||
Debug.LogError($"Crest: Maximum query count ({_MaximumQueryCount}) exceeded, increase the <i>{nameof(WaterRenderer)} > Simulations > {_Lod.Name} > {nameof(_Lod.MaximumQueryCount)}</i> to support a higher number of queries.", _Water);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -286,9 +299,11 @@ namespace WaveHarmonic.Crest
|
||||
/// </summary>
|
||||
protected bool UpdateQueryPoints(int ownerHash, float minSpatialLength, Vector3[] queryPoints, Vector3[] queryNormals)
|
||||
{
|
||||
if (queryPoints.Length + _SegmentRegistrarRingBuffer.Current._QueryCount > _MaximumQueryCount)
|
||||
var registrar = _SegmentRegistrarRingBuffer.Current;
|
||||
|
||||
if (queryPoints.Length + registrar._QueryCount > _MaximumQueryCount)
|
||||
{
|
||||
Debug.LogError($"Crest: Max query count ({_MaximumQueryCount}) exceeded, increase the max query count in the Animated Waves Settings to support a higher number of queries.");
|
||||
LogMaximumQueryCountExceededError();
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -299,20 +314,20 @@ namespace WaveHarmonic.Crest
|
||||
var countNorms = queryNormals != null ? queryNormals.Length : 0;
|
||||
var countTotal = countPts + countNorms * k_NormalAdditionalQueryCount;
|
||||
|
||||
if (_SegmentRegistrarRingBuffer.Current._Segments.TryGetValue(ownerHash, out var segment))
|
||||
if (registrar._Segments.TryGetValue(ownerHash, out var segment))
|
||||
{
|
||||
var segmentSize = segment.y - segment.x + 1;
|
||||
if (segmentSize == countTotal)
|
||||
{
|
||||
// Update frame count
|
||||
segment.z = Time.frameCount;
|
||||
_SegmentRegistrarRingBuffer.Current._Segments[ownerHash] = segment;
|
||||
registrar._Segments[ownerHash] = segment;
|
||||
|
||||
segmentRetrieved = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
_SegmentRegistrarRingBuffer.Current._Segments.Remove(ownerHash);
|
||||
registrar._Segments.Remove(ownerHash);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -324,18 +339,18 @@ namespace WaveHarmonic.Crest
|
||||
|
||||
if (!segmentRetrieved)
|
||||
{
|
||||
if (_SegmentRegistrarRingBuffer.Current._Segments.Count >= k_MaximumGuids)
|
||||
if (registrar._Segments.Count >= k_MaximumGuids)
|
||||
{
|
||||
Debug.LogError("Crest: Too many guids registered with CollProviderCompute. Increase s_maxGuids.");
|
||||
return false;
|
||||
}
|
||||
|
||||
segment.x = _SegmentRegistrarRingBuffer.Current._QueryCount;
|
||||
segment.x = registrar._QueryCount;
|
||||
segment.y = segment.x + countTotal - 1;
|
||||
segment.z = Time.frameCount;
|
||||
_SegmentRegistrarRingBuffer.Current._Segments.Add(ownerHash, segment);
|
||||
registrar._Segments.Add(ownerHash, segment);
|
||||
|
||||
_SegmentRegistrarRingBuffer.Current._QueryCount += countTotal;
|
||||
registrar._QueryCount += countTotal;
|
||||
|
||||
//Debug.Log("Crest: Added points for " + guid);
|
||||
}
|
||||
@@ -346,9 +361,14 @@ namespace WaveHarmonic.Crest
|
||||
var samplesPerWave = 2f;
|
||||
var minGridSize = minWavelength / samplesPerWave;
|
||||
|
||||
// Displacements should not utilize the last slice which is used for transitioning
|
||||
// waves between sampling resolutions. While it might be ok to use the last slice
|
||||
// for other targets, we avoid using it to be consistent with displacements.
|
||||
var minimumSlice = Mathf.Clamp(Mathf.FloorToInt(Mathf.Log(Mathf.Max(minGridSize / _Lod.Texel, 1f), 2f)), 0, _Water.LodLevels - 2);
|
||||
|
||||
if (countPts + segment.x > _QueryPositionXZ_MinimumGridSize.Length)
|
||||
{
|
||||
Debug.LogError("Crest: Too many wave height queries. Increase Max Query Count in the Animated Waves Settings.");
|
||||
LogMaximumQueryCountExceededError();
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -356,7 +376,7 @@ namespace WaveHarmonic.Crest
|
||||
{
|
||||
_QueryPositionXZ_MinimumGridSize[pointi + segment.x].x = queryPoints[pointi].x;
|
||||
_QueryPositionXZ_MinimumGridSize[pointi + segment.x].y = queryPoints[pointi].z;
|
||||
_QueryPositionXZ_MinimumGridSize[pointi + segment.x].z = minGridSize;
|
||||
_QueryPositionXZ_MinimumGridSize[pointi + segment.x].z = minimumSlice;
|
||||
}
|
||||
|
||||
// To compute each normal, post 2 query points (reuse point above)
|
||||
@@ -366,13 +386,13 @@ namespace WaveHarmonic.Crest
|
||||
|
||||
_QueryPositionXZ_MinimumGridSize[arrIdx].x = queryNormals[normi].x + k_FiniteDifferenceDx;
|
||||
_QueryPositionXZ_MinimumGridSize[arrIdx].y = queryNormals[normi].z;
|
||||
_QueryPositionXZ_MinimumGridSize[arrIdx].z = minGridSize;
|
||||
_QueryPositionXZ_MinimumGridSize[arrIdx].z = minimumSlice;
|
||||
|
||||
arrIdx += 1;
|
||||
|
||||
_QueryPositionXZ_MinimumGridSize[arrIdx].x = queryNormals[normi].x;
|
||||
_QueryPositionXZ_MinimumGridSize[arrIdx].y = queryNormals[normi].z + k_FiniteDifferenceDx;
|
||||
_QueryPositionXZ_MinimumGridSize[arrIdx].z = minGridSize;
|
||||
_QueryPositionXZ_MinimumGridSize[arrIdx].z = minimumSlice;
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -590,10 +610,11 @@ namespace WaveHarmonic.Crest
|
||||
_QueryResultsTimeLast = _QueryResultsTime;
|
||||
_ResultSegmentsLast = _ResultSegments;
|
||||
|
||||
var data = _Requests[lastDoneIndex]._Request.GetData<Vector3>();
|
||||
var last = _Requests[lastDoneIndex];
|
||||
var data = last._Request.GetData<Vector3>();
|
||||
data.CopyTo(_QueryResults);
|
||||
_QueryResultsTime = _Requests[lastDoneIndex]._DataTimestamp;
|
||||
_ResultSegments = _Requests[lastDoneIndex]._Segments;
|
||||
_QueryResultsTime = last._DataTimestamp;
|
||||
_ResultSegments = last._Segments;
|
||||
}
|
||||
|
||||
// Remove all the requests up to the last completed one
|
||||
@@ -618,7 +639,23 @@ namespace WaveHarmonic.Crest
|
||||
_SegmentRegistrarRingBuffer.ClearAll();
|
||||
}
|
||||
|
||||
public virtual int Query(int ownerHash, float minSpatialLength, Vector3[] queryPoints, Vector3[] results)
|
||||
public virtual void Initialize(WaterRenderer water)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public int ResultGuidCount => _ResultSegments != null ? _ResultSegments.Count : 0;
|
||||
|
||||
public int RequestCount => _Requests != null ? _Requests.Count : 0;
|
||||
|
||||
public int QueryCount => _SegmentRegistrarRingBuffer != null ? _SegmentRegistrarRingBuffer.Current._QueryCount : 0;
|
||||
}
|
||||
|
||||
abstract class QueryBaseSimple : QueryBase, IQueryableSimple
|
||||
{
|
||||
protected QueryBaseSimple(IQueryableLod<IQueryProvider> lod) : base(lod) { }
|
||||
|
||||
public virtual int Query(int ownerHash, float minSpatialLength, Vector3[] queryPoints, Vector3[] results, Vector3? center)
|
||||
{
|
||||
var result = (int)QueryStatus.OK;
|
||||
|
||||
@@ -634,12 +671,159 @@ namespace WaveHarmonic.Crest
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
public int ResultGuidCount => _ResultSegments != null ? _ResultSegments.Count : 0;
|
||||
abstract class QueryPerCamera<T> : IQueryable where T : IQueryable, new()
|
||||
{
|
||||
internal readonly WaterRenderer _Water;
|
||||
internal readonly Dictionary<Camera, T> _Providers = new();
|
||||
|
||||
public int RequestCount => _Requests != null ? _Requests.Count : 0;
|
||||
public QueryPerCamera(WaterRenderer water)
|
||||
{
|
||||
_Water = water;
|
||||
Initialize(water);
|
||||
}
|
||||
|
||||
public int QueryCount => _SegmentRegistrarRingBuffer != null ? _SegmentRegistrarRingBuffer.Current._QueryCount : 0;
|
||||
public int ResultGuidCount
|
||||
{
|
||||
get
|
||||
{
|
||||
var total = 0;
|
||||
foreach (var (camera, provider) in _Providers)
|
||||
{
|
||||
if (_Water.ShouldExecuteQueries(camera)) total += provider.ResultGuidCount;
|
||||
}
|
||||
return total;
|
||||
}
|
||||
}
|
||||
|
||||
public int RequestCount
|
||||
{
|
||||
get
|
||||
{
|
||||
var total = 0;
|
||||
foreach (var (camera, provider) in _Providers)
|
||||
{
|
||||
if (_Water.ShouldExecuteQueries(camera)) total += provider.RequestCount;
|
||||
}
|
||||
return total;
|
||||
}
|
||||
}
|
||||
|
||||
public int QueryCount
|
||||
{
|
||||
get
|
||||
{
|
||||
var total = 0;
|
||||
foreach (var (camera, provider) in _Providers)
|
||||
{
|
||||
if (_Water.ShouldExecuteQueries(camera)) total += provider.QueryCount;
|
||||
}
|
||||
return total;
|
||||
}
|
||||
}
|
||||
|
||||
public void CleanUp()
|
||||
{
|
||||
foreach (var provider in _Providers.Values)
|
||||
{
|
||||
provider?.CleanUp();
|
||||
}
|
||||
}
|
||||
|
||||
public void Initialize(WaterRenderer water)
|
||||
{
|
||||
var camera = water.CurrentCamera;
|
||||
|
||||
if (camera == null)
|
||||
{
|
||||
camera = water.Viewer;
|
||||
}
|
||||
|
||||
if (camera == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_Providers.ContainsKey(camera))
|
||||
{
|
||||
// Cannot use parameters. We could use System.Activator.CreateInstance to get
|
||||
// around that, but instead we just use WaterRenderer.Instance.
|
||||
_Providers.Add(camera, new());
|
||||
}
|
||||
}
|
||||
|
||||
public void SendReadBack(WaterRenderer water)
|
||||
{
|
||||
_Providers[water.CurrentCamera].SendReadBack(water);
|
||||
}
|
||||
|
||||
public void UpdateQueries(WaterRenderer water)
|
||||
{
|
||||
_Providers[water.CurrentCamera].UpdateQueries(water);
|
||||
}
|
||||
|
||||
public Vector2 FindCenter(Vector3[] queries, Vector3? center)
|
||||
{
|
||||
if (center != null)
|
||||
{
|
||||
return ((Vector3)center).XZ();
|
||||
}
|
||||
|
||||
// Calculate center if none provided.
|
||||
var sum = Vector2.zero;
|
||||
foreach (var point in queries)
|
||||
{
|
||||
sum += point.XZ();
|
||||
}
|
||||
|
||||
return new(sum.x / queries.Length, sum.y / queries.Length);
|
||||
}
|
||||
}
|
||||
|
||||
abstract class QueryPerCameraSimple<T> : QueryPerCamera<T>, IQueryableSimple where T : IQueryableSimple, new()
|
||||
{
|
||||
protected QueryPerCameraSimple(WaterRenderer water) : base(water) { }
|
||||
|
||||
public int Query(int id, float length, Vector3[] queries, Vector3[] results, Vector3? center = null)
|
||||
{
|
||||
if (_Water.IsSeparateViewpointCameraLoop)
|
||||
{
|
||||
return _Providers[_Water.CurrentCamera].Query(id, length, queries, results, center);
|
||||
}
|
||||
|
||||
var lastStatus = -1;
|
||||
var lastDistance = Mathf.Infinity;
|
||||
|
||||
var newCenter = FindCenter(queries, center);
|
||||
|
||||
foreach (var provider in _Providers)
|
||||
{
|
||||
var camera = provider.Key;
|
||||
|
||||
if (!_Water.ShouldExecuteQueries(camera))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var distance = (newCenter - camera.transform.position.XZ()).sqrMagnitude;
|
||||
|
||||
if (lastStatus == (int)QueryBase.QueryStatus.OK && lastDistance < distance)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var status = provider.Value.Query(id, length, queries, results, center);
|
||||
|
||||
if (lastStatus < 0 || status == (int)QueryBase.QueryStatus.OK)
|
||||
{
|
||||
lastStatus = status;
|
||||
lastDistance = distance;
|
||||
}
|
||||
}
|
||||
|
||||
return lastStatus;
|
||||
}
|
||||
}
|
||||
|
||||
static partial class Extensions
|
||||
|
||||
Reference in New Issue
Block a user