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);
        }
Exemple #3
0
        /// <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);
        }
Exemple #4
0
        /// <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);
        }
Exemple #5
0
        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;
            }
        }
Exemple #10
0
        /// <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);
        }
Exemple #14
0
    /// <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);
        }
    }
Exemple #15
0
        /// <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);
        }
Exemple #16
0
 public CollProviderCache(ICollProvider collProvider)
 {
     _collProvider = collProvider;
 }