/// <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(); }