private Quaternion getAngle(Vector2 p2) { // var angle = Mathf.Atan2(p2.y - p1.y, p2.x - p1.x) * 180 / Mathf.PI; var angle = Math3d.AngleBetweenVector2(AsUp, p2); return(Quaternion.AngleAxis(angle, AsForward)); }
void Fall_SuperUpdate() { if (AcquiringGround()) { moveDirection = Math3d.ProjectVectorOnPlane(controller.up, moveDirection); currentState = PlayerStates.Idle; return; } if (input.Current.JumpInput && doubleJump == false) { currentState = PlayerStates.DoubleJump; return; } if (input.Current.JumpInput && doubleJump == true) { currentState = PlayerStates.Glide; return; } Vector3 planarMoveDirection = Math3d.ProjectVectorOnPlane(controller.up, moveDirection); Vector3 verticalMoveDirection = moveDirection - planarMoveDirection; planarMoveDirection = Vector3.MoveTowards(planarMoveDirection, LocalMovement() * WalkSpeed, JumpAcceleration * controller.deltaTime); verticalMoveDirection -= controller.up * Gravity * controller.deltaTime; verticalMoveDirection.y = Mathf.Max(verticalMoveDirection.y, -7f); moveDirection = planarMoveDirection + verticalMoveDirection; }
void WallSlide_SuperUpdate() { if (input.Current.MoveInput == Vector3.zero || Vector3.Dot(collisionVector, LocalMovement()) > 0) { currentState = PlayerStates.Fall; return; } Vector3 planarMoveDirection = Math3d.ProjectVectorOnPlane(controller.up, moveDirection); Vector3 verticalMoveDirection = moveDirection - planarMoveDirection; if (Vector3.Angle(verticalMoveDirection, controller.up) > 90 && AcquiringGround()) { moveDirection = planarMoveDirection; currentState = PlayerStates.Idle; return; } if (input.Current.JumpInput) { moveDirection = collisionVector * 8; currentState = PlayerStates.Jump; return; } moveDirection -= controller.up * Gravity * 0.1f * Time.deltaTime; }
public void CreateEdgesBetweenNodes() { foreach (var node in m_graph.Nodes) { foreach (var dir in Graph.allDirections) { var nextPos = new Vector3(node.position.x + dir.x, 0f, node.position.z + dir.y); var neighborNode = GetNodeAtPosition(nextPos); if (neighborNode != null && neighborNode.nodeType != NodeType.Blocked && node.nodeType != NodeType.Blocked) { // TODO: this blocked by wall stuff works fine, but i was tired and its quite ugly. bool isBlockedByWall = false; foreach (var wall in walls) { var blocked = Math3d.AreLineSegmentsCrossing(node.position, neighborNode.position, wall.wallPoints[0].position, wall.wallPoints[1].position); if (blocked) { isBlockedByWall = true; break; } } if (!isBlockedByWall) { m_graph.AddEdge(node.NodeIndex, neighborNode.NodeIndex, m_terrainCosts.GetCost(neighborNode.nodeType)); } } } } }
/// <summary> /// Method used to calculate destination position when player jumps. /// </summary> /// <returns>The player's jump destination position.</returns> /// <param name="jumpStartPosition">Jump start position (typically, player's current position).</param> /// <param name="currentVertexFollowed">Current vertex that is being followed.</param> public Vector2 GetJumpDestinationPosition(Vector2 jumpStartPosition, VertexController currentVertexFollowed) { int currentVertexIndex = currentVertexFollowed.transform.GetSiblingIndex(); int previousVertexIndex = currentVertexIndex - 1; previousVertexIndex = previousVertexIndex < 0 ? previousVertexIndex + this.transform.childCount : previousVertexIndex; VertexController previousVertex = this.transform.GetChild(previousVertexIndex).GetComponent <VertexController>(); int nextVertexIndex = (currentVertexIndex + 1) % this.transform.childCount; VertexController nextVertex = this.transform.GetChild(nextVertexIndex).GetComponent <VertexController>(); Vector2 line = (nextVertex.transform.position - previousVertex.transform.position).normalized; line = line.y < 0 ? -line : line; float lineA = Mathf.Tan(Vector2.Angle(line, Vector2.right) * Mathf.Deg2Rad); float lineB = jumpStartPosition.y - (lineA * jumpStartPosition.x); Vector2 linePoint1 = new Vector2(0, lineB); Vector2 linePoint2 = new Vector2(1, lineA + lineB); // Debug lines drawing, uncomment to debug this method //Debug.DrawLine(previousVertex.transform.position, nextVertex.transform.position, Color.green, 3f); //Debug.DrawLine(linePoint1, linePoint2, Color.red, 3f); //Debug.DrawLine(jumpStartPosition + Vector2.left, jumpStartPosition + Vector2.right, Color.white, 3f); //Debug.DrawLine(jumpStartPosition + Vector2.down, jumpStartPosition + Vector2.up, Color.white, 3f); Vector3 intersectionPoint = Vector3.zero; Math3d.LineLineIntersection(out intersectionPoint, currentVertexFollowed.transform.position, (nextVertex.transform.position - currentVertexFollowed.transform.position).normalized, linePoint1, (linePoint2 - linePoint1).normalized); return(intersectionPoint); }
/// <summary> /// Gets proper next folder's position. Used to spawn folders in available positions. /// </summary> /// <returns>KeyValuePair of vertices used to calculate spawn position and spawn position.</returns> /// <param name="currentVertexFollowed">Current vertex followed.</param> public KeyValuePair <VertexController[], Vector2> GetNextFolderPosition(VertexController currentVertexFollowed) { int currentVertexIndex = currentVertexFollowed.transform.GetSiblingIndex(); int nextVertexIndex = (currentVertexIndex + 1) % this.transform.childCount; VertexController nextVertex = this.transform.GetChild(nextVertexIndex).GetComponent <VertexController>(); int nextNextVertexIndex = (currentVertexIndex + 2) % this.transform.childCount; VertexController nextNextVertex = this.transform.GetChild(nextNextVertexIndex).GetComponent <VertexController>(); float availableSpaceScale = 0.5f; Vector2 availableSpaceVertex1 = currentVertexFollowed.transform.position + (nextVertex.transform.position - currentVertexFollowed.transform.position) * (1f - availableSpaceScale) / 3f; availableSpaceVertex1 += (Vector2)(nextNextVertex.transform.position - currentVertexFollowed.transform.position) * (1f - availableSpaceScale) / 3f; Vector2 availableSpaceVertex2 = nextVertex.transform.position + (currentVertexFollowed.transform.position - nextVertex.transform.position) * (1f - availableSpaceScale) / 3f; availableSpaceVertex2 += (Vector2)(nextNextVertex.transform.position - nextVertex.transform.position) * (1f - availableSpaceScale) / 3f; Vector2 availableSpaceVertex3 = nextNextVertex.transform.position + (currentVertexFollowed.transform.position - nextNextVertex.transform.position) * (1f - availableSpaceScale) / 3f; availableSpaceVertex3 += (Vector2)(nextVertex.transform.position - nextNextVertex.transform.position) * (1f - availableSpaceScale) / 3f; // Debug lines drawing, uncomment to debug this method //Debug.DrawLine(availableSpaceVertex1, availableSpaceVertex2, Color.white, 3f); //Debug.DrawLine(availableSpaceVertex2, availableSpaceVertex3, Color.white, 3f); //Debug.DrawLine(availableSpaceVertex3, availableSpaceVertex1, Color.white, 3f); VertexController[] returnList = { currentVertexFollowed, nextVertex, nextNextVertex }; return(new KeyValuePair <VertexController[], Vector2>(returnList, Math3d.GetRandomPointInsideTriangle(availableSpaceVertex1, availableSpaceVertex2, availableSpaceVertex3))); }
/// <summary> /// Provides raycast data based on where a SphereCast would contact the specified normal /// Raycasting downwards from a point along the controller's bottom sphere, based on the provided /// normal /// </summary> /// <param name="groundNormal">Normal of a triangle assumed to be directly below the controller</param> /// <param name="hit">Simulated SphereCast data</param> /// <returns>True if the raycast is successful</returns> private bool SimulateSphereCast(Vector3 groundNormal, out RaycastHit hit) { var groundAngle = Vector3.Angle(groundNormal, up) * Mathf.Deg2Rad; var secondaryOrigin = transform.position + up * Tolerance; if (!Mathf.Approximately(groundAngle, 0)) { var horizontal = Mathf.Sin(groundAngle) * radius; var vertical = (1.0f - Mathf.Cos(groundAngle)) * radius; // Retrieve a vector pointing up the slope var r2 = Vector3.Cross(groundNormal, down); var v2 = -Vector3.Cross(r2, groundNormal); secondaryOrigin += Math3d.ProjectVectorOnPlane(up, v2).normalized *horizontal + up * vertical; } if (Physics.Raycast(secondaryOrigin, down, out hit, Mathf.Infinity, Walkable)) { // Remove the tolerance from the distance travelled hit.distance -= Tolerance; return(true); } return(false); }
// Update is called once per frame void Update() { Vector3 direction = Math3d.ProjectVectorOnPlane(transform.up, (target.position - transform.position).normalized); if (Vector3.Distance(target.position, transform.position) < SightDistance && Vector3.Angle(direction, transform.forward) > SightAngle) { transform.rotation = Quaternion.RotateTowards(transform.rotation, Quaternion.LookRotation(direction), TurnSpeed * Time.deltaTime); if (!AnimatedMesh.GetComponent <Animation>().IsPlaying("turn")) { AnimatedMesh.GetComponent <Animation>().Play("turn"); GetComponent <AudioSource>().Play(); } } else { if (!AnimatedMesh.GetComponent <Animation>().isPlaying) { AnimatedMesh.GetComponent <Animation>().Play("idle"); } } windRotation = SuperMath.ClampAngle(windRotation + 360.0f * Time.deltaTime); WindTransform.Rotation = Quaternion.Euler(new Vector3(0, 0, windRotation)); }
protected override bool Compare(Fact solution, Fact fact) { return(fact is LineFact && solution is LineFact && Math3d.IsApproximatelyParallel(((LineFact)fact).Dir, ((LineFact)solution).Dir) && ((LineFact)fact).Distance + Math3d.vectorPrecission >= ((LineFact)solution).Distance); // && Mathf.Approximately(((LineFact) x).Distance, ((LineFact) y).Distance); }
public static IPoly RemoveDuplicateVerticies(IPoly poly) { List <Vector3> output = new List <Vector3>(); for (int i = 0; i < poly.Resolution; i++) { if (output.Count == 0) { output.Add(poly.GetPoint(i)); } else { Vector3 point = poly.GetPoint(i); Vector3 last = output[output.Count - 1]; if (!Math3d.Compare(point, last)) { output.Add(point); } } } if (Math3d.Compare(output[0], output[output.Count - 1])) { output.RemoveAt(0); } return(poly.Clone(output.ToArray())); }
public static bool IsEdgeIntersectingPolygon(IPoly polygon, Vector3 point1, Vector3 point2) { for (int i = 0; i < polygon.Resolution; i++) { Vector3 a = polygon.GetPoint(i); Vector3 b = polygon.GetPointWrapped(i + 1); if ((point1 - a).sqrMagnitude < 0.0001f) { continue; } if ((point1 - b).sqrMagnitude < 0.0001f) { continue; } if ((point2 - a).sqrMagnitude < 0.0001f) { continue; } if ((point2 - b).sqrMagnitude < 0.0001f) { continue; } if (Math3d.AreLineSegmentsCrossing(a, b, point1, point2)) { return(true); } } return(false); }
private void OnDrawGizmos() { Vector3 hitPointOnPlane = Math3d.ProjectPointOnPlane(_plane.up, _plane.position , transform.position); Debug.DrawLine(transform.position, hitPointOnPlane, Color.red); }
/* * Provides raycast data based on where a SphereCast would have contacted * the specified normal. * Raycasting downwards from a point along the controller's bottom sphere, * based on the provided normal. */ private bool SimulateSphereCast(CollisionSphere collisionSphere, Vector3 groundNormal, out RaycastHit hit) { float groundAngle = Vector3.Angle(groundNormal, playerView.Up) * Mathf.Deg2Rad; Vector3 secondaryOrigin = playerView.Position + (playerView.Up * settings.tolerance); if (!Mathf.Approximately(groundAngle, 0)) { float horizontal = Mathf.Sin(groundAngle) * collisionSphere.Radius; float vertical = (1f - Mathf.Cos(groundAngle)) * collisionSphere.Radius; Vector3 upslopeDirection = -CollisionMath.DownslopeDirection(groundNormal, playerView.Down); Vector3 horizontalDirection = Math3d.ProjectVectorOnPlane(playerView.Up, upslopeDirection).normalized; secondaryOrigin += horizontalDirection * horizontal + playerView.Up * vertical; } if (SphereCast(secondaryOrigin, settings.epsilon, playerView.Down, out hit)) { hit.distance -= settings.tolerance; return(true); } return(false); }
private bool GoldBodySlam() { float radius = controller.radius * 1.5f; Collider[] colliders = Physics.OverlapSphere(transform.position + controller.up * controller.height * 0.5f, radius); foreach (var col in colliders) { EnemyMachine machine = col.GetComponent <EnemyMachine>(); if (machine != null) { if (machine.GetStruck(Math3d.ProjectVectorOnPlane(controller.up, machine.transform.position - transform.position).normalized, 7.0f, 15.0f)) { sound.PlayImpact(); machine.MakeGold(); } } RollingBallGoldDestroy ball = col.GetComponent <RollingBallGoldDestroy>(); if (ball) { ball.BlowUp(); } } return(false); }
/// <summary> /// Attempt to get an object out of the dictionary, returning true if the object is in the dictinoary, and false otherwise /// The object will be returned to the out parameter t /// </summary> /// <param name="point"></param> /// <param name="direction"></param> /// <param name="t"></param> /// <returns></returns> public bool TryGet(Vector3 point, Vector3 direction, out T t) { point = Math3d.LinePlaneIntersection(point, direction, Vector3.zero, direction); direction = direction.normalized; PointDictionary <T> vectors; if (intersections.TryGet(point, out vectors)) { if (vectors.TryGet(direction, out t)) { return(true); } else if (vectors.TryGet(-direction, out t)) { return(true); } else { t = default(T); return(false); } } else { t = default(T); return(false); } }
public bool HeavyDamage(int damage, Vector3 origin) { if (status.Invincible()) { return(false); } if (StateCompare(MarioStates.Knockback) || StateCompare(MarioStates.KnockbackForwards) || StateCompare(MarioStates.TeleportIn) || StateCompare(MarioStates.TeleportOut)) { return(false); } Vector3 direction = Math3d.ProjectVectorOnPlane(controller.up, origin - transform.position).normalized; if (direction == Vector3.zero) { direction = lookDirection; } bool forward = Vector3.Angle(direction, lookDirection) < 90; if (Airborn()) { if (forward) { moveSpeed = -3.0f; currentState = MarioStates.AirKnockback; } else { moveSpeed = 3.0f; currentState = MarioStates.AirKnockbackForwards; } } else { if (forward) { currentState = MarioStates.Knockback; moveSpeed = -3.0f; } else { currentState = MarioStates.KnockbackForwards; moveSpeed = 3.0f; } } lookDirection = forward ? direction : -direction; SmartCamera.Shake(1.6f, 25.0f, 0.5f); sound.PlayTakeDamage(); Instantiate(TakeDamageEffect, transform.position + controller.up * controller.height * 0.6f, Quaternion.identity); status.TakeDamage(damage); return(true); }
private float WallCollisionAngle(Vector3 wallNormal, Vector3 direction) { Vector3 planarDirection = Math3d.ProjectVectorOnPlane(controller.up, direction); Vector3 planarWall = Math3d.ProjectVectorOnPlane(controller.up, wallNormal); return(Vector3.Angle(planarWall, planarDirection)); }
//Calculates the triangle points (counter clockwise) of a triangle placed over a unit quad. //This way a triangle is created which fits over a texture. private static void GenerateTriangle(out Vector4[] points, out Vector2[] uvs, float size, Quaternion rotation) { uvs = new Vector2[3]; //Calculate the horizontal displacement. float x = (1f / Mathf.Tan(60f * Mathf.Deg2Rad)) + 0.5f; //Calculate the vertical displacement. float y = (0.5f / Mathf.Tan(30f * Mathf.Deg2Rad)) + 0.5f; //Set the points, counter clockwise as an upright triangle, with the left //corner as point 0, right corner point 1, and top is point 2. Vector3[] localPoints = new Vector3[3]; localPoints[0] = new Vector3(-x, -0.5f) * size; localPoints[1] = new Vector3(x, -0.5f) * size; localPoints[2] = new Vector3(0, y) * size; //Set the uv's for (int i = 0; i < 3; i++) { float u = Math3d.NormalizeComplex(localPoints[i].x / size, -0.5f, 0.5f); float v = Math3d.NormalizeComplex(localPoints[i].y / size, -0.5f, 0.5f); uvs[i] = new Vector2(u, v); } //Rotate the points for (int i = 0; i < 3; i++) { localPoints[i] = rotation * localPoints[i]; } //Convert to vector4 points = Vector3ToVector4(localPoints); }
/// <summary> /// Provides raycast data based on where a SphereCast would contact the specified normal /// Raycasting downwards from a point along the controller's bottom sphere, based on the provided /// normal /// </summary> /// <param name="groundNormal">Normal of a triangle assumed to be directly below the controller</param> /// <param name="hit">Simulated SphereCast data</param> /// <returns>True if the raycast is successful</returns> private bool SimulateSphereCast(Vector3 groundNormal, out RaycastHit hit) { float groundAngle = Vector3.Angle(groundNormal, controller.up) * Mathf.Deg2Rad; Vector3 secondaryOrigin = controller.transform.position + controller.up * Tolerance; if (!Mathf.Approximately(groundAngle, 0)) { float horizontal = Mathf.Sin(groundAngle) * controller.radius; float vertical = (1.0f - Mathf.Cos(groundAngle)) * controller.radius; // Retrieve a vector pointing up the slope Vector3 r2 = Vector3.Cross(groundNormal, controller.down); Vector3 v2 = -Vector3.Cross(r2, groundNormal); secondaryOrigin += Math3d.ProjectVectorOnPlane(controller.up, v2).normalized *horizontal + controller.up * vertical; } if (Physics.Raycast(secondaryOrigin, controller.down, out hit, Mathf.Infinity, walkable, triggerInteraction)) { // Remove the tolerance from the distance travelled hit.distance -= Tolerance + TinyTolerance; return(true); } else { return(false); } }
public static Vector3 Circumcenter(Vector3 pt1, Vector3 pt2, Vector3 pt3) { // Get the perpendicular bisector of pt1, pt2 Vector3 v12 = pt2 - pt1; Vector3 v12normalized = v12.normalized; Vector3 v13 = pt3 - pt1; Vector3 v13normalized = v13.normalized; Vector3 v12perp = v13 - (Vector3.Dot(v13, v12normalized)) * v12normalized; v12perp.Normalize(); // Get the perpendicular bisector of pt1, pt3 Vector3 v13perp = v12 - (Vector3.Dot(v12, v13normalized)) * v13normalized; v13perp.Normalize(); Vector3 v12base = (pt1 + pt2) / 2; Vector3 v13base = (pt1 + pt3) / 2; // Compute intersection of the two bisectors Vector3 closest1, closest2; Math3d.ClosestPointsOnTwoLines(out closest1, out closest2, v12base, v12perp, v13base, v13perp); return((closest1 + closest2) / 2); }
// Update is called once per frame void FixedUpdate() { if (_isShoot) // neu da sut roi` { if (_ballRigidBody.velocity.sqrMagnitude <= 0.001f) // banh dung yen, ko can tinh' diem~ giao cat' { _ballTarget.position = Vector3.zero; } else { Vector3 intersection = Vector3.zero; if (Math3d.LinePlaneIntersection(out intersection, _ballRigidBody.position, (_ballRigidBody.velocity).normalized, _endPoint.up, _endPoint.position)) // tim giao diem giua~ mat phang gan` thu mon va duong di cua trai banh, { intersection.y = Mathf.Clamp(intersection.y, 0, 3f); intersection.x = Mathf.Clamp(intersection.x, -5f, 5f); _ballTarget.position = intersection; // set vi tri ballTarget la vi tri giao diem tim duoc } else { // ball target la diem~ co' x,y = x,y cua ball. z = z cua _endpoint, xem endpoint nhu mat phang~ gan thu~ mon, // thu mon se~ bay nguoi can fa' khi banh giao cat' voi' mat phang~ nay`, va _ballTarget chinh' la diem~ giao cat' // giua~ duong` di cua~ ball va mat phang~ nay Vector3 posTemp = _ball.position; posTemp.z = _endPoint.position.z; _ballTarget.position = posTemp; } } _previousPos = _ballRigidBody.position; _ballTargetPrevious.position = _previousPos; } else { } }
public void OnTrackablesUpdated() { if (rotations.Count >= smoothingFrames) { rotations.Dequeue(); positions.Dequeue(); } rotations.Enqueue(transform.rotation); positions.Enqueue(transform.position); Vector4 avgr = Vector4.zero; foreach (Quaternion singleRotation in rotations) { Math3d.AverageQuaternion(ref avgr, singleRotation, rotations.Peek(), rotations.Count); } Vector3 avgp = Vector3.zero; foreach (Vector3 singlePosition in positions) { avgp += singlePosition; } avgp /= positions.Count; smoothedRotation = new Quaternion(avgr.x, avgr.y, avgr.z, avgr.w); smoothedPosition = avgp; }
/// <summary> /// Splits the vertices and normals of each triangle in the mesh so that none are shared by any two triangles. /// </summary> /// <remarks>This achieves a flat-shaded lighting effect on the mesh.</remarks> /// <param name="mesh">Mesh.</param> public static void SplitVertices(this Mesh mesh) { var triangles = mesh.triangles; var vertices = mesh.vertices; var newVerts = new Vector3[triangles.Length]; var newNorms = new Vector3[triangles.Length]; for (int i = 0; i < triangles.Length; i++) { newVerts[i] = vertices[triangles[i]]; triangles[i] = i; } for (int i = 0; i < triangles.Length; i += 3) { Vector3 normal, point; Math3d.PlaneFrom3Points(out normal, out point, newVerts[triangles[i]], newVerts[triangles[i + 1]], newVerts[triangles[i + 2]]); newNorms[i] = normal; newNorms[i + 1] = normal; newNorms[i + 2] = normal; } mesh.vertices = newVerts; mesh.triangles = triangles; mesh.normals = newNorms; }
/// <summary> /// Expands a polygon by the specified distance. /// </summary> /// <param name="poly"></param> /// <param name="distance"></param> /// <param name="constructor"></param> /// <returns></returns> public static IPoly Expand(this IPoly poly, float distance, Func <IEnumerable <Vector3>, IPoly> constructor = null) { if (constructor == null) { constructor = poly.Clone; } Vector3[] points = new Vector3[poly.Resolution]; Vector3[] normals = new Vector3[poly.Resolution]; Vector3[] direction = new Vector3[poly.Resolution]; for (int i = 0; i < poly.Resolution; i++) { points[i] = poly.GetPoint(i); normals[i] = poly.GetSurfaceNormal(i).normalized; direction[i] = poly.GetPoint((i + 1) % poly.Resolution) - poly.GetPoint(i); } Vector3[] outputPoints = new Vector3[poly.Resolution]; for (int i = 0; i < poly.Resolution; i++) { Vector3 p0 = points[i] + normals[i] * distance; int iMinus = (i - 1 + poly.Resolution) % poly.Resolution; Vector3 l0 = points[iMinus] + normals[iMinus] * distance; outputPoints[i] = Math3d.LinePlaneIntersection(l0, direction[iMinus], p0, normals[i]); } return(constructor(outputPoints)); }
void Wander_SuperUpdate() { if (!IsGrounded(0.5f, true)) { currentState = BobOmbStates.Fall; return; } Vector3 direction = target.position - transform.position; direction = Math3d.ProjectVectorOnPlane(controller.up, direction); float distance = Vector3.Distance(target.position, transform.position); if (Vector3.Angle(direction, lookDirection) < FieldOfView && distance < SightDistance) { currentState = BobOmbStates.Chase; return; } moveSpeed = Mathf.MoveTowards(moveSpeed, WanderSpeed, 3.0f * Time.deltaTime); lookDirection = Quaternion.AngleAxis(30.0f * Time.deltaTime, controller.up) * lookDirection; moveDirection = moveSpeed * lookDirection; }
//Get an average (mean) from more then two quaternions (with two, slerp would be used). //Note: this only works if all the quaternions are relatively close together. //Usage: //-Cumulative is an external Vector4 which holds all the added x y z and w components. //-newRotation is the next rotation to be added to the average pool //-firstRotation is the first quaternion of the array to be averaged //-addAmount holds the total amount of quaternions which are currently added //This function returns the current average quaternion public static void AverageQuaternion(ref Vector4 cumulative, Quaternion newRotation, Quaternion firstRotation, int addAmount) { float w = 0.0f; float x = 0.0f; float y = 0.0f; float z = 0.0f; //Before we add the new rotation to the average (mean), we have to check whether the quaternion has to be inverted. Because //q and -q are the same rotation, but cannot be averaged, we have to make sure they are all the same. if (!Math3d.AreQuaternionsClose(newRotation, firstRotation)) { newRotation = Math3d.InverseSignQuaternion(newRotation); } //Average the values float addDet = 1f / (float)addAmount; cumulative.w += newRotation.w; w = cumulative.w * addDet; cumulative.x += newRotation.x; x = cumulative.x * addDet; cumulative.y += newRotation.y; y = cumulative.y * addDet; cumulative.z += newRotation.z; z = cumulative.z * addDet; //note: if speed is an issue, you can skip the normalization step //return NormalizeQuaternion(x, y, z, w); }
bool SlopeLimit() { //Calculate the angle with the current ground first to see if it is greater than slope limit Vector3 n = _currentGround.normal; float a = Vector3.Angle(n, transform.up); if (a > slopeLimit) { //Grab the direction that the controller is moving in Vector3 absoluteMoveDirection = Math3d.ProjectVectorOnPlane(n, transform.position - initialPosition); // Retrieve a vector pointing down the slope Vector3 r = Vector3.Cross(n, -transform.up); Vector3 v = Vector3.Cross(r, n); //Check the angle between the move direction of the controller and a vector down the slope. If less than 90 degrees then the player is moving down the slope return false float angle = Vector3.Angle(absoluteMoveDirection, v); if (angle <= 90.0f) { return(false); } // Calculate where to place the controller on the slope, or at the bottom, based on the desired movement distance Vector3 resolvedPosition = Math3d.ProjectPointOnLine(initialPosition, r, transform.position); Vector3 direction = Math3d.ProjectVectorOnPlane(n, resolvedPosition - transform.position); transform.position += direction; return(true); } return(false); }
public void SetTargetWithAngle(Vector3 point, float angle) { currentRadian = angle * Mathf.Deg2Rad; targetPoint = point; //GizmosHelper.DrawBox(point, Vector3.one * 0.2f, Color.yellow); Vector3 direction = point - firePoint.position; //if (Vector3.Angle(direction, transform.forward) > 10) //{ // // Haven't face the right direction. // projectileArc.gameObject.SetActive(false); // return; //} //else //{ // projectileArc.gameObject.SetActive(true); //} float yOffset = direction.y; direction = Math3d.ProjectVectorOnPlane(Vector3.up, direction); float distance = direction.magnitude; currentSpeed = ProjectileMath.CalculateLaunchSpeed(distance, yOffset, Physics.gravity.magnitude, angle * Mathf.Deg2Rad); projectileArc.UpdateArc(currentSpeed, distance, Physics.gravity.magnitude, currentRadian, direction, true); SetThrowPoint(direction, currentRadian * Mathf.Rad2Deg); }
//Setup all the papi lights. private void SetupPapiLights(ref List <SpriteLights.LightData> lightData, RunwayData runwayData, bool randomBrightness) { for (int side = 0; side < 2; side++) { if (runwayData.papiType[side] != PapiType.NONE) { //Calculate the offset direction. Vector3 lengthOffsetDir = Math3d.GetForwardVector(runwayData.rotation[side]); Vector3 sideOffsetDir = Math3d.GetRightVector(runwayData.rotation[side]); Vector3 lengthEdgeOffsetVec = Math3d.SetVectorLength(lengthOffsetDir, 337f); if ((runwayData.papiType[side] == PapiType.PAPIRIGHT) || (runwayData.papiType[side] == PapiType.PAPIBOTH)) { Vector3 startOffsetVec = lengthEdgeOffsetVec + Math3d.SetVectorLength(sideOffsetDir, (runwayData.width * 0.5f) + 15f); Vector3 startPosition = runwayData.thresholdPosition[side] + startOffsetVec; Vector3 currentPosition = startPosition; Vector3 sideOffsetVec = Math3d.SetVectorLength(sideOffsetDir, 9f); for (int i = 0; i < 4; i++) { SpriteLights.LightData data = new SpriteLights.LightData(); float angle = GetPapiAngle(i); data.position = currentPosition; data.rotation = runwayData.rotation[side] * Quaternion.Euler(Vector3.right * angle); lightData.Add(data); currentPosition += sideOffsetVec; } } if ((runwayData.papiType[side] == PapiType.PAPILEFT) || (runwayData.papiType[side] == PapiType.PAPIBOTH)) { sideOffsetDir *= -1; Vector3 startOffsetVec = lengthEdgeOffsetVec + Math3d.SetVectorLength(sideOffsetDir, (runwayData.width * 0.5f) + 15f); Vector3 startPosition = runwayData.thresholdPosition[side] + startOffsetVec; Vector3 currentPosition = startPosition; Vector3 sideOffsetVec = Math3d.SetVectorLength(sideOffsetDir, 9f); for (int i = 0; i < 4; i++) { SpriteLights.LightData data = new SpriteLights.LightData(); float angle = GetPapiAngle(i); data.position = currentPosition; data.rotation = runwayData.rotation[side] * Quaternion.Euler(Vector3.right * angle); lightData.Add(data); currentPosition += sideOffsetVec; } } } } }
static public void LookAt(Transform item, Vector3 target_pos) { item.localEulerAngles = new Vector3( item.localEulerAngles.x, item.localEulerAngles.y, Math3d.AngleFromUp(target_pos - item.position) ); }