void FixedUpdateBuoyancy(ICollProvider collProvider) { float archimedesForceMagnitude = WATER_DENSITY * Mathf.Abs(Physics.gravity.y); for (int i = 0; i < _forcePoints.Length; i++) { FloaterForcePoints point = _forcePoints[i]; var transformedPoint = transform.TransformPoint(point._offsetPosition + new Vector3(0, _centerOfMass.y, 0)); Vector3 undispPos; if (!collProvider.ComputeUndisplacedPosition(ref transformedPoint, _samplingData, out undispPos)) { // If we couldn't get wave shape, assume flat water at sea level undispPos = transformedPoint; undispPos.y = OceanRenderer.Instance.SeaLevel; } Vector3 displaced; collProvider.SampleDisplacement(ref undispPos, _samplingData, out displaced); var dispPos = undispPos + displaced; var heightDiff = dispPos.y - transformedPoint.y; if (heightDiff > 0) { RB.AddForceAtPosition(archimedesForceMagnitude * heightDiff * Vector3.up * point._weight * _forceMultiplier / _totalWeight, transformedPoint); } } }
/// <summary> /// Provides ocean shape to CPU. /// </summary> public ICollProvider CreateCollisionProvider() { ICollProvider result = null; switch (_collisionSource) { case CollisionSources.None: result = new CollProviderNull(); break; case CollisionSources.OceanDisplacementTexturesGPU: result = GPUReadbackDisps.Instance; break; case CollisionSources.GerstnerWavesCPU: result = FindObjectOfType <ShapeGerstnerBatched>(); break; } if (result == null) { return(null); } if (_cachedHeightQueries) { result = new CollProviderCache(result); } return(result); }
/// <summary> /// Provides ocean shape to CPU. /// </summary> public ICollProvider CreateCollisionProvider() { ICollProvider result = null; switch (_collisionSource) { case CollisionSources.None: result = new CollProviderNull(); break; case CollisionSources.GerstnerWavesCPU: result = FindObjectOfType <ShapeGerstnerBatched>(); break; case CollisionSources.ComputeShaderQueries: result = QueryDisplacements.Instance; break; } if (result == null) { // this should not be hit - return null to create null ref exceptions Debug.Assert(false, "Could not create collision provider. Collision source = " + _collisionSource.ToString()); return(null); } return(result); }
/// <summary> /// Provides ocean shape to CPU. /// </summary> public ICollProvider CreateCollisionProvider() { ICollProvider result = null; switch (_collisionSource) { case CollisionSources.None: result = new CollProviderNull(); break; case CollisionSources.GerstnerWavesCPU: result = FindObjectOfType <ShapeGerstnerBatched>(); break; case CollisionSources.ComputeShaderQueries: result = new QueryDisplacements(); break; } if (result == null) { // this should not be hit, but can be if compute shaders aren't loaded correctly. // they will print out appropriate errors, so we don't want to return just null and have null reference // exceptions spamming the logs. //Debug.LogError($"Could not create collision provider. Collision source = {_collisionSource.ToString()}", this); return(new CollProviderNull()); } return(result); }
void UpdateWaterQueries(ICollProvider collProvider) { // Update query points for (int i = 0; i < _forcePoints.Length; i++) { _queryPoints[i] = transform.TransformPoint(_forcePoints[i]._offsetPosition + new Vector3(0, _centerOfMass.y, 0)); } _queryPoints[_forcePoints.Length] = transform.position; collProvider.Query(GetHashCode(), ObjectWidth, _queryPoints, _queryResultDisps, null, _queryResultVels); }
void FixedUpdateDrag(ICollProvider collProvider, Vector3 waterSurfaceVel) { // Apply drag relative to water var _velocityRelativeToWater = _rb.velocity - waterSurfaceVel; var forcePosition = _rb.position + _forceHeightOffset * Vector3.up; _rb.AddForceAtPosition(Vector3.up * Vector3.Dot(Vector3.up, -_velocityRelativeToWater) * _dragInWaterUp, forcePosition, ForceMode.Acceleration); _rb.AddForceAtPosition(transform.right * Vector3.Dot(transform.right, -_velocityRelativeToWater) * _dragInWaterRight, forcePosition, ForceMode.Acceleration); _rb.AddForceAtPosition(transform.forward * Vector3.Dot(transform.forward, -_velocityRelativeToWater) * _dragInWaterForward, forcePosition, ForceMode.Acceleration); }
void FixedUpdateBuoyancy(ICollProvider collProvider) { var archimedesForceMagnitude = WATER_DENSITY * Mathf.Abs(Physics.gravity.y); for (int i = 0; i < _forcePoints.Length; i++) { var waterHeight = OceanRenderer.Instance.SeaLevel + _queryResultDisps[i].y; var heightDiff = waterHeight - _queryPoints[i].y; if (heightDiff > 0) { _rb.AddForceAtPosition(archimedesForceMagnitude * heightDiff * Vector3.up * _forcePoints[i]._weight * _forceMultiplier / _totalWeight, _queryPoints[i]); } } }
/// <summary> /// Align to water normal. One normal by default, but can use a separate normal based on boat length vs width. This gives /// varying rotations based on boat dimensions. /// </summary> void FixedUpdateOrientation(ICollProvider collProvider, Vector3 undisplacedPos) { Vector3 normal, normalLongitudinal = Vector3.up; if (!collProvider.SampleNormal(ref undisplacedPos, _samplingData, out normal)) { normal = Vector3.up; } if (_useBoatLength) { // Compute a new sampling data that takes into account the boat length (as opposed to boat width) var thisRect = new Rect(transform.position.x, transform.position.z, 0f, 0f); collProvider.GetSamplingData(ref thisRect, _boatLength, _samplingDataLengthWise); if (collProvider.SampleNormal(ref undisplacedPos, _samplingDataLengthWise, out normalLongitudinal)) { var F = transform.forward; F.y = 0f; F.Normalize(); normal -= Vector3.Dot(F, normal) * F; var R = transform.right; R.y = 0f; R.Normalize(); normalLongitudinal -= Vector3.Dot(R, normalLongitudinal) * R; } collProvider.ReturnSamplingData(_samplingDataLengthWise); } if (_debugDraw) { Debug.DrawLine(transform.position, transform.position + 5f * normal, Color.green); } if (_debugDraw && _useBoatLength) { Debug.DrawLine(transform.position, transform.position + 5f * normalLongitudinal, Color.green); } var torqueWidth = Vector3.Cross(transform.up, normal); _rb.AddTorque(torqueWidth * _boyancyTorque, ForceMode.Acceleration); if (_useBoatLength) { var torqueLength = Vector3.Cross(transform.up, normalLongitudinal); _rb.AddTorque(torqueLength * _boyancyTorque, ForceMode.Acceleration); } }
void Start() { _instance = this; _oceanBuilder = FindObjectOfType <OceanBuilder>(); _oceanBuilder.GenerateMesh(_baseVertDensity, _lodCount); _collProvider = new CollProviderDispTexs(); if (_cachedCpuOceanQueries) { _collProvider = new CollProviderCache(_collProvider); } if (_viewpoint == null) { _viewpoint = Camera.main.transform; } }
/// <summary> /// Provides ocean shape to CPU. /// </summary> public ICollProvider CreateCollisionProvider() { ICollProvider result = null; switch (_collisionSource) { case CollisionSources.None: result = new CollProviderNull(); break; case CollisionSources.OceanDisplacementTexturesGPU: result = GPUReadbackDisps.Instance; Debug.Assert(result != null, "Sampling collision too early, collision system has not been initialised."); break; case CollisionSources.GerstnerWavesCPU: result = FindObjectOfType <ShapeGerstnerBatched>(); break; case CollisionSources.ComputeShaderQueries: result = QueryDisplacements.Instance; break; } if (result == null && _collisionSource == CollisionSources.OceanDisplacementTexturesGPU) { // can happen if async readback not supported on device result = new CollProviderNull(); } if (result == null) { // this should not be hit - return null to create null ref exceptions Debug.Assert(false, "Could not create collision provider. Collision source = " + _collisionSource.ToString()); return(null); } if (_cachedHeightQueries) { result = new CollProviderCache(result); } return(result); }
/// <summary> /// Align to water normal. One normal by default, but can use a separate normal based on boat length vs width. This gives /// varying rotations based on boat dimensions. /// </summary> void FixedUpdateOrientation(ICollProvider collProvider, Vector3 undisplacedPos) { Vector3 normal, normalLongitudinal; if (!collProvider.SampleNormal(ref undisplacedPos, out normal, _boatWidth)) { normal = Vector3.up; } if (_useBoatLength && collProvider.SampleNormal(ref undisplacedPos, out normalLongitudinal, _boatLength)) { var F = transform.forward; F.y = 0f; F.Normalize(); normal -= Vector3.Dot(F, normal) * F; var R = transform.right; R.y = 0f; R.Normalize(); normalLongitudinal -= Vector3.Dot(R, normalLongitudinal) * R; } else { normalLongitudinal = Vector3.up; } if (_debugDraw) { Debug.DrawLine(transform.position, transform.position + 5f * normal, Color.green); } if (_debugDraw && _useBoatLength) { Debug.DrawLine(transform.position, transform.position + 5f * normalLongitudinal, Color.green); } var torqueWidth = Vector3.Cross(transform.up, normal); _rb.AddTorque(torqueWidth * _boyancyTorque, ForceMode.Acceleration); if (_useBoatLength) { var torqueLength = Vector3.Cross(transform.up, normalLongitudinal); _rb.AddTorque(torqueLength * _boyancyTorque, ForceMode.Acceleration); } }
/// <summary> /// Align to water normal. One normal by default, but can use a separate normal based on boat length vs width. This gives /// varying rotations based on boat dimensions. /// </summary> void FixedUpdateOrientation(ICollProvider collProvider, Vector3 undisplacedPos) { Vector3 normal, normalLongitudinal = Vector3.up; if (!collProvider.SampleNormal(ref undisplacedPos, _samplingData, out normal)) { normal = Vector3.up; } if (_debugDraw) { Debug.DrawLine(transform.position, transform.position + 5f * normal, Color.green); } var torqueWidth = Vector3.Cross(transform.up, normal); RB.AddTorque(torqueWidth * _boyancyTorque, ForceMode.Acceleration); RB.AddTorque(-_dragInWaterRotational * RB.angularVelocity); }
void FixedUpdateDrag(ICollProvider collProvider, Vector3 waterSurfaceVel) { // Apply drag relative to water var pos = RB.position; Vector3 undispPos; if (!collProvider.ComputeUndisplacedPosition(ref pos, _samplingData, out undispPos)) { // If we couldn't get wave shape, assume flat water at sea level undispPos = pos; undispPos.y = OceanRenderer.Instance.SeaLevel; } var _velocityRelativeToWater = RB.velocity - waterSurfaceVel; var forcePosition = RB.position + _forceHeightOffset * Vector3.up; RB.AddForceAtPosition(Vector3.up * Vector3.Dot(Vector3.up, -_velocityRelativeToWater) * _dragInWaterUp, forcePosition, ForceMode.Acceleration); RB.AddForceAtPosition(transform.right * Vector3.Dot(transform.right, -_velocityRelativeToWater) * _dragInWaterRight, forcePosition, ForceMode.Acceleration); RB.AddForceAtPosition(transform.forward * Vector3.Dot(transform.forward, -_velocityRelativeToWater) * _dragInWaterForward, forcePosition, ForceMode.Acceleration); }
/// <summary> /// Align to water normal. One normal by default, but can use a separate normal based on boat length vs width. This gives /// varying rotations based on boat dimensions. /// </summary> void FixedUpdateOrientation(ICollProvider collProvider, Vector3 normalSideways) { Vector3 normal = normalSideways, normalLongitudinal = Vector3.up; if (_useBoatLength) { _sampleHeightHelperLengthwise.Init(transform.position, _boatLength, true); var dummy = 0f; if (_sampleHeightHelperLengthwise.Sample(ref dummy, ref normalLongitudinal)) { var F = transform.forward; F.y = 0f; F.Normalize(); normal -= Vector3.Dot(F, normal) * F; var R = transform.right; R.y = 0f; R.Normalize(); normalLongitudinal -= Vector3.Dot(R, normalLongitudinal) * R; } } if (_debugDraw) { Debug.DrawLine(transform.position, transform.position + 5f * normal, Color.green); } if (_debugDraw && _useBoatLength) { Debug.DrawLine(transform.position, transform.position + 5f * normalLongitudinal, Color.yellow); } var torqueWidth = Vector3.Cross(transform.up, normal); _rb.AddTorque(torqueWidth * _boyancyTorque, ForceMode.Acceleration); if (_useBoatLength) { var torqueLength = Vector3.Cross(transform.up, normalLongitudinal); _rb.AddTorque(torqueLength * _boyancyTorque, ForceMode.Acceleration); } }
/// <summary> /// Provides ocean shape to CPU. /// </summary> public ICollProvider CreateCollisionProvider() { ICollProvider result = null; switch (_collisionSource) { case CollisionSources.None: result = new CollProviderNull(); break; case CollisionSources.GerstnerWavesCPU: result = FindObjectOfType <ShapeGerstnerBatched>(); break; case CollisionSources.ComputeShaderQueries: if (!OceanRenderer.RunningWithoutGPU) { result = new QueryDisplacements(); } else { Debug.LogError("Crest: Compute shader queries not supported in headless/batch mode. To resolve, assign an Animated Wave Settings asset to the OceanRenderer component and set the Collision Source to be a CPU option."); } break; } if (result == null) { // this should not be hit, but can be if compute shaders aren't loaded correctly. // they will print out appropriate errors, so we don't want to return just null and have null reference // exceptions spamming the logs. //Debug.LogError($"Could not create collision provider. Collision source = {_collisionSource.ToString()}", this); return(new CollProviderNull()); } return(result); }
public CollProviderCache(ICollProvider collProvider) { _collProvider = collProvider; }