Пример #1
0
        /// <summary>
        /// Update the current segment distance
        /// </summary>
        public void UpdateSegment()
        {
            m_segmentDistance  = 0f;
            m_segmentDuration  = TimeSpan.Zero;
            m_segmentStartTime = TimeSpan.Zero;
            if (!m_isFirstPOI)
            {
                m_segmentStartTime = m_prevPoi.m_segmentStartTime + m_prevPoi.m_segmentDuration;
            }
            m_poiSteps.Clear();

            if (m_manager.m_flythroughType == PegasusConstants.FlythroughType.SingleShot && m_manager.GetNextPOI(this, false) == null)
            {
                return;
            }

            float   pct  = 0f;
            Vector3 pos1 = Vector3.zero;
            Vector3 pos2 = Vector3.zero;

            if (m_nextPoi != null)
            {
                //Calculate the segment distance by iterating over the spline - at a resolution related to the overall distance
                int   stepsPerMeter        = 3;
                int   measurementsPerMeter = stepsPerMeter * 20; //Another magic multiplier - the more steps per meter the more measurements are required
                int   measurement;
                float straightLineDistance    = Vector3.Distance(transform.position, m_nextPoi.transform.position);
                int   totalMeasurments        = (int)Mathf.Ceil((float)measurementsPerMeter * straightLineDistance);
                float measurementIncrement    = 1f / (float)totalMeasurments;
                float measurementDistance     = 0f;
                float steppedDistance         = 0f;
                float minMeasurementDistance  = 0f;
                float maxMeasurementDistance  = 0f;
                float totalSteppedDistance    = 0f;
                float minMeasuredStepDistance = 0f;
                float maxMeasuredStepDistance = 0f;

                pos1 = transform.position;
                for (measurement = 1, pct = 0f, minMeasurementDistance = 0f, maxMeasurementDistance = 0f; measurement <= totalMeasurments; measurement++)
                {
                    pct += measurementIncrement;
                    pos2 = CalculatePositionSpline(pct);
                    pos2 = m_manager.GetValidatedPoiPosition(pos2, m_heightCheckType);
                    measurementDistance = Vector3.Distance(pos1, pos2);
                    m_segmentDistance  += measurementDistance;
                    pos1 = pos2;

                    //For debugging
                    if (ApproximatelyEqual(minMeasurementDistance, 0f) || (measurementDistance < minMeasurementDistance))
                    {
                        minMeasurementDistance = measurementDistance;
                    }
                    if (ApproximatelyEqual(maxMeasurementDistance, 0f) || (measurementDistance > maxMeasurementDistance))
                    {
                        maxMeasurementDistance = measurementDistance;
                    }
                }
                //Debug.Log(string.Format("{0} - meas dist {1:0.0000},  min dist {2:0.0000}, max dist {3:0.0000}, staight length {4:0.000}, spline length {5:0.000}", transform.name, 1f / (float)measurementsPerMeter   , minMeasurementDistance, maxMeasurementDistance, straightLineDistance, m_segmentDistance));

                //Refine steps - increase them if there is a small distance in oder to create a smoother movement
                if (m_segmentDistance < 2f)
                {
                    stepsPerMeter *= 3; //Arbitrar magic value
                }

                //Now add in the actual steps - the biggest thing they need to be to get consistent speed is as close to eqidistant as possible
                float expectedStepDistance = 1f / (float)stepsPerMeter; //We want an exact multiple that gets to the whole length, but is nearest to 1 / stepsPerMeter
                expectedStepDistance = m_segmentDistance / Mathf.Floor(m_segmentDistance / expectedStepDistance);

                pos1 = transform.position;
                m_poiSteps.Add(pos1);
                for (measurement = 1, pct = 0f, minMeasuredStepDistance = 0f, maxMeasuredStepDistance = 0f; measurement <= totalMeasurments; measurement++)
                {
                    pct += measurementIncrement;
                    pos2 = CalculatePositionSpline(pct);
                    pos2 = m_manager.GetValidatedPoiPosition(pos2, m_heightCheckType);

                    measurementDistance = Vector3.Distance(pos1, pos2);
                    steppedDistance    += measurementDistance;
                    if (steppedDistance >= expectedStepDistance)
                    {
                        //For debugging
                        if (ApproximatelyEqual(minMeasuredStepDistance, 0f) || (steppedDistance < minMeasuredStepDistance))
                        {
                            minMeasuredStepDistance = steppedDistance;
                        }
                        if (ApproximatelyEqual(maxMeasuredStepDistance, 0f) || (steppedDistance > maxMeasuredStepDistance))
                        {
                            maxMeasuredStepDistance = steppedDistance;
                        }

                        //Lerp the intermediary steps to maintain distances
                        while (steppedDistance >= expectedStepDistance)
                        {
                            m_poiSteps.Add(Vector3.Lerp(m_poiSteps[m_poiSteps.Count - 1], pos2, expectedStepDistance / steppedDistance));
                            steppedDistance      -= expectedStepDistance;
                            totalSteppedDistance += expectedStepDistance;
                        }
                    }
                    pos1 = pos2;
                }

                //Debug.Log(string.Format("{0} - exp step dist {1:0.0000},  min step dist {2:0.0000}, max step dist {3:0.0000}, straight length {4:0.000}, spline length {5:0.000}, stepped length {6:0.000}, steps {7}, ERROR {8:0.000}, ERROR % {9:0.00}", transform.name, expectedStepDistance, minMeasuredStepDistance, maxMeasuredStepDistance, straightLineDistance, m_segmentDistance, totalSteppedDistance, m_poiSteps.Count, totalSteppedDistance - m_segmentDistance, ((totalSteppedDistance - m_segmentDistance) / expectedStepDistance) * 100f));

                //Check the last position, if we just missed out then add another, otherwise move the last one so it is exact
                if (((totalSteppedDistance - m_segmentDistance) / expectedStepDistance) < -0.5f)
                {
                    m_poiSteps.Add(m_nextPoi.transform.position);
                }
                else
                {
                    m_poiSteps[m_poiSteps.Count - 1] = m_nextPoi.transform.position;
                }
            }

            //Update the duration
            UpdateSegmentDuration();
        }