public double LocalToPathPercent(double localPercent, int elementIndex) { if (root == null) { return(0.0); } int totalSpan = 0; foreach (Element element in _elements) { totalSpan += element.span; } double passed = 0.0; for (int i = 0; i < _elements.Length; i++) { double computerPercent = (double)_elements[i].span / totalSpan; passed += computerPercent; if (i == elementIndex) { passed -= computerPercent; double normalized = DMath.InverseLerp(_elements[i].startPercent, _elements[i].endPercent, localPercent); return(passed + computerPercent * normalized); } } return(0.0); }
public void GetEvaluationValues(double inputPercent, out SplineComputer computer, out double percent, out Spline.Direction direction) { computer = null; percent = 0.0; direction = Spline.Direction.Forward; if (root == null) { return; } int totalSpan = 0; foreach (Element element in _elements) { totalSpan += element.span; } double passed = 0.0; for (int i = 0; i < _elements.Length; i++) { if (passed > inputPercent) { break; } double computerPercent = (double)_elements[i].span / totalSpan; percent = DMath.Lerp(_elements[i].startPercent, _elements[i].endPercent, DMath.InverseLerp(passed, passed + computerPercent, inputPercent)); computer = _elements[i].computer; passed += computerPercent; } }
public Vector3 EvaluatePosition(double percent) { if (root == null) { return(Vector3.zero); } if (_elements.Length == 1) { return(_elements[0].computer.EvaluatePosition(percent)); } double totalLength = 0.0; for (int i = 0; i < _elements.Length; i++) { totalLength += _elements[i].span; } double passed = 0.0; for (int i = 0; i < _elements.Length; i++) { double computerPercent = _elements[i].span / totalLength; passed += computerPercent; if (passed >= percent || Mathf.Approximately((float)passed, (float)percent)) { double localPercent = DMath.Lerp(_elements[i].startPercent, _elements[i].endPercent, DMath.InverseLerp(passed - computerPercent, passed, percent)); return(_elements[i].computer.EvaluatePosition(localPercent)); } } return(Vector3.zero); }
private static Func <decimal, decimal> FunctionFromType(EasingType easing) { switch (easing) { case EasingType.Constant: return(x => 1); case EasingType.Linear: return(x => x); case EasingType.Quadratic: return(x => DMath.Pow(x, 2)); case EasingType.Cubic: return(x => DMath.Pow(x, 3)); case EasingType.Quartic: return(x => DMath.Pow(x, 4)); case EasingType.Quintic: return(x => DMath.Pow(x, 5)); case EasingType.Sinusoidal: return(x => 1 - DMath.Cos(x * DMath.PI / 2)); // Wait... That's not Sine! case EasingType.Exponential: return(x => DMath.Pow(x, 5)); case EasingType.Circular: return(x => 1 - DMath.Sqrt(1 - x * x)); default: throw new ArgumentOutOfRangeException(); } }
public void GetSamplingValues(double percent, out int sampleIndex, out double lerp) { lerp = 0.0; if (sampleMode == SplineComputer.SampleMode.Optimized) { double indexValue = percent * (optimizedIndices.Length - 1); int index = DMath.FloorInt(indexValue); sampleIndex = optimizedIndices[index]; double lerpPercent = 0.0; if (index < optimizedIndices.Length - 1) { //Percent 0-1 between the sampleIndex and the next sampleIndex double indexLerp = indexValue - index; double sampleIndexPercent = (double)index / (optimizedIndices.Length - 1); double nextSampleIndexPercent = (double)(index + 1) / (optimizedIndices.Length - 1); //Percent 0-1 of the sample between the sampleIndices' percents lerpPercent = DMath.Lerp(sampleIndexPercent, nextSampleIndexPercent, indexLerp); } if (sampleIndex < Count - 1) { lerp = DMath.InverseLerp(samples[sampleIndex].percent, samples[sampleIndex + 1].percent, lerpPercent); } return; } sampleIndex = DMath.FloorInt(percent * (Count - 1)); lerp = (Count - 1) * percent - sampleIndex; }
void SplitAtPoint(int index, ref SplinePoint[] points) { Undo.RecordObject(computer, "Split At Point " + index); EditorUtility.SetDirty(computer); SplinePoint[] splitPoints = new SplinePoint[computer.pointCount - index]; for (int i = 0; i < splitPoints.Length; i++) { splitPoints[i] = computer.GetPoint(index + i); } SplineComputer spline = CreateNewSpline(); spline.SetPoints(splitPoints); SplineUser[] users = spline.GetSubscribers(); for (int i = 0; i < users.Length; i++) { users[i].clipFrom = DMath.InverseLerp((double)index / (computer.pointCount - 1), 1.0, users[i].clipFrom); users[i].clipTo = DMath.InverseLerp((double)index / (computer.pointCount - 1), 1.0, users[i].clipTo); } splitPoints = new SplinePoint[index + 1]; for (int i = 0; i <= index; i++) { splitPoints[i] = computer.GetPoint(i); } points = splitPoints; users = computer.GetSubscribers(); for (int i = 0; i < users.Length; i++) { users[i].clipFrom = DMath.InverseLerp(0.0, ((double)index) / (computer.pointCount - 1), users[i].clipFrom); users[i].clipTo = DMath.InverseLerp(0.0, ((double)index) / (computer.pointCount - 1), users[i].clipTo); } HandleNodes(spline, index); }
public override void SetAnimatorParameters() { if (InputAxisFloatHash != 0) { Animator.SetFloat(InputAxisFloatHash, _axis); } if (InputBoolHash != 0) { Animator.SetBool(InputBoolHash, !DMath.Equalsf(_axis)); } if (AcceleratingBoolHash != 0) { Animator.SetBool(AcceleratingBoolHash, Accelerating); } if (BrakingBoolHash != 0) { Animator.SetBool(BrakingBoolHash, Braking); } if (TopSpeedPercentFloatHash != 0) { Animator.SetFloat(TopSpeedPercentFloatHash, Mathf.Abs(Controller.GroundVelocity) / TopSpeed); } }
public override void OnActiveEnter(State previousState) { //Debug.Log("Jump"); Used = true; Controller.Detach(); Controller.Velocity += DMath.AngleToVector((Controller.SurfaceAngle + 90.0f) * Mathf.Deg2Rad) * ActivateSpeed; var roll = Manager.Get <Roll>(); if (roll == null) { return; } if (roll.Active) { // Disable air control if jumping while rolling Manager.End <AirControl>(); } else { Manager.Perform <Roll>(true, true); } }
private void BezierGetTangent(ref Vector3 tangent, double t, int i) { if (points.Length > 0) { tangent = points[0].tangent2; } else { return; } if (points.Length == 1) { return; } if (i < points.Length - 1) { t = DMath.Clamp01(t); i = Mathf.Clamp(i, 0, points.Length - 2); float ft = (float)t; float nt = 1f - ft; tangent = -3 * nt * nt * points[i].position + 3 * nt * nt * points[i].tangent2 - 6 * ft * nt * points[i].tangent2 - 3 * ft * ft * points[i + 1].tangent + 6 * ft * nt * points[i + 1].tangent + 3 * ft * ft * points[i + 1].position; } }
private void LinearGetPoint(ref Vector3 point, double t, int i) { if (points.Length == 0) { point = Vector3.zero; return; } if (i + 1 < points.Length) { t = DMath.Clamp01(t); i = Mathf.Clamp(i, 0, points.Length - 2); point = Vector3.Lerp(points[i].position, points[i + 1].position, (float)t); } else { if (i < points.Length) { point = points[i].position; } else { point = Vector3.zero; } } }
/// <summary> /// Returns the percent from the spline at a given distance from the start point /// </summary> /// <param name="start">The start point</param> /// /// <param name="distance">The distance to travel</param> /// <param name="direction">The direction towards which to move</param> /// <returns></returns> public double Travel(double start, float distance, Spline.Direction direction) { float moved = 0f; float lastMoved = 0f; Vector3 lastPoint = EvaluatePosition(start); Vector3 currentPoint = lastPoint; int step = DMath.FloorInt(start / moveStep); double percent = moveStep * (step + 1); double lastPercent = start; while (moved < distance) { if (direction == Spline.Direction.Forward) { step++; } else { step--; } lastPercent = percent; percent = moveStep * step; if (percent < 0.0 || percent > 1.0) { break; } currentPoint = EvaluatePosition(percent); lastMoved = moved; moved += Vector3.Distance(currentPoint, lastPoint); lastPoint = currentPoint; } double distancePercent = DMath.InverseLerp(lastMoved, moved, distance); return(DMath.Lerp(lastPercent, percent, distancePercent)); }
private void BezierGetPoint(ref Vector3 point, double t, int i) { //Used for getting a point on a Bezier spline if (points.Length > 0) { point = points[0].position; } else { return; } if (points.Length == 1) { return; } if (i < points.Length - 1) { t = DMath.Clamp01(t); i = Mathf.Clamp(i, 0, points.Length - 2); float ft = (float)t; float nt = 1f - ft; point = nt * nt * nt * points[i].position + 3f * nt * nt * ft * points[i].tangent2 + 3f * nt * ft * ft * points[i + 1].tangent + ft * ft * ft * points[i + 1].position; } }
public override void OnActiveEnter(State previousState) { if (DMath.Equalsf(Controller.GroundVelocity)) { Controller.FacingForward = Controller.Footing == Footing.Left; } if (!AllowDuck) { var duck = Manager.Get <Duck>(); if (duck != null) { duck.AllowShouldPerform = false; } } if (!AllowLookUp) { var lookUp = Manager.Get <LookUp>(); if (lookUp != null) { lookUp.AllowShouldPerform = false; } } }
public override void OnActiveUpdate() { if (DMath.Equalsf(Controller.GroundVelocity)) { Controller.FacingForward = Controller.Footing == Footing.Left; } }
public int GetClippedSampleCount(double clipFrom, double clipTo, out int startIndex, out int endIndex) { startIndex = endIndex = 0; if (sampleMode == SplineComputer.SampleMode.Default) { startIndex = DMath.FloorInt((Count - 1) * clipFrom); endIndex = DMath.CeilInt((Count - 1) * clipTo); } else { double clipFromLerp = 0.0, clipToLerp = 0.0; GetSamplingValues(clipFrom, out startIndex, out clipFromLerp); GetSamplingValues(clipTo, out endIndex, out clipToLerp); if (clipToLerp > 0.0 && endIndex < Count - 1) { endIndex++; } } if (clipTo < clipFrom) //Handle looping segments { int toSamples = endIndex + 1; int fromSamples = Count - startIndex; return(toSamples + fromSamples); } return(endIndex - startIndex + 1); }
/// <summary> /// Evaluates the spline segment based on the spline's precision and returns only the position. /// </summary> /// <param name="positions">The position buffer</param> /// <param name="from">Start position [0-1]</param> /// <param name="to">Target position [from-1]</param> /// <returns></returns> public void EvaluatePositions(ref Vector3[] positions, double from = 0.0, double to = 1.0) { if (points.Length == 0) { positions = new Vector3[0]; return; } from = DMath.Clamp01(from); to = DMath.Clamp(to, from, 1.0); double fromValue = from * (iterations - 1); double toValue = to * (iterations - 1); int clippedIterations = DMath.CeilInt(toValue) - DMath.FloorInt(fromValue) + 1; if (positions.Length != clippedIterations) { positions = new Vector3[clippedIterations]; } double percent = from; double ms = moveStep; int index = 0; while (true) { positions[index] = EvaluatePosition(percent); index++; if (index >= positions.Length) { break; } percent = DMath.Move(percent, to, ms); } }
public void GetEvaluationValues(double inputPercent, out SplineComputer computer, out double percent, out Spline.Direction direction) { computer = null; percent = 0.0; direction = Spline.Direction.Forward; if (root == null) { return; } int num = 0; Element[] elements = _elements; foreach (Element element in elements) { num += element.span; } double num2 = 0.0; for (int j = 0; j < _elements.Length; j++) { if (num2 > inputPercent) { break; } double num3 = (double)_elements[j].span / (double)num; percent = DMath.Lerp(_elements[j].startPercent, _elements[j].endPercent, DMath.InverseLerp(num2, num2 + num3, inputPercent)); computer = _elements[j].computer; num2 += num3; } }
public override void OnActiveFixedUpdate() { UpdateControlLockTimer(); // Accelerate as long as the control lock isn't on if (!ControlLockTimerOn) { Accelerate(_axis); } // If we're on a wall and aren't going quickly enough, start the control lock if (Mathf.Abs(Controller.GroundVelocity) < Controller.DetachSpeed && DMath.AngleInRange_d(Controller.RelativeSurfaceAngle, 50.0f, 310.0f)) { Lock(); } // Disable slope gravity when we're not moving, so that Sonic can stand on slopes Controller.DisableSlopeGravity = !(Accelerating || ControlLockTimerOn || Mathf.Abs(Controller.GroundVelocity) > MinSlopeGravitySpeed); // Disable ground friction while we have player input Controller.DisableGroundFriction = (!DisableAcceleration && Accelerating) || (!DisableDeceleration && Braking); // Orient the player in the direction we're moving (not graphics-wise, just internally!) if (!ControlLockTimerOn && !DMath.Equalsf(_axis)) { Controller.FacingForward = Controller.GroundVelocity >= 0.0f; } }
public double LocalToPathPercent(double localPercent, int elementIndex) { if (root == null) { return(0.0); } int num = 0; Element[] elements = _elements; foreach (Element element in elements) { num += element.span; } double num2 = 0.0; for (int j = 0; j < _elements.Length; j++) { double num3 = (double)_elements[j].span / (double)num; num2 += num3; if (j == elementIndex) { num2 -= num3; double num4 = DMath.InverseLerp(_elements[j].startPercent, _elements[j].endPercent, localPercent); return(num2 + num3 * num4); } } return(0.0); }
public Vector3 EvaluatePosition(double percent) { if (root == null) { return(Vector3.zero); } if (_elements.Length == 1) { return(_elements[0].computer.EvaluatePosition(percent)); } double num = 0.0; for (int i = 0; i < _elements.Length; i++) { num += (double)_elements[i].span; } double num2 = 0.0; for (int j = 0; j < _elements.Length; j++) { double num3 = (double)_elements[j].span / num; num2 += num3; if (num2 >= percent || Mathf.Approximately((float)num2, (float)percent)) { double percent2 = DMath.Lerp(_elements[j].startPercent, _elements[j].endPercent, DMath.InverseLerp(num2 - num3, num2, percent)); return(_elements[j].computer.EvaluatePosition(percent2)); } } return(Vector3.zero); }
public void AlignTextureWithFace(Face face) { // Get reference values for the axes var refU = face.Texture.UAxis; var refV = face.Texture.VAxis; // Reference points in the texture plane to use for shifting later on var refX = face.Texture.UAxis * face.Texture.XShift * face.Texture.XScale; var refY = face.Texture.VAxis * face.Texture.YShift * face.Texture.YScale; // Two non-parallel planes intersect at an edge. We want the textures on this face // to line up with the textures on the provided face. To do this, we rotate the texture // normal on the provided face around the intersection edge to get the new texture axes. // Then we rotate the texture reference point around this edge as well to get the new shift values. // The scale values on both faces will always end up being the same value. // Find the intersection edge vector var intersectionEdge = face.Plane.Normal.Cross(Plane.Normal); // Create a plane using the intersection edge as the normal var intersectionPlane = new Plane(intersectionEdge, 0); // If the planes are parallel, the texture doesn't need any rotation - just different shift values. var intersect = Plane.Intersect(face.Plane, Plane, intersectionPlane); if (intersect != null) { var texNormal = face.Texture.GetNormal(); // Since the intersection plane is perpendicular to both face planes, we can find the angle // between the two planes (the original texture plane and the plane of this face) by projecting // the normals of the planes onto the perpendicular plane and taking the cross product. // Project the two normals onto the perpendicular plane var ptNormal = intersectionPlane.Project(texNormal).Normalise(); var ppNormal = intersectionPlane.Project(Plane.Normal).Normalise(); // Get the angle between the projected normals var dot = Math.Round(ptNormal.Dot(ppNormal), 4); var angle = DMath.Acos(dot); // A.B = cos(angle) // Rotate the texture axis by the angle around the intersection edge var transform = new UnitRotate(angle, new Line(Coordinate.Zero, intersectionEdge)); refU = transform.Transform(refU); refV = transform.Transform(refV); // Rotate the texture reference points as well, but around the intersection line, not the origin refX = transform.Transform(refX + intersect) - intersect; refY = transform.Transform(refY + intersect) - intersect; } // Convert the reference points back to get the final values Texture.Rotation = 0; Texture.UAxis = refU; Texture.VAxis = refV; Texture.XShift = refU.Dot(refX) / face.Texture.XScale; Texture.YShift = refV.Dot(refY) / face.Texture.YScale; Texture.XScale = face.Texture.XScale; Texture.YScale = face.Texture.YScale; CalculateTextureCoordinates(true); }
private void BezierGetPoint(ref Vector3 point, double t, int i) { //Used for getting a point on a Bezier spline if (points.Length > 0) { point = points[0].position; } else { return; } if (points.Length == 1) { return; } if (i < points.Length - 1) { t = DMath.Clamp01(t); i = Mathf.Clamp(i, 0, points.Length - 2); Vector3 P0 = points[i].position; Vector3 P1 = points[i].tangent2; Vector3 P2 = points[i + 1].tangent; Vector3 P3 = points[i + 1].position; float ft = (float)t; point = Mathf.Pow(1 - ft, 3) * P0 + 3 * Mathf.Pow((1 - ft), 2) * ft * P1 + 3 * (1 - ft) * Mathf.Pow(ft, 2) * P2 + Mathf.Pow(ft, 3) * P3; } }
/// <summary> /// The Inverse of the matrix copied into mInv. /// Returns false if the matrix has no inverse. /// A matrix multipled by its inverse is the idenity. /// Invert a 3x3 using cofactors. This is about 8 times faster than /// the Numerical Recipes code which uses Gaussian elimination. /// </summary> public bool TryInverse(ref Matrix3x3d mInv) { mInv.m00 = m11 * m22 - m12 * m21; mInv.m01 = m02 * m21 - m01 * m22; mInv.m02 = m01 * m12 - m02 * m11; mInv.m10 = m12 * m20 - m10 * m22; mInv.m11 = m00 * m22 - m02 * m20; mInv.m12 = m02 * m10 - m00 * m12; mInv.m20 = m10 * m21 - m11 * m20; mInv.m21 = m01 * m20 - m00 * m21; mInv.m22 = m00 * m11 - m01 * m10; double det = m00 * mInv.m00 + m01 * mInv.m10 + m02 * mInv.m20; if (DMath.IsZero(det)) { return(false); } double invDet = 1.0 / det; mInv.m00 *= invDet; mInv.m01 *= invDet; mInv.m02 *= invDet; mInv.m10 *= invDet; mInv.m11 *= invDet; mInv.m12 *= invDet; mInv.m20 *= invDet; mInv.m21 *= invDet; mInv.m22 *= invDet; return(true); }
/// <summary> /// Calculate the length of the spline /// </summary> /// <param name="from">Calculate from [0-1] default: 0f</param> /// <param name="to">Calculate to [0-1] default: 1f</param> /// <param name="resolution">Resolution multiplier for precision [0-1] default: 1f</param> /// <returns></returns> public float CalculateLength(double from = 0.0, double to = 1.0, double resolution = 1.0) { if (points.Length == 0) { return(0f); } resolution = DMath.Clamp01(resolution); if (resolution == 0.0) { return(0f); } from = DMath.Clamp01(from); to = DMath.Clamp01(to); if (to < from) { to = from; } double percent = from; Vector3 lastPos = EvaluatePosition(percent); float sum = 0f; while (true) { percent = DMath.Move(percent, to, moveStep / resolution); Vector3 pos = EvaluatePosition(percent); sum += (pos - lastPos).magnitude; lastPos = pos; if (percent == to) { break; } } return(sum); }
/// <summary> /// Casts rays along the spline against all colliders in the scene /// </summary> /// <param name="hit">Hit information</param> /// <param name="hitPercent">The percent of evaluation where the hit occured</param> /// <param name="layerMask">Layer mask for the raycast</param> /// <param name="resolution">Resolution multiplier for precision [0-1] default: 1f</param> /// <param name="from">Raycast from [0-1] default: 0f</param> /// <param name="to">Raycast to [0-1] default: 1f</param> /// <param name="hitTriggers">Should hit triggers? (not supported in 5.1)</param> /// <returns></returns> public bool Raycast(out RaycastHit hit, out double hitPercent, LayerMask layerMask, double resolution = 1.0, double from = 0.0, double to = 1.0, QueryTriggerInteraction hitTriggers = QueryTriggerInteraction.UseGlobal ) { resolution = DMath.Clamp01(resolution); from = DMath.Clamp01(from); to = DMath.Clamp01(to); double percent = from; Vector3 fromPos = EvaluatePosition(percent); hitPercent = 0f; if (resolution == 0f) { hit = new RaycastHit(); hitPercent = 0f; return(false); } while (true) { double prevPercent = percent; percent = DMath.Move(percent, to, moveStep / resolution); Vector3 toPos = EvaluatePosition(percent); if (Physics.Linecast(fromPos, toPos, out hit, layerMask, hitTriggers)) { double segmentPercent = (hit.point - fromPos).sqrMagnitude / (toPos - fromPos).sqrMagnitude; hitPercent = DMath.Lerp(prevPercent, percent, segmentPercent); return(true); } fromPos = toPos; if (percent == to) { break; } } return(false); }
public IEnumerable <MapObject> Create(IDGenerator generator, Box box, ITexture texture, int roundDecimals) { var numSides = (int)_numSides.GetValue(); if (numSides < 3) { yield break; } // This is all very similar to the cylinder brush. var width = box.Width; var length = box.Length; var major = width / 2; var minor = length / 2; var angle = 2 * DMath.PI / numSides; var points = new Coordinate[numSides]; for (var i = 0; i < numSides; i++) { var a = i * angle; var xval = box.Center.X + major * DMath.Cos(a); var yval = box.Center.Y + minor * DMath.Sin(a); var zval = box.Start.Z; points[i] = new Coordinate(xval, yval, zval).Round(roundDecimals); } var faces = new List <Coordinate[]>(); var point = new Coordinate(box.Center.X, box.Center.Y, box.End.Z).Round(roundDecimals); for (var i = 0; i < numSides; i++) { var next = (i + 1) % numSides; faces.Add(new[] { points[i], point, points[next] }); } faces.Add(points.ToArray()); var solid = new Solid(generator.GetNextObjectID()) { Colour = Colour.GetRandomBrushColour(), Flags = (System.UInt32)SolidFlags.solid }; foreach (var arr in faces) { var face = new Face(generator.GetNextFaceID()) { Parent = solid, Plane = new Plane(arr[0], arr[1], arr[2]), Colour = solid.Colour, Texture = { Texture = texture } }; face.Vertices.AddRange(arr.Select(x => new Vertex(x, face))); face.Init(); solid.Faces.Add(face); } solid.UpdateBoundingBox(); yield return(solid); }
public override void Awake() { base.Awake(); if (DMath.Equalsf(Friction)) { Friction += DMath.Epsilon; } }
/// <summary> /// Treats this vector as a directional unit vector and constructs a euler angle representation of that angle (in radians) /// </summary> /// <returns></returns> public Coordinate ToEulerAngles() { // http://www.gamedev.net/topic/399701-convert-vector-to-euler-cardan-angles/#entry3651854 var yaw = DMath.Atan2(_y, _x); var pitch = DMath.Atan2(-_z, DMath.Sqrt(_x * _x + _y * _y)); return(new Coordinate(0, pitch, yaw)); // HL FGD has X = roll, Y = pitch, Z = yaw }
private void EvaluateTangent(ref Vector3 tangent, double percent) { percent = DMath.Clamp01(percent); double doubleIndex = (points.Length - 1) * percent; int pointIndex = Mathf.Clamp(DMath.FloorInt(doubleIndex), 0, Mathf.Max(points.Length - 2, 0)); GetTangent(ref tangent, doubleIndex - pointIndex, pointIndex); }
private void EvaluatePosition(ref Vector3 point, double percent) { percent = DMath.Clamp01(percent); double num = (double)(points.Length - 1) * percent; int num2 = Mathf.Clamp(DMath.FloorInt(num), 0, Mathf.Max(points.Length - 2, 0)); GetPoint(ref point, num - (double)num2, num2); }