private void BezierQuadraticTest(MyVector3 posA, MyVector3 posB, MyVector3 handle) { //Store the interpolated values so we later can display them List <Vector3> interpolatedValues = new List <Vector3>(); //Loop between 0 and 1 in steps, where 1 step is minimum //So if steps is 5 then the line will be cut in 5 sections int steps = 10; float stepSize = 1f / (float)steps; float t = 0f; //+1 becuase wa also have to include the first point for (int i = 0; i < steps + 1; i++) { //Debug.Log(t); MyVector3 interpolatedValue = BezierQuadratic.GetPosition(posA, posB, handle, t); interpolatedValues.Add(interpolatedValue.ToVector3()); t += stepSize; } //Display the curve DisplayInterpolation.DisplayCurve(interpolatedValues, useRandomColor: true); //Display the start and end values and the handle points DisplayInterpolation.DisplayHandle(handle.ToVector3(), posA.ToVector3()); DisplayInterpolation.DisplayHandle(handle.ToVector3(), posB.ToVector3()); //Display other related data //Get the forwrd dir of the point at t and display it MyVector3 forwardDir = BezierQuadratic.GetTangent(posA, posB, handle, tSliderValue); MyVector3 slidePos = BezierQuadratic.GetPosition(posA, posB, handle, tSliderValue); Gizmos.color = Color.blue; Gizmos.DrawRay(slidePos.ToVector3(), forwardDir.ToVector3()); Gizmos.color = Color.red; Gizmos.DrawWireSphere(slidePos.ToVector3(), 0.15f); }
private IEnumerator PerformMovementCoroutine(bool ignoreMoveCosts, Action postMovementCallback) { Animator.SetTrigger("Moving Requested"); IHexCell startingCell = PositionCanon.GetOwnerOfPossession(this); IHexCell currentCell = startingCell; Vector3 currentLocation = Grid.PerformIntersectionWithTerrainSurface(currentCell.AbsolutePosition); Vector3 a, b, c = currentLocation; yield return(LookAt(CurrentPath.First().AbsolutePosition)); float t = Time.deltaTime * Config.TravelSpeedPerSecond; while ((ignoreMoveCosts || CurrentMovement > 0) && CurrentPath != null && CurrentPath.Count > 0) { var nextCell = CurrentPath.FirstOrDefault(); Vector3 nextLocation = Grid.PerformIntersectionWithTerrainSurface(nextCell.AbsolutePosition); if (!PositionCanon.CanChangeOwnerOfPossession(this, nextCell) || nextCell == null) { CurrentPath.Clear(); break; } if (!ignoreMoveCosts) { CurrentMovement = Math.Max(0, CurrentMovement - PositionCanon.GetTraversalCostForUnit(this, currentCell, nextCell, false) ); } PositionCanon.ChangeOwnerOfPossession(this, nextCell); CurrentPath.RemoveAt(0); a = c; b = currentLocation; c = (b + nextLocation) * 0.5f; for (; t < 1f; t += Time.deltaTime * Config.TravelSpeedPerSecond) { transform.position = BezierQuadratic.GetPoint(a, b, c, t); Vector3 d = BezierQuadratic.GetFirstDerivative(a, b, c, t); d.y = 0f; transform.localRotation = Quaternion.LookRotation(d); yield return(null); } t -= 1f; currentCell = nextCell; currentLocation = Grid.PerformIntersectionWithTerrainSurface(currentCell.AbsolutePosition); } if (currentCell != startingCell) { a = c; b = currentLocation; c = b; for (; t < 1f; t += Time.deltaTime * Config.TravelSpeedPerSecond) { transform.position = BezierQuadratic.GetPoint(a, b, c, t); Vector3 d = BezierQuadratic.GetFirstDerivative(a, b, c, t); d.y = 0f; transform.localRotation = Quaternion.LookRotation(d); yield return(null); } } postMovementCallback(); Animator.SetTrigger("Idling Requested"); }
private void BezierQuadraticEqualSteps(MyVector3 posA, MyVector3 posB, MyVector3 handle) { //Store the interpolated values so we later can display them List <Vector3> actualPositions = new List <Vector3>(); //Create a curve which is the data structure used in the following calculations BezierQuadratic bezierQuadratic = new BezierQuadratic(posA, posB, handle); //Step 1. Calculate the length of the entire curve //This is needed to so we know how long we should walk each step float lengthNaive = InterpolationHelpMethods.GetLength_Naive(bezierQuadratic, steps: 20, tEnd: 1f); float lengthExact = InterpolationHelpMethods.GetLength_SimpsonsRule(bezierQuadratic, tStart: 0f, tEnd: 1f); Debug.Log("Naive length: " + lengthNaive + " Exact length: " + lengthExact); int steps = 5; //Important not to confuse this with the step size we use to iterate t //This step size is distance in m float length = lengthNaive; float lengthStepSize = length / (float)steps; float stepSize = 1f / (float)steps; float t = 0f; float distanceTravelled = 0f; for (int i = 0; i < steps + 1; i++) { //MyVector3 inaccuratePos = bezierCubic.GetInterpolatedValue(t); //Calculate t to get to this distance //Method 1 //float actualT = InterpolationHelpMethods.Find_t_FromDistance_Iterative(bezierQuadratic, distanceTravelled, length); //Method 2 float actualT = InterpolationHelpMethods.Find_t_FromDistance_Lookup(bezierQuadratic, distanceTravelled, accumulatedDistances: null); MyVector3 actualPos = bezierQuadratic.GetInterpolatedValue(actualT); actualPositions.Add(actualPos.ToVector3()); //Test that the derivative calculations are working float dEst = InterpolationHelpMethods.EstimateDerivative(bezierQuadratic, t); float dAct = bezierQuadratic.ExactDerivative(t); Debug.Log("Estimated derivative: " + dEst + " Actual derivative: " + dAct); //Debug.Log("Distance " + distanceTravelled); //Move on to next iteration distanceTravelled += lengthStepSize; t += stepSize; } //List<MyVector3> positionsOnCurve = InterpolationHelpMethods.SplitCurve(bezierQuadratic, 20, tEnd: 1f); //foreach (MyVector3 p in positionsOnCurve) //{ // Gizmos.DrawWireSphere(p.ToVector3(), 0.1f); //} DisplayInterpolatedValues(actualPositions, useRandomColor: true); //Display the start and end values and the handle points DisplayHandle(handle.ToVector3(), posA.ToVector3()); DisplayHandle(handle.ToVector3(), posB.ToVector3()); }
private void BezierQuadraticTest_EqualSteps(MyVector3 posA, MyVector3 posB, MyVector3 handle) { //Create a curve which is the data structure used in the following calculations BezierQuadratic bezierQuadratic = new BezierQuadratic(posA, posB, handle); //Step 1. Calculate the length of the entire curve //This is needed to so we know how long we should walk each step float lengthNaive = InterpolationHelpMethods.GetLength_Naive(bezierQuadratic, steps: 20, tEnd: 1f); float lengthExact = InterpolationHelpMethods.GetLength_SimpsonsRule(bezierQuadratic, tStart: 0f, tEnd: 1f); //Debug.Log("Naive length: " + lengthNaive + " Exact length: " + lengthExact); //Step 2. Convert the t's to be percentage along the curve //Save the accurate t at each position on the curve List <float> accurateTs = new List <float>(); int steps = 5; //Important not to confuse this with the step size we use to iterate t //This step size is distance in m float length = lengthNaive; float lengthStepSize = length / (float)steps; float stepSize = 1f / (float)steps; float t = 0f; float distanceTravelled = 0f; for (int i = 0; i < steps + 1; i++) { //MyVector3 inaccuratePos = bezierCubic.GetInterpolatedValue(t); //Calculate t to get to this distance //Method 1 //float accurateT = InterpolationHelpMethods.Find_t_FromDistance_Iterative(bezierQuadratic, distanceTravelled, length); //Method 2 float accurateT = InterpolationHelpMethods.Find_t_FromDistance_Lookup(bezierQuadratic, distanceTravelled, accumulatedDistances: null); accurateTs.Add(accurateT); //Test that the derivative calculations are working //float dEst = InterpolationHelpMethods.EstimateDerivative(bezierQuadratic, t); //float dAct = bezierQuadratic.GetDerivative(t); //Debug.Log("Estimated derivative: " + dEst + " Actual derivative: " + dAct); //Debug.Log("Distance " + distanceTravelled); //Move on to next iteration distanceTravelled += lengthStepSize; t += stepSize; } //Get the data we want from the curve //Store the interpolated values so we later can display them List <Vector3> actualPositions = new List <Vector3>(); // List <Vector3> tangents = new List <Vector3>(); //Orientation, which includes the tangent and position List <InterpolationTransform> orientations = new List <InterpolationTransform>(); for (int i = 0; i < accurateTs.Count; i++) { float accurateT = accurateTs[i]; MyVector3 actualPos = bezierQuadratic.GetPosition(accurateT); actualPositions.Add(actualPos.ToVector3()); MyVector3 tangent = bezierQuadratic.GetTangent(accurateT); tangents.Add(tangent.ToVector3()); //Orientation, which includes both position and tangent InterpolationTransform orientation = InterpolationTransform.GetTransform_UpRef(bezierQuadratic, accurateT, MyVector3.Up); orientations.Add(orientation); } //Display //Unity doesnt have a built-in method to display an accurate Qudratic bezier, so we have to create our own //DisplayInterpolation.DisplayBezierQuadratic(bezierQuadratic, Color.black); DisplayInterpolation.DisplayCurve(bezierQuadratic, Color.black); //DisplayInterpolation.DisplayCurve(actualPositions, useRandomColor: true); DisplayInterpolation.DisplayCurve(actualPositions, Color.gray); //Display the start and end values and the handle points DisplayInterpolation.DisplayHandle(handle.ToVector3(), posA.ToVector3()); DisplayInterpolation.DisplayHandle(handle.ToVector3(), posB.ToVector3()); //Stuff on the curve //DisplayInterpolation.DisplayDirections(actualPositions, tangents, 1f, Color.red); DisplayInterpolation.DisplayOrientations(orientations, 1f); }
private void TriangulateCultureCorners_FlatEdge( IHexCell center, IHexCell left, IHexCell right, IHexCell nextRight, HexDirection direction, ICivilization centerOwner, ReadOnlyCollection <Vector2> centerRightContour, ReadOnlyCollection <Vector2> rightCenterContour, IHexMesh cultureMesh ) { if (left != null && CivTerritoryLogic.GetCivClaimingCell(left) != centerOwner) { Color cultureColor = centerOwner.Template.Color; var centerLeftContour = CellEdgeContourCanon.GetContourForCellEdge(center, direction.Previous()); var rightLeftContour = CellEdgeContourCanon.GetContourForCellEdge(right, direction.Previous2()); Vector2 centerLeftFirstInner = Vector2.Lerp(centerLeftContour.First(), center.AbsolutePositionXZ, RenderConfig.CultureWidthPercent); Vector2 centerLeftLastInner = Vector2.Lerp(centerLeftContour.Last(), center.AbsolutePositionXZ, RenderConfig.CultureWidthPercent); Vector2 rightLeftFirstInner = Vector2.Lerp(rightLeftContour.First(), right.AbsolutePositionXZ, RenderConfig.CultureWidthPercent); Vector2 rightleftLastInner = Vector2.Lerp(rightLeftContour.Last(), right.AbsolutePositionXZ, RenderConfig.CultureWidthPercent); Vector2 rayAlongCenterLeft = (centerLeftLastInner - centerLeftFirstInner).normalized; Vector2 rayAlongRightLeft = (rightLeftFirstInner - rightleftLastInner).normalized; Vector2 bezierControl; if (!Geometry2D.ClosestPointsOnTwoLines( centerLeftLastInner, rayAlongCenterLeft, rightLeftFirstInner, rayAlongRightLeft, out bezierControl, out bezierControl )) { Debug.LogError("TriangulateCultureCorners_FlatEdge failed to find a valid control point"); return; } Vector3 pivotXYZ = new Vector3(centerLeftContour.Last().x, 0f, centerLeftContour.Last().y); float paramDelta = 5f / RenderConfig.RiverQuadsPerCurve; for (float t = 0; t < 1f; t = Mathf.Clamp01(t + paramDelta)) { float nextT = Mathf.Clamp01(t + paramDelta); Vector2 bezierOne = BezierQuadratic.GetPoint(centerLeftLastInner, bezierControl, rightLeftFirstInner, nextT); Vector2 bezierTwo = BezierQuadratic.GetPoint(centerLeftLastInner, bezierControl, rightLeftFirstInner, t); cultureMesh.AddTriangle(pivotXYZ, new Vector3(bezierOne.x, 0f, bezierOne.y), new Vector3(bezierTwo.x, 0f, bezierTwo.y)); cultureMesh.AddTriangleUV(new Vector2(0f, 1f), Vector2.zero, Vector2.zero); cultureMesh.AddTriangleColor(cultureColor); } if (rightCenterContour.Count == 3) { Vector2 innerPoint = Vector2.Lerp(rightCenterContour.Last(), right.AbsolutePositionXZ, RenderConfig.CultureWidthPercent); Vector2 secondToLastContour = rightCenterContour[rightCenterContour.Count - 2]; Vector2 lastContour = rightCenterContour.Last(); cultureMesh.AddTriangle( new Vector3(innerPoint.x, 0f, innerPoint.y), new Vector3(secondToLastContour.x, 0f, secondToLastContour.y), new Vector3(lastContour.x, 0f, lastContour.y) ); cultureMesh.AddTriangleUV(new Vector2(0f, 0f), new Vector2(0f, 1f), new Vector2(0f, 1f)); cultureMesh.AddTriangleColor(cultureColor); } } }