Пример #1
0
        public void Update(ManagedHand managedHand, Vector3 keyPointLocation, params Vector3[] decayPoints)
        {
            if (!managedHand.Visible)
            {
                //lost:
                if (Visible)
                {
                    FireLostEvent();
                    _progress.locationHistory.Clear();
                }

                return;
            }

            //visibility status:
            bool currentVisibility = true;

            //too close to next joint in chain means visibility failed:
            if (Vector3.Distance(keyPointLocation, _mainCamera.transform.position) < _minHeadDistance)
            {
                currentVisibility = false;
            }
            else
            {
                for (int i = 0; i < decayPoints.Length; i++)
                {
                    if (Vector3.Distance(keyPointLocation, decayPoints[i]) < _lostKeyPointDistance)
                    {
                        currentVisibility = false;
                        break;
                    }
                }
            }

            positionRaw = keyPointLocation;

            //lost visibility:
            if (!currentVisibility && Visible)
            {
                FireLostEvent();
                _progress.locationHistory.Clear();
                return;
            }

            //history cache:
            _progress.locationHistory.Add(keyPointLocation);

            //only need 3 in our history:
            if (_progress.locationHistory.Count > 3)
            {
                _progress.locationHistory.RemoveAt(0);
            }

            //we have enough history:
            if (_progress.locationHistory.Count == 3)
            {
                //movement intent stats:
                Vector3 vectorA = _progress.locationHistory[_progress.locationHistory.Count - 2] - _progress.locationHistory[_progress.locationHistory.Count - 3];
                Vector3 vectorB = _progress.locationHistory[_progress.locationHistory.Count - 1] - _progress.locationHistory[_progress.locationHistory.Count - 2];
                float   delta   = Vector3.Distance(_progress.locationHistory[_progress.locationHistory.Count - 3], _progress.locationHistory[_progress.locationHistory.Count - 1]);
                float   angle   = Vector3.Angle(vectorA, vectorB);
                Stability = 1 - Mathf.Clamp01(delta / _maxDistance);

                //moving in a constant direction?
                if (angle < 90)
                {
                    _progress.target = _progress.locationHistory[_progress.locationHistory.Count - 1];
                }

                //snap or smooth:
                if (Stability == 0)
                {
                    positionFiltered = _progress.target;
                }
                else
                {
                    positionFiltered = Vector3.SmoothDamp(positionFiltered, _progress.target, ref _progress.velocity, _smoothTime * Stability);
                }
            }
            else
            {
                positionFiltered = keyPointLocation;
            }

            //inside the camera plane - flatten against the plane?
            InsideClipPlane = TransformUtilities.InsideClipPlane(positionFiltered);
            if (InsideClipPlane)
            {
                positionFiltered = TransformUtilities.LocationOnClipPlane(positionFiltered);
            }

            //gained visibility:
            if (currentVisibility && !Visible)
            {
                //we must also break distance for point proximity:
                for (int i = 0; i < decayPoints.Length; i++)
                {
                    if (Vector3.Distance(keyPointLocation, decayPoints[i]) < _foundKeyPointDistance)
                    {
                        currentVisibility = false;
                        break;
                    }
                }

                //still good?
                if (currentVisibility)
                {
                    FireFoundEvent();
                }
            }
        }