Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Test] Experiment with using Native Containers in query API #411

Open
wants to merge 3 commits into
base: refactor/remove-gpu-readback
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// This file is subject to the MIT License as seen in the root of this folder structure (LICENSE)

using Crest;
using Unity.Collections;
using UnityEngine;

/// <summary>
Expand All @@ -14,37 +15,42 @@ public class OceanSampleDisplacementDemo : MonoBehaviour
public float _minGridSize = 0f;

GameObject[] _markerObjects = new GameObject[3];
Vector3[] _markerPos = new Vector3[3];
Vector3[] _resultDisps = new Vector3[3];
Vector3[] _resultNorms = new Vector3[3];
Vector3[] _resultVels = new Vector3[3];



float _samplesRadius = 5f;

void Update()
{

if (OceanRenderer.Instance == null)
{
return;
}

NativeArray<Vector3> markerPos = new NativeArray<Vector3>(3, Allocator.Temp);
NativeArray<Vector3> resultDisps = new NativeArray<Vector3>(3, Allocator.Temp);
NativeArray<Vector3> resultNorms = new NativeArray<Vector3>(3, Allocator.Temp);
NativeArray<Vector3> resultVels = new NativeArray<Vector3>(3, Allocator.Temp);

if (_trackCamera)
{
var height = Mathf.Abs(Camera.main.transform.position.y - OceanRenderer.Instance.SeaLevel);
var lookAngle = Mathf.Max(Mathf.Abs(Camera.main.transform.forward.y), 0.001f);
var offset = height / lookAngle;
_markerPos[0] = Camera.main.transform.position + Camera.main.transform.forward * offset;
_markerPos[1] = Camera.main.transform.position + Camera.main.transform.forward * offset + _samplesRadius * Vector3.right;
_markerPos[2] = Camera.main.transform.position + Camera.main.transform.forward * offset + _samplesRadius * Vector3.forward;
markerPos[0] = Camera.main.transform.position + Camera.main.transform.forward * offset;
markerPos[1] = Camera.main.transform.position + Camera.main.transform.forward * offset + _samplesRadius * Vector3.right;
markerPos[2] = Camera.main.transform.position + Camera.main.transform.forward * offset + _samplesRadius * Vector3.forward;
}

if (OceanRenderer.Instance == null)
{
return;
}

var collProvider = OceanRenderer.Instance.CollisionProvider;

var status = collProvider.Query(GetHashCode(), _minGridSize, _markerPos, _resultDisps, _resultNorms, _resultVels);
var status = collProvider.Query(GetHashCode(), _minGridSize, markerPos, resultDisps, resultNorms, resultVels);

if (collProvider.RetrieveSucceeded(status))
{
for (int i = 0; i < _resultDisps.Length; i++)
for (int i = 0; i < resultDisps.Length; i++)
{
if (_markerObjects[i] == null)
{
Expand All @@ -53,28 +59,34 @@ void Update()
_markerObjects[i].transform.localScale = Vector3.one * 0.5f;
}

var query = _markerPos[i];
var query = markerPos[i];
query.y = OceanRenderer.Instance.SeaLevel;

var disp = _resultDisps[i];
var disp = resultDisps[i];

var pos = query;
pos.y = disp.y;
Debug.DrawLine(pos, pos - disp);
_markerObjects[i].transform.position = pos;

_markerObjects[i].transform.rotation = Quaternion.FromToRotation(Vector3.up, _resultNorms[i]);
_markerObjects[i].transform.rotation = Quaternion.FromToRotation(Vector3.up, resultNorms[i]);
}

for (var i = 0; i < _resultNorms.Length; i++)
for (var i = 0; i < resultNorms.Length; i++)
{
Debug.DrawLine(_markerObjects[i].transform.position, _markerObjects[i].transform.position + _resultNorms[i], Color.blue);
Debug.DrawLine(_markerObjects[i].transform.position, _markerObjects[i].transform.position + resultNorms[i], Color.blue);
}

for (var i = 0; i < _resultVels.Length; i++)
for (var i = 0; i < resultVels.Length; i++)
{
Debug.DrawLine(_markerObjects[i].transform.position, _markerObjects[i].transform.position + _resultVels[i], Color.green);
Debug.DrawLine(_markerObjects[i].transform.position, _markerObjects[i].transform.position + resultVels[i], Color.green);
}
}


resultVels.Dispose();
resultNorms.Dispose();
resultDisps.Dispose();
markerPos.Dispose();
}
}
5 changes: 3 additions & 2 deletions crest/Assets/Crest/Crest/Scripts/Collision/CollProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

// This file is subject to the MIT License as seen in the root of this folder structure (LICENSE)

using Unity.Collections;
using UnityEngine;

namespace Crest
Expand All @@ -20,7 +21,7 @@ public interface ICollProvider
/// <param name="o_resultHeights">Float array of water heights at the query positions. Pass null if this information is not required.</param>
/// <param name="o_resultNorms">Water normals at the query positions. Pass null if this information is not required.</param>
/// <param name="o_resultVels">Water surface velocities at the query positions. Pass null if this information is not required.</param>
int Query(int i_ownerHash, float i_minSpatialLength, Vector3[] i_queryPoints, float[] o_resultHeights, Vector3[] o_resultNorms, Vector3[] o_resultVels);
int Query(int i_ownerHash, float i_minSpatialLength, NativeSlice<Vector3> i_queryPoints, NativeSlice<float> o_resultHeights, NativeSlice<Vector3> o_resultNorms, NativeSlice<Vector3> o_resultVels);

/// <summary>
/// Query water physical data at a set of points. Pass in null to any out parameters that are not required.
Expand All @@ -31,7 +32,7 @@ public interface ICollProvider
/// <param name="o_resultDisps">Displacement vectors for water surface points that will displace to the XZ coordinates of the query points. Water heights are given by sea level plus the y component of the displacement.</param>
/// <param name="o_resultNorms">Water normals at the query positions. Pass null if this information is not required.</param>
/// <param name="o_resultVels">Water surface velocities at the query positions. Pass null if this information is not required.</param>
int Query(int i_ownerHash, float i_minSpatialLength, Vector3[] i_queryPoints, Vector3[] o_resultDisps, Vector3[] o_resultNorms, Vector3[] o_resultVels);
int Query(int i_ownerHash, float i_minSpatialLength, NativeSlice<Vector3> i_queryPoints, NativeSlice<Vector3> o_resultDisps, NativeSlice<Vector3> o_resultNorms, NativeSlice<Vector3> o_resultVels);

/// <summary>
/// Check if query results could be retrieved successfully using return code from Query() function
Expand Down
17 changes: 9 additions & 8 deletions crest/Assets/Crest/Crest/Scripts/Collision/CollProviderNull.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

// This file is subject to the MIT License as seen in the root of this folder structure (LICENSE)

using Unity.Collections;
using UnityEngine;

namespace Crest
Expand All @@ -11,25 +12,25 @@ namespace Crest
/// </summary>
public class CollProviderNull : ICollProvider
{
public int Query(int i_ownerHash, float i_minSpatialLength, Vector3[] i_queryPoints, Vector3[] o_resultDisps, Vector3[] o_resultNorms, Vector3[] o_resultVels)
public int Query(int i_ownerHash, float i_minSpatialLength, NativeSlice<Vector3> i_queryPoints, NativeSlice<Vector3> o_resultDisps, NativeSlice<Vector3> o_resultNorms, NativeSlice<Vector3> o_resultVels)
{
if (o_resultDisps != null)
if (o_resultDisps.Length != 0)
{
for (int i = 0; i < o_resultDisps.Length; i++)
{
o_resultDisps[i] = Vector3.zero;
}
}

if (o_resultNorms != null)
if (o_resultNorms.Length != 0)
{
for (int i = 0; i < o_resultNorms.Length; i++)
{
o_resultNorms[i] = Vector3.up;
}
}

if (o_resultVels != null)
if (o_resultVels.Length != 0)
{
for (int i = 0; i < o_resultVels.Length; i++)
{
Expand All @@ -40,25 +41,25 @@ public int Query(int i_ownerHash, float i_minSpatialLength, Vector3[] i_queryPoi
return 0;
}

public int Query(int i_ownerHash, float i_minSpatialLength, Vector3[] i_queryPoints, float[] o_resultHeights, Vector3[] o_resultNorms, Vector3[] o_resultVels)
public int Query(int i_ownerHash, float i_minSpatialLength, NativeSlice<Vector3> i_queryPoints, NativeSlice<float> o_resultHeights, NativeSlice<Vector3> o_resultNorms, NativeSlice<Vector3> o_resultVels)
{
if (o_resultHeights != null)
if (o_resultHeights.Length != 0)
{
for (int i = 0; i < o_resultHeights.Length; i++)
{
o_resultHeights[i] = 0f;
}
}

if (o_resultNorms != null)
if (o_resultNorms.Length != 0)
{
for (int i = 0; i < o_resultNorms.Length; i++)
{
o_resultNorms[i] = Vector3.up;
}
}

if (o_resultVels != null)
if (o_resultVels.Length != 0)
{
for (int i = 0; i < o_resultVels.Length; i++)
{
Expand Down
76 changes: 45 additions & 31 deletions crest/Assets/Crest/Crest/Scripts/Collision/QueryBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ struct ReadbackRequest

List<ReadbackRequest> _requests = new List<ReadbackRequest>();

public enum QueryStatus
public enum QueryStatus : int
{
OK = 0,
RetrieveFailed = 1,
Expand All @@ -188,14 +188,14 @@ public enum QueryStatus
/// Takes a unique request ID and some world space XZ positions, and computes the displacement vector that lands at this position,
/// to a good approximation. The world space height of the water at that position is then SeaLevel + displacement.y.
/// </summary>
protected bool UpdateQueryPoints(int i_ownerHash, float i_minSpatialLength, Vector3[] queryPoints, Vector3[] queryNormals)
protected bool UpdateQueryPoints(int i_ownerHash, float i_minSpatialLength, NativeSlice<Vector3> queryPoints, NativeSlice<Vector3> queryNormals)
{
var segmentRetrieved = false;
Vector2Int segment;

// We'll send in 3 points to get normals
var countPts = (queryPoints != null ? queryPoints.Length : 0);
var countNorms = (queryNormals != null ? queryNormals.Length : 0);
var countPts = (queryPoints.Length != 0 ? queryPoints.Length : 0);
var countNorms = (queryNormals.Length != 0 ? queryNormals.Length : 0);
var countTotal = countPts + countNorms * 3;

if (_segmentRegistrarRingBuffer.Current._segments.TryGetValue(i_ownerHash, out segment))
Expand Down Expand Up @@ -241,27 +241,40 @@ protected bool UpdateQueryPoints(int i_ownerHash, float i_minSpatialLength, Vect

for (int pointi = 0; pointi < countPts; pointi++)
{
_queryPosXZ_minGridSize[pointi + segment.x].x = queryPoints[pointi].x;
_queryPosXZ_minGridSize[pointi + segment.x].y = queryPoints[pointi].z;
_queryPosXZ_minGridSize[pointi + segment.x].z = minGridSize;
Vector3 queryPosXZ_minGridSizVal = _queryPosXZ_minGridSize[pointi + segment.x];
queryPosXZ_minGridSizVal.x = queryPoints[pointi].x;
queryPosXZ_minGridSizVal.y = queryPoints[pointi].z;
queryPosXZ_minGridSizVal.z = minGridSize;
_queryPosXZ_minGridSize[pointi + segment.x] = queryPosXZ_minGridSizVal;
}

// To compute each normal, post 3 query points
for (int normi = 0; normi < countNorms; normi++)
{
var arrIdx = segment.x + countPts + 3 * normi;

_queryPosXZ_minGridSize[arrIdx + 0].x = queryNormals[normi].x;
_queryPosXZ_minGridSize[arrIdx + 0].y = queryNormals[normi].z;
_queryPosXZ_minGridSize[arrIdx + 0].z = minGridSize;

_queryPosXZ_minGridSize[arrIdx + 1].x = queryNormals[normi].x + s_finiteDiffDx;
_queryPosXZ_minGridSize[arrIdx + 1].y = queryNormals[normi].z;
_queryPosXZ_minGridSize[arrIdx + 1].z = minGridSize;
{
Vector3 queryPosXZ_minGridSizVal = _queryPosXZ_minGridSize[arrIdx + 0];
queryPosXZ_minGridSizVal.x = queryNormals[normi].x;
queryPosXZ_minGridSizVal.y = queryNormals[normi].z;
queryPosXZ_minGridSizVal.z = minGridSize;
_queryPosXZ_minGridSize[arrIdx + 0] = queryPosXZ_minGridSizVal;
}

_queryPosXZ_minGridSize[arrIdx + 2].x = queryNormals[normi].x;
_queryPosXZ_minGridSize[arrIdx + 2].y = queryNormals[normi].z + s_finiteDiffDx;
_queryPosXZ_minGridSize[arrIdx + 2].z = minGridSize;
{
Vector3 queryPosXZ_minGridSizVal = _queryPosXZ_minGridSize[arrIdx + 1];
queryPosXZ_minGridSizVal.x = queryNormals[normi].x + s_finiteDiffDx;
queryPosXZ_minGridSizVal.y = queryNormals[normi].z;
queryPosXZ_minGridSizVal.z = minGridSize;
_queryPosXZ_minGridSize[arrIdx + 1] = queryPosXZ_minGridSizVal;
}
{
Vector3 queryPosXZ_minGridSizVal = _queryPosXZ_minGridSize[arrIdx + 2];
queryPosXZ_minGridSizVal.x = queryNormals[normi].x;
queryPosXZ_minGridSizVal.y = queryNormals[normi].z + s_finiteDiffDx;
queryPosXZ_minGridSizVal.z = minGridSize;
_queryPosXZ_minGridSize[arrIdx + 2] = queryPosXZ_minGridSizVal;
}
}

return true;
Expand All @@ -287,7 +300,7 @@ public void CompactQueryStorage()
/// <summary>
/// Copy out displacements, heights, normals. Pass null if info is not required.
/// </summary>
protected bool RetrieveResults(int guid, Vector3[] displacements, float[] heights, Vector3[] normals)
protected bool RetrieveResults(int guid, NativeSlice<Vector3> displacements, NativeSlice<float> heights, NativeSlice<Vector3> normals)
{
if (_resultSegments == null)
{
Expand All @@ -303,19 +316,19 @@ protected bool RetrieveResults(int guid, Vector3[] displacements, float[] height
}

var countPoints = 0;
if (displacements != null) countPoints = displacements.Length;
if (heights != null) countPoints = heights.Length;
if (displacements != null && heights != null) Debug.Assert(displacements.Length == heights.Length);
var countNorms = (normals != null ? normals.Length : 0);
if (displacements.Length != 0) countPoints = displacements.Length;
if (heights.Length != 0) countPoints = heights.Length;
if (displacements.Length != 0 && heights.Length != 0) Debug.Assert(displacements.Length == heights.Length);
var countNorms = (normals.Length != 0 ? normals.Length : 0);
var countTotal = countPoints + countNorms * 3;

if (countPoints > 0)
{
// Retrieve Results
if (displacements != null) _queryResults.Slice(segment.x, countPoints).CopyTo(displacements);
if (displacements.Length != 0) displacements.CopyFrom(_queryResults.Slice(segment.x, countPoints));

// Retrieve Result heights
if (heights != null)
if (heights.Length != 0)
{
var seaLevel = OceanRenderer.Instance.SeaLevel;
for (int i = 0; i < countPoints; i++)
Expand All @@ -337,8 +350,9 @@ protected bool RetrieveResults(int guid, Vector3[] displacements, float[] height
var px = dx + _queryResults[firstNorm + 3 * i + 1];
var pz = dz + _queryResults[firstNorm + 3 * i + 2];

normals[i] = Vector3.Cross(p - px, p - pz).normalized;
normals[i].y *= -1f;
Vector3 normal = Vector3.Cross(p - px, p - pz).normalized;
normal.y *= -1f;
normals[i] = normal;
}
}

Expand All @@ -349,7 +363,7 @@ protected bool RetrieveResults(int guid, Vector3[] displacements, float[] height
/// Compute time derivative of the displacements by calculating difference from last query. More complicated than it would seem - results
/// may not be available in one or both of the results, or the query locations in the array may change.
/// </summary>
protected int CalculateVelocities(int i_ownerHash, float i_minSpatialLength, Vector3[] i_queryPositions, Vector3[] results)
protected int CalculateVelocities(int i_ownerHash, float i_minSpatialLength, NativeSlice<Vector3> i_queryPositions, NativeSlice<Vector3> results)
{
// Need at least 2 returned results to do finite difference
if (_queryResultsTime < 0f || _queryResultsTimeLast < 0f)
Expand Down Expand Up @@ -504,21 +518,21 @@ protected virtual void OnDisable()
_segmentRegistrarRingBuffer.ClearAll();
}

public int Query(int i_ownerHash, float i_minSpatialLength, Vector3[] i_queryPoints, Vector3[] o_resultDisps, Vector3[] o_resultNorms, Vector3[] o_resultVels)
public int Query(int i_ownerHash, float i_minSpatialLength, NativeSlice<Vector3> i_queryPoints, NativeSlice<Vector3> o_resultDisps, NativeSlice<Vector3> o_resultNorms, NativeSlice<Vector3> o_resultVels)
{
var result = (int)QueryStatus.OK;

if (!UpdateQueryPoints(i_ownerHash, i_minSpatialLength, i_queryPoints, o_resultNorms != null ? i_queryPoints : null))
if (!UpdateQueryPoints(i_ownerHash, i_minSpatialLength, i_queryPoints, o_resultNorms.Length != 0 ? i_queryPoints : default))
{
result |= (int)QueryStatus.PostFailed;
}

if (!RetrieveResults(i_ownerHash, o_resultDisps, null, o_resultNorms))
if (!RetrieveResults(i_ownerHash, o_resultDisps, default, o_resultNorms))
{
result |= (int)QueryStatus.RetrieveFailed;
}

if (o_resultVels != null)
if (o_resultVels.Length != 0)
{
result |= CalculateVelocities(i_ownerHash, i_minSpatialLength, i_queryPoints, o_resultVels);
}
Expand Down
Loading