private FP GetPercent(FP distance, FP radius) { //(1-(distance/radius))^power-1 // TODO - PORT // FP percent = (FP)Math.Pow(1 - ((distance - radius) / radius), Power) - 1; FP percent = (FP)Math.Pow((1 - ((distance - radius) / radius)).AsFloat(), Power.AsFloat()) - 1; if (FP.IsNaN(percent)) { return(0f); } return(FPMath.Clamp(percent, 0f, 1f)); }
/// <summary> /// Creates a matrix which rotates around the given axis by the given angle. /// </summary> /// <param name="axis">The axis.</param> /// <param name="angle">The angle.</param> /// <param name="result">The resulting rotation matrix</param> public static void AxisAngle(ref FPVector axis, FP angle, out FPMatrix4x4 result) { // a: angle // x, y, z: unit vector for axis. // // Rotation matrix M can compute by using below equation. // // T T // M = uu + (cos a)( I-uu ) + (sin a)S // // Where: // // u = ( x, y, z ) // // [ 0 -z y ] // S = [ z 0 -x ] // [ -y x 0 ] // // [ 1 0 0 ] // I = [ 0 1 0 ] // [ 0 0 1 ] // // // [ xx+cosa*(1-xx) yx-cosa*yx-sina*z zx-cosa*xz+sina*y ] // M = [ xy-cosa*yx+sina*z yy+cosa(1-yy) yz-cosa*yz-sina*x ] // [ zx-cosa*zx-sina*y zy-cosa*zy+sina*x zz+cosa*(1-zz) ] // FP x = axis.x, y = axis.y, z = axis.z; FP sa = FPMath.Sin(angle), ca = FPMath.Cos(angle); FP xx = x * x, yy = y * y, zz = z * z; FP xy = x * y, xz = x * z, yz = y * z; result.M11 = xx + ca * (FP.One - xx); result.M12 = xy - ca * xy + sa * z; result.M13 = xz - ca * xz - sa * y; result.M14 = FP.Zero; result.M21 = xy - ca * xy - sa * z; result.M22 = yy + ca * (FP.One - yy); result.M23 = yz - ca * yz + sa * x; result.M24 = FP.Zero; result.M31 = xz - ca * xz + sa * y; result.M32 = yz - ca * yz - sa * x; result.M33 = zz + ca * (FP.One - zz); result.M34 = FP.Zero; result.M41 = FP.Zero; result.M42 = FP.Zero; result.M43 = FP.Zero; result.M44 = FP.One; }
public FP?IntersectsWithRay(FPVector2 origin, FPVector2 direction) { FP largestDistance = FPMath.Max(A.Position.x - origin.x, B.Position.x - origin.x) * 2f; LineSegment raySegment = new LineSegment(new Vertex(origin, 0), new Vertex(origin + (direction * largestDistance), 0)); FPVector2?intersection = FindIntersection(this, raySegment); FP? value = null; if (intersection != null) { value = FPVector2.Distance(origin, intersection.Value); } return(value); }
/// <summary> /// Called once before iteration starts. /// </summary> /// <param name="timestep">The 5simulation timestep</param> public override void PrepareForIteration(FP timestep) { effectiveMass = body1.invInertiaWorld + body2.invInertiaWorld; softnessOverDt = softness / timestep; effectiveMass.M11 += softnessOverDt; effectiveMass.M22 += softnessOverDt; effectiveMass.M33 += softnessOverDt; FPMatrix.Inverse(ref effectiveMass, out effectiveMass); FPMatrix orientationDifference; FPMatrix.Multiply(ref initialOrientation1, ref initialOrientation2, out orientationDifference); FPMatrix.Transpose(ref orientationDifference, out orientationDifference); FPMatrix q = orientationDifference * body2.invOrientation * body1.orientation; FPVector axis; FP x = q.M32 - q.M23; FP y = q.M13 - q.M31; FP z = q.M21 - q.M12; FP r = FPMath.Sqrt(x * x + y * y + z * z); FP t = q.M11 + q.M22 + q.M33; FP angle = FP.Atan2(r, t - 1); axis = new FPVector(x, y, z) * angle; if (r != FP.Zero) { axis = axis * (FP.One / r); } bias = axis * biasFactor * (-FP.One / timestep); // Apply previous frame solution as initial guess for satisfying the constraint. if (!body1.IsStatic) { body1.angularVelocity += FPVector.Transform(accumulatedImpulse, body1.invInertiaWorld); } if (!body2.IsStatic) { body2.angularVelocity += FPVector.Transform(-FP.One * accumulatedImpulse, body2.invInertiaWorld); } }
/// <summary> /// 改变朝向,改变forward的朝向跟摄像机的朝向一样 /// </summary> /// <param name="forward"></param> public void ChangeAvatarForward(FPVector toForward) { JoystickAngle = 90; if (AvatarForm == E_AvatarForm.PERSON_STATE) { _ufpTransformChildObj.ChangeForward(toForward); return; } RaycastHit _groundHit; _characterMotionObj.RayGroundInfo(out _groundHit); FPVector _fpNormal = _ufpTransformChildObj.ChangeVec3ToTSVec(_groundHit.normal); if (_groundHit.normal == Vector3.up) { _ufpTransformChildObj.ChangeForward(toForward); // _childObj.forward = toForward; JoystickAngle = 90; return; } else { FPVector left = FPVector.Cross(toForward, _fpNormal); //切线 FPVector newForward = FPVector.Cross(_fpNormal, left); if (_fpNormal == FPVector.zero) { Debug.Log("forward:::" + toForward); return; } FPQuaternion newRotation = FPQuaternion.LookRotation(newForward, _fpNormal); U_FPTransform ComMoveTransform = ComMoveFollowObj.GetFPTransform(); FPQuaternion comObject = new FPQuaternion(ComMoveTransform.rotation.x, ComMoveTransform.rotation.y, ComMoveTransform.rotation.z, ComMoveTransform.rotation.w); // ComMoveFollowObj.transform.rotation = newRotation; ComMoveTransform.SetRotation(newRotation); FPVector comForward = ComMoveTransform.forward; FPVector childForward = _ufpTransformChildObj.forward; FP DragAngle = FPVector.Angle(comForward, childForward); DragAngle = FPMath.Sign(FPVector.Cross(childForward, comForward).y) * DragAngle; ChangeAvaterForward(DragAngle); //改变对象的旋转数值 ComMoveTransform.SetRotation(comObject); //恢复摄像机原来的rotation数值 } }
public void EDITOR_Update() { if (!is_ready) { EDITOR_Prepare(); return; } if (this is IVariable && (this as IVariable).GetVariableName() != title) { EDITOR_Prepare(); return; } if (GraphEditor.snapToGrid) { if (!GraphEditor.is_drag) { position = FPMath.SnapVector2(position); } rects[this.id] = new Rect(FPMath.SnapVector2(this.position) + GraphEditor.scroll, this.size); } else { rects[this.id] = new Rect(this.position + GraphEditor.scroll, this.size); } Vector2 pos = rects[this.id].position; head_rect.position = pos; body_rect.position = new Vector2(pos.x, pos.y + head_height); icon_rect.position = new Vector2(pos.x + 5.0f, pos.y + 5.0f); if (has_subtitle) { if (invert_title) { title_rect.position = new Vector2(pos.x + ICON_SIZE_OFFSET, pos.y + 23.0f); subtitle_rect.position = new Vector2(pos.x + ICON_SIZE_OFFSET, pos.y + 6.0f); } else { title_rect.position = new Vector2(pos.x + ICON_SIZE_OFFSET, pos.y + 6.0f); subtitle_rect.position = new Vector2(pos.x + ICON_SIZE_OFFSET, pos.y + 23.0f); } } else { title_rect.position = new Vector2(pos.x + ICON_SIZE_OFFSET, pos.y + 15.0f); } }
/// <summary> /// Iteratively solve this constraint. /// </summary> public override void Iterate() { if (skipConstraint) { return; } FP jv = body1.linearVelocity * jacobian[0] + body1.angularVelocity * jacobian[1] + body2.linearVelocity * jacobian[2] + body2.angularVelocity * jacobian[3]; FP softnessScalar = accumulatedImpulse * softnessOverDt; FP lambda = -effectiveMass * (jv + bias + softnessScalar); if (behavior == DistanceBehavior.LimitMinimumDistance) { FP previousAccumulatedImpulse = accumulatedImpulse; accumulatedImpulse = FPMath.Max(accumulatedImpulse + lambda, 0); lambda = accumulatedImpulse - previousAccumulatedImpulse; } else if (behavior == DistanceBehavior.LimitMaximumDistance) { FP previousAccumulatedImpulse = accumulatedImpulse; accumulatedImpulse = FPMath.Min(accumulatedImpulse + lambda, 0); lambda = accumulatedImpulse - previousAccumulatedImpulse; } else { accumulatedImpulse += lambda; } if (!body1.isStatic) { body1.linearVelocity += body1.inverseMass * lambda * jacobian[0]; body1.angularVelocity += FPVector.Transform(lambda * jacobian[1], body1.invInertiaWorld); } if (!body2.isStatic) { body2.linearVelocity += body2.inverseMass * lambda * jacobian[2]; body2.angularVelocity += FPVector.Transform(lambda * jacobian[3], body2.invInertiaWorld); } }
/// <summary> /// Iteratively solve this constraint. /// </summary> public override void Iterate() { if (skipConstraint) { return; } FP jv = FPVector.Dot(ref body1.linearVelocity, ref jacobian[0]); jv += FPVector.Dot(ref body2.linearVelocity, ref jacobian[1]); FP softnessScalar = accumulatedImpulse * softnessOverDt; FP lambda = -effectiveMass * (jv + bias + softnessScalar); if (behavior == DistanceBehavior.LimitMinimumDistance) { FP previousAccumulatedImpulse = accumulatedImpulse; accumulatedImpulse = FPMath.Max(accumulatedImpulse + lambda, 0); lambda = accumulatedImpulse - previousAccumulatedImpulse; } else if (behavior == DistanceBehavior.LimitMaximumDistance) { FP previousAccumulatedImpulse = accumulatedImpulse; accumulatedImpulse = FPMath.Min(accumulatedImpulse + lambda, 0); lambda = accumulatedImpulse - previousAccumulatedImpulse; } else { accumulatedImpulse += lambda; } FPVector temp; if (!body1.isStatic) { FPVector.Multiply(ref jacobian[0], lambda * body1.inverseMass, out temp); FPVector.Add(ref temp, ref body1.linearVelocity, out body1.linearVelocity); } if (!body2.isStatic) { FPVector.Multiply(ref jacobian[1], lambda * body2.inverseMass, out temp); FPVector.Add(ref temp, ref body2.linearVelocity, out body2.linearVelocity); } }
void OnGUI() { scroll = EditorGUILayout.BeginScrollView(scroll); if (GUILayout.Button("SAVE")) { GraphEditor.asset.SaveData(); } if (GUILayout.Button("RESET POSITION")) { GraphEditor.scroll = Vector2.zero; } if (GUILayout.Button("GO TO CENTER")) { GraphEditor.scroll = new Vector2(0.0f, 10.0f) + FPMath.CenterOfPoints(GraphEditor.graph.nodes.Select(n => (-n.position - (n.size / 2.0f)) * GraphEditor.zoom + (GraphEditor.window.size / 2.0f) / GraphEditor.zoom).ToList()); } EditorGUILayout.EndScrollView(); }
public override void ApplyForce(FP dt, FP strength) { foreach (Body body in World.BodyList) { //TODO: Consider Force Type FP decayMultiplier = GetDecayMultiplier(body); if (decayMultiplier != 0) { FPVector2 forceVector; if (ForceType == ForceTypes.Point) { forceVector = body.Position - Position; } else { Direction.Normalize(); forceVector = Direction; if (forceVector.magnitude == 0) { forceVector = new FPVector2(0, 1); } } //TODO: Consider Divergence: //forceVector = Vector2.Transform(forceVector, Matrix.CreateRotationZ((MathHelper.Pi - MathHelper.Pi/2) * (FP)Randomize.NextFP())); // Calculate random Variation if (Variation != 0) { FP strengthVariation = KBEngine.FPRandom.value * FPMath.Clamp(Variation, 0, 1); forceVector.Normalize(); body.ApplyForce(forceVector * strength * decayMultiplier * strengthVariation); } else { forceVector.Normalize(); body.ApplyForce(forceVector * strength * decayMultiplier); } } } }
public static FPVector2 MoveTowards( FPVector2 current, FPVector2 target, pfloat maxDistanceDelta) { pfloat num1 = target.x - current.x; pfloat num2 = target.y - current.y; pfloat num4 = (num1 * num1 + num2 * num2); if (num4 == 0f || maxDistanceDelta >= 0f && num4 <= maxDistanceDelta * maxDistanceDelta) { return(target); } var num5 = FPMath.Sqrt(num4); return(new FPVector2(current.x + num1 / num5 * maxDistanceDelta, current.y + num2 / num5 * maxDistanceDelta)); }
public static FPQuaternion Euler(pfloat roll, pfloat pitch, pfloat yaw) { FPQuaternion quaternion; var num9 = roll * 0.5f; var num6 = FPMath.Sin(num9); var num5 = FPMath.Cos(num9); var num8 = pitch * 0.5f; var num4 = FPMath.Sin(num8); var num3 = FPMath.Cos(num8); var num7 = yaw * 0.5f; var num2 = FPMath.Sin(num7); var num = FPMath.Cos(num7); quaternion.x = ((num * num4) * num5) + ((num2 * num3) * num6); quaternion.y = ((num2 * num3) * num5) - ((num * num4) * num6); quaternion.z = ((num * num3) * num6) - ((num2 * num4) * num5); quaternion.w = ((num * num3) * num5) + ((num2 * num4) * num6); return(quaternion); }
/// <summary> /// Gets the axis aligned bounding box of the orientated shape. (Inlcuding all /// 'sub' shapes) /// </summary> /// <param name="orientation">The orientation of the shape.</param> /// <param name="box">The axis aligned bounding box of the shape.</param> public override void GetBoundingBox(ref FPMatrix orientation, out TSBBox box) { box.min = mInternalBBox.min; box.max = mInternalBBox.max; FPVector localHalfExtents = FP.Half * (box.max - box.min); FPVector localCenter = FP.Half * (box.max + box.min); FPVector center; FPVector.Transform(ref localCenter, ref orientation, out center); FPMatrix abs; FPMath.Absolute(ref orientation, out abs); FPVector temp; FPVector.Transform(ref localHalfExtents, ref abs, out temp); box.max = center + temp; box.min = center - temp; }
private static void DrawCircuit(float width, Vector2 p1, Vector2 p2, Vector2 t1, Vector2 t2) { bool inverted = p1.x < p2.x; if (inverted) { float center_y = FPMath.CenterOfPoints(p1, p2).y; float delta = Mathf.Min(Mathf.Abs(p1.x - p2.x) * 0.5f, 40.0f); Vector2 t1_pos = new Vector2(p1.x - delta, p1.y); Vector2 t2_pos = new Vector2(p2.x + delta, p2.y); Vector2 t1_center = new Vector2(t1_pos.x, center_y); Vector2 t2_center = new Vector2(t2_pos.x, center_y); Handles.DrawAAPolyLine(width, 6, p1, t1_pos, t1_center, t2_center, t2_pos, p2); } else { Handles.DrawAAPolyLine(width, 4, p1, t1, t2, p2); } }
/// <summary> /// Creates a gear shape with the specified radius and number of teeth. /// </summary> /// <param name="radius">The radius.</param> /// <param name="numberOfTeeth">The number of teeth.</param> /// <param name="tipPercentage">The tip percentage.</param> /// <param name="toothHeight">Height of the tooth.</param> /// <returns></returns> public static Vertices CreateGear(FP radius, int numberOfTeeth, FP tipPercentage, FP toothHeight) { Vertices vertices = new Vertices(); FP stepSize = FP.PiTimes2 / numberOfTeeth; tipPercentage /= 100f; FPMath.Clamp(tipPercentage, 0f, 1f); FP toothTipStepSize = (stepSize / 2f) * tipPercentage; FP toothAngleStepSize = (stepSize - (toothTipStepSize * 2f)) / 2f; for (int i = numberOfTeeth - 1; i >= 0; --i) { if (toothTipStepSize > 0f) { vertices.Add( new FPVector2(radius * FP.Cos(stepSize * i + toothAngleStepSize * 2f + toothTipStepSize), -radius * FP.Sin(stepSize * i + toothAngleStepSize * 2f + toothTipStepSize))); vertices.Add( new FPVector2((radius + toothHeight) * FP.Cos(stepSize * i + toothAngleStepSize + toothTipStepSize), -(radius + toothHeight) * FP.Sin(stepSize * i + toothAngleStepSize + toothTipStepSize))); } vertices.Add(new FPVector2((radius + toothHeight) * FP.Cos(stepSize * i + toothAngleStepSize), -(radius + toothHeight) * FP.Sin(stepSize * i + toothAngleStepSize))); vertices.Add(new FPVector2(radius * FP.Cos(stepSize * i), -radius * FP.Sin(stepSize * i))); } return(vertices); }
private Dictionary <Body, FPVector2> ApplyImpulse(FPVector2 pos, FP radius, FP force, FP maxForce, HashSet <Body> overlappingBodies) { Dictionary <Body, FPVector2> forces = new Dictionary <Body, FPVector2>(overlappingBodies.Count); foreach (Body overlappingBody in overlappingBodies) { if (IsActiveOn(overlappingBody)) { FP distance = FPVector2.Distance(pos, overlappingBody.Position); FP forcePercent = GetPercent(distance, radius); FPVector2 forceVector = pos - overlappingBody.Position; forceVector *= 1f / FP.Sqrt(forceVector.x * forceVector.x + forceVector.y * forceVector.y); forceVector *= FPMath.Min(force * forcePercent, maxForce); forceVector *= -1; overlappingBody.ApplyLinearImpulse(forceVector); forces.Add(overlappingBody, forceVector); } } return(forces); }
/// <summary> /// Transforms the bounding box into the space given by orientation and position. /// </summary> /// <param name="position"></param> /// <param name="orientation"></param> /// <param name="result"></param> internal void InverseTransform(ref FPVector position, ref FPMatrix orientation) { FPVector.Subtract(ref max, ref position, out max); FPVector.Subtract(ref min, ref position, out min); FPVector center; FPVector.Add(ref max, ref min, out center); center.x *= FP.Half; center.y *= FP.Half; center.z *= FP.Half; FPVector halfExtents; FPVector.Subtract(ref max, ref min, out halfExtents); halfExtents.x *= FP.Half; halfExtents.y *= FP.Half; halfExtents.z *= FP.Half; FPVector.TransposedTransform(ref center, ref orientation, out center); FPMatrix abs; FPMath.Absolute(ref orientation, out abs); FPVector.TransposedTransform(ref halfExtents, ref abs, out halfExtents); FPVector.Add(ref center, ref halfExtents, out max); FPVector.Subtract(ref center, ref halfExtents, out min); }
public void Update() { if (Target == null) { return; } // ChangeDirectionByDragging(); //if (_dragging && _directorToLeft && !_bTouchMouse) //左遥感 //{ // _rockerControl = ComMoveController.RockerControl.LeftControl; // _ufpTransform.RotateAround(_playerTransformObj.position, FPVector.up, FrameSyncManager.DeltaTime * RockerSpeed); // _ufpTransform.UpdateAllData(); // Debug.Log("_ufpTransform:::" + _ufpTransform.forward.ToVector()); // //transform.RotateAround(_childObj.position, Vector3.up, Time.deltaTime * RockerSpeed); // return; //} //else if (_dragging && _directorToRight && !_bTouchMouse) //右遥感 //{ // _rockerControl = ComMoveController.RockerControl.RightControl; // _ufpTransform.RotateAround(_playerTransformObj.position, FPVector.up, FrameSyncManager.DeltaTime * -RockerSpeed); // _ufpTransform.UpdateAllData(); // // transform.RotateAround(_childObj.position, Vector3.up, Time.deltaTime * -RockerSpeed); // return; //} //Debug.Log("_currentAngle:::" + _currentAngle + ",_childObj.eulerAngles.y::" + _childObj.eulerAngles.y // + ",transform.rotation::"+ transform.rotation); RaycastHit GroundHitInfo; RaycastHit BarrieHitrInfo; bool bGroundInfoFlag = _motionObj.RayGroundInfo(out GroundHitInfo); bool bBarrierInfoFlag = _motionObj.RayBarrierInfo(_childTransformObj.forward.ToVector(), out BarrieHitrInfo); FPVector fpGroundInfoNormal = FPVector.zero; if (bGroundInfoFlag) { fpGroundInfoNormal = GroundHitInfo.normal.ToFPVector(); } if (!_dragging && !_bTouchMouse && _bBeforeDragging) { _rockerControl = ComMoveController.RockerControl.None; return; } else if (!_dragging) { if (_bBeforeDragging) //在这里设置值,为了保证childObj的forward朝向跟摄像机的一致,防止先后差值 { _bBeforeDragging = false; return; } if (!bGroundInfoFlag) //在空中 { _rockerControl = ComMoveController.RockerControl.AirControl; if (_motionObj.bJumpFlag && false) //这是处理不跟随着对象跳跃的逻辑部分 { Distance = FPMath.Clamp(Distance - (Input.GetAxis("Mouse ScrollWheel") * MouseScrollWheelSensitivity), DistanceMin, DistanceMax); FPVector DataVec3 = new FPVector(_playerTransformObj.position.x, transform.position.y - Height, _playerTransformObj.position.z); _ufpTransform.position = (_ufpTransform.rotation * new FPVector(.0f, Height, -Distance)) + DataVec3; _ufpTransform.UpdateAllData(); return; } } else if (!bBarrierInfoFlag || !_motionObj.JudgetGroundSlope(BarrieHitrInfo.normal)) //有地面接触但前方没有障碍物 { if (!_motionObj.JudgetGroundSlope(GroundHitInfo.normal)) { _rockerControl = ComMoveController.RockerControl.OtherControl; _climbOtherWall = false; } else { if (_climbOtherWall && _beforeWallNormalVec3 != fpGroundInfoNormal) //表示从一面墙跨到另外一面墙 { _beforeGroundNormalVec3 = _beforeWallNormalVec3; _beforeWallNormalVec3 = fpGroundInfoNormal; } _rockerControl = ComMoveController.RockerControl.ClimbControl; } } else //有地面接触且前方有障碍物 { _rockerControl = ComMoveController.RockerControl.None; _beforeControl = ComMoveController.RockerControl.OtherControl; if (!_motionObj.JudgetGroundSlope(GroundHitInfo.normal)) //从地面跨到墙上的情况 { _beforeGroundNormalVec3 = fpGroundInfoNormal; } else //从一面墙跨到另外一面墙的情况 { _climbOtherWall = true; _beforeWallNormalVec3 = fpGroundInfoNormal; //设置这个变量的原因是:有可能检测到障碍物,但是玩家并没有跨越过去 } } } if (_rockerControl == RockerControl.AirControl) { Distance = FPMath.Clamp(Distance - (Input.GetAxis("Mouse ScrollWheel") * MouseScrollWheelSensitivity), DistanceMin, DistanceMax); _ufpTransform.position = (_ufpTransform.rotation * new FPVector(.0f, Height, -Distance)) + _playerTransformObj.position; _ufpTransform.UpdateAllData(); } else if (_rockerControl == RockerControl.OtherControl) { var quaternion = FPQuaternion.AngleAxis((_currentAngle) + _childTransformObj.transform.eulerAngles.y, FPVector.up); Distance = FPMath.Clamp(Distance - (Input.GetAxis("Mouse ScrollWheel") * MouseScrollWheelSensitivity), DistanceMin, DistanceMax); _ufpTransform.SetRotation(quaternion); // transform.rotation = quaternion; FPVector data = (_ufpTransform.rotation * new FPVector(.0f, Height, -Distance)); _ufpTransform.position = (_ufpTransform.rotation * new FPVector(.0f, Height, -Distance)) + _playerTransformObj.position; _ufpTransform.UpdatePosition(); //Debug.Log("data::"+ data.ToVector()+ ", _ufpTransform.position::::" + _ufpTransform.position.ToVector() // + ",transform::" + transform.position + "::_playerTransformObj.position:" + _playerTransformObj.position.ToVector() // + ",,name::" + _playerTransformObj.gameObject.name); _rotation = _ufpTransform.rotation; _ufpTransform.UpdateForward(); } else if (_rockerControl == RockerControl.ClimbControl) { Distance = FPMath.Clamp(Distance - (Input.GetAxis("Mouse ScrollWheel") * MouseScrollWheelSensitivity), DistanceMin, DistanceMax); var quaternion = FPQuaternion.AngleAxis((0) + transform.eulerAngles.y, FPVector.up); _ufpTransform.position = (_ufpTransform.rotation * new FPVector(.0f, Height, -Distance)) + _playerTransformObj.position; _ufpTransform.UpdateAllData(); FPVector climbForward = _ufpTransform.forward; if (_beforeControl == ComMoveController.RockerControl.OtherControl && _beforeGroundNormalVec3 != FPVector.zero) { FP tempAngle = FPVector.Angle(_beforeGroundNormalVec3, fpGroundInfoNormal); FPVector normal = FPVector.Cross(_beforeGroundNormalVec3, fpGroundInfoNormal); //叉乘求出法线向量 // num *= Mathf.Sign(Vector3.Dot(normal, info.transform.up)); //求法线向量与物体上方向向量点乘,结果为1或-1,修正旋转方向 climbForward = FPQuaternion.AngleAxis((90 - tempAngle), normal) * fpGroundInfoNormal; climbForward = -1 * climbForward; _finishWallNormalVec3 = climbForward; _beforeControl = ComMoveController.RockerControl.ClimbControl; } FP forwardAngle = FPVector.Angle(_finishWallNormalVec3, _ufpTransform.forward); if (forwardAngle != 0 && false) //处理摄像机角度偏转 { //1)调整摄像机的旋转角度 float direcFlag = -1; FPVector normalVec3 = FPVector.Cross(_finishWallNormalVec3, _ufpTransform.forward); //叉乘求出法线向量 direcFlag *= FPMath.Sign(Vector3.Dot(normalVec3.ToVector(), _ufpTransform.up.ToVector())); //求法线向量与物体上方向向量点乘,结果为1或-1,修正旋转方向 forwardAngle *= direcFlag; FPVector beforeForward = _ufpTransform.forward; FPVector forward = FPQuaternion.AngleAxis(forwardAngle, _ufpTransform.up) * _ufpTransform.forward; // Debug.Log("_ufpTransform.forward::" + _ufpTransform.forward.ToVector() + ",forward::" + forward.ToVector() // + "forwardAngle:::" + forwardAngle.AsFloat() + ",forward1111::" + forward); float quaternionSpeed = 0.003f; if (!_bTouchMouse) { quaternionSpeed = 0.03f; } if (beforeForward != forward) { Debug.Log("LookRotation(forward):::" + FPQuaternion.LookRotation(forward) + ",_rotation::" + _rotation + ",unity::" + Quaternion.LookRotation(forward.ToVector())); _rotation = FPQuaternion.Slerp(_rotation, FPQuaternion.LookRotation(forward), quaternionSpeed); _ufpTransform.SetRotation(_rotation); } // Debug.Log(",forward::"+ forward.ToVector() + ",_ufpTransform.forward::" + _ufpTransform.forward.ToVector()); //2)调整人物的旋转角度 if (!_climbOtherWall) // 这是从地面爬到墙得处理,如果是从一面墙爬到另外一面墙,镜头不做转换 { Debug.Log("beforeForward:::" + beforeForward.ToVector() + ",_ufpTransform.forward::" + _ufpTransform.forward.ToVector()); _offsetAngle = FPVector.Angle(beforeForward, _ufpTransform.forward) * direcFlag; _avatarObj.ChangeAvaterForward(_offsetAngle); } } } Debug.DrawLine(_ufpTransform.position.ToVector(), _playerTransformObj.transform.position, Color.red); if (_rockerControl == RockerControl.OtherControl || _rockerControl == RockerControl.ClimbControl) { //看是否有障碍物 FPVector directionTarget = (_ufpTransform.position - _ufpTransform.ChangeVec3ToTSVec(_rayPointObj.position)).normalized; FP distance = FPVector.Distance(_ufpTransform.position, _ufpTransform.ChangeVec3ToTSVec(_rayPointObj.position)); if (distance > Distance) { _ufpTransform.Translate(directionTarget * (distance - Distance)); _ufpTransform.UpdateRotationAndPosition(); } // Debug.DrawRay(_rayPointObj.position, directionTarget * Distance, Color.black); int layerMask = LayerMask.GetMask(Layers.Render); RaycastHit info; if (Physics.Raycast(_rayPointObj.position, directionTarget.ToVector(), out info, Distance.AsFloat(), layerMask)) //如果 { // Debug.Log("info.name::" + info.transform.name); if (info.transform.name != transform.name /*&& info.transform.tag != Tags.Ground*/) { _ufpTransform.SetPosition(_ufpTransform.ChangeVec3ToTSVec(info.point)); //transform.position = info.point; } if (_rockerControl == RockerControl.OtherControl) { _beforeControl = RockerControl.OtherControl; } } } }
public static FPVector3 Lerp(FPVector3 a, FPVector3 b, pfloat t) { t = FPMath.Clamp01(t); return(new FPVector3(a.x + (b.x - a.x) * t, a.y + (b.y - a.y) * t, a.z + (b.z - a.z) * t)); }
/// <summary> /// Activate the explosion at the specified position. /// </summary> /// <param name="pos">The position where the explosion happens </param> /// <param name="radius">The explosion radius </param> /// <param name="maxForce">The explosion force at the explosion point (then is inversely proportional to the square of the distance)</param> /// <returns>A list of bodies and the amount of force that was applied to them.</returns> public Dictionary <Fixture, FPVector2> Activate(FPVector2 pos, FP radius, FP maxForce) { AABB aabb; aabb.LowerBound = pos + new FPVector2(-radius, -radius); aabb.UpperBound = pos + new FPVector2(radius, radius); Fixture[] shapes = new Fixture[MaxShapes]; // More than 5 shapes in an explosion could be possible, but still strange. Fixture[] containedShapes = new Fixture[5]; bool exit = false; int shapeCount = 0; int containedShapeCount = 0; // Query the world for overlapping shapes. World.QueryAABB( fixture => { if (fixture.TestPoint(ref pos)) { if (IgnoreWhenInsideShape) { exit = true; return(false); } containedShapes[containedShapeCount++] = fixture; } else { shapes[shapeCount++] = fixture; } // Continue the query. return(true); }, ref aabb); if (exit) { return(new Dictionary <Fixture, FPVector2>()); } Dictionary <Fixture, FPVector2> exploded = new Dictionary <Fixture, FPVector2>(shapeCount + containedShapeCount); // Per shape max/min angles for now. FP[] vals = new FP[shapeCount * 2]; int valIndex = 0; for (int i = 0; i < shapeCount; ++i) { PolygonShape ps; CircleShape cs = shapes[i].Shape as CircleShape; if (cs != null) { // We create a "diamond" approximation of the circle Vertices v = new Vertices(); FPVector2 vec = FPVector2.zero + new FPVector2(cs.Radius, 0); v.Add(vec); vec = FPVector2.zero + new FPVector2(0, cs.Radius); v.Add(vec); vec = FPVector2.zero + new FPVector2(-cs.Radius, cs.Radius); v.Add(vec); vec = FPVector2.zero + new FPVector2(0, -cs.Radius); v.Add(vec); ps = new PolygonShape(v, 0); } else { ps = shapes[i].Shape as PolygonShape; } if ((shapes[i].Body.BodyType == BodyType.Dynamic) && ps != null) { FPVector2 toCentroid = shapes[i].Body.GetWorldPoint(ps.MassData.Centroid) - pos; FP angleToCentroid = FP.Atan2(toCentroid.y, toCentroid.x); FP min = FP.MaxValue; FP max = FP.MinValue; FP minAbsolute = 0.0f; FP maxAbsolute = 0.0f; for (int j = 0; j < ps.Vertices.Count; ++j) { FPVector2 toVertex = (shapes[i].Body.GetWorldPoint(ps.Vertices[j]) - pos); FP newAngle = FP.Atan2(toVertex.y, toVertex.x); FP diff = (newAngle - angleToCentroid); diff = (diff - FP.Pi) % (2 * FP.Pi); // the minus pi is important. It means cutoff for going other direction is at 180 deg where it needs to be if (diff < 0.0f) { diff += 2 * FP.Pi; // correction for not handling negs } diff -= FP.Pi; if (FP.Abs(diff) > FP.Pi) { continue; // Something's wrong, point not in shape but exists angle diff > 180 } if (diff > max) { max = diff; maxAbsolute = newAngle; } if (diff < min) { min = diff; minAbsolute = newAngle; } } vals[valIndex] = minAbsolute; ++valIndex; vals[valIndex] = maxAbsolute; ++valIndex; } } Array.Sort(vals, 0, valIndex, _rdc); _data.Clear(); bool rayMissed = true; for (int i = 0; i < valIndex; ++i) { Fixture fixture = null; FP midpt; int iplus = (i == valIndex - 1 ? 0 : i + 1); if (vals[i] == vals[iplus]) { continue; } if (i == valIndex - 1) { // the single edgecase midpt = (vals[0] + FP.PiTimes2 + vals[i]); } else { midpt = (vals[i + 1] + vals[i]); } midpt = midpt / 2; FPVector2 p1 = pos; FPVector2 p2 = radius * new FPVector2(FP.Cos(midpt), FP.Sin(midpt)) + pos; // RaycastOne bool hitClosest = false; World.RayCast((f, p, n, fr) => { Body body = f.Body; if (!IsActiveOn(body)) { return(0); } hitClosest = true; fixture = f; return(fr); }, p1, p2); //draws radius points if ((hitClosest) && (fixture.Body.BodyType == BodyType.Dynamic)) { if ((_data.Any()) && (_data.Last().Body == fixture.Body) && (!rayMissed)) { int laPos = _data.Count - 1; ShapeData la = _data[laPos]; la.Max = vals[iplus]; _data[laPos] = la; } else { // make new ShapeData d; d.Body = fixture.Body; d.Min = vals[i]; d.Max = vals[iplus]; _data.Add(d); } if ((_data.Count > 1) && (i == valIndex - 1) && (_data.Last().Body == _data.First().Body) && (_data.Last().Max == _data.First().Min)) { ShapeData fi = _data[0]; fi.Min = _data.Last().Min; _data.RemoveAt(_data.Count - 1); _data[0] = fi; while (_data.First().Min >= _data.First().Max) { fi.Min -= FP.PiTimes2; _data[0] = fi; } } int lastPos = _data.Count - 1; ShapeData last = _data[lastPos]; while ((_data.Count > 0) && (_data.Last().Min >= _data.Last().Max)) // just making sure min<max { last.Min = _data.Last().Min - FP.PiTimes2; _data[lastPos] = last; } rayMissed = false; } else { rayMissed = true; // raycast did not find a shape } } for (int i = 0; i < _data.Count; ++i) { if (!IsActiveOn(_data[i].Body)) { continue; } FP arclen = _data[i].Max - _data[i].Min; FP first = FPMath.Min(MaxEdgeOffset, EdgeRatio * arclen); int insertedRays = FP.Ceiling((((arclen - 2.0f * first) - (MinRays - 1) * MaxAngle) / MaxAngle)).AsInt(); if (insertedRays < 0) { insertedRays = 0; } FP offset = (arclen - first * 2.0f) / ((FP)MinRays + insertedRays - 1); //Note: This loop can go into infinite as it operates on FPs. //Added FPEquals with a large epsilon. for (FP j = _data[i].Min + first; j < _data[i].Max || MathUtils.FPEquals(j, _data[i].Max, 0.0001f); j += offset) { FPVector2 p1 = pos; FPVector2 p2 = pos + radius * new FPVector2(FP.Cos(j), FP.Sin(j)); FPVector2 hitpoint = FPVector2.zero; FP minlambda = FP.MaxValue; List <Fixture> fl = _data[i].Body.FixtureList; for (int x = 0; x < fl.Count; x++) { Fixture f = fl[x]; RayCastInput ri; ri.Point1 = p1; ri.Point2 = p2; ri.MaxFraction = 50f; RayCastOutput ro; if (f.RayCast(out ro, ref ri, 0)) { if (minlambda > ro.Fraction) { minlambda = ro.Fraction; hitpoint = ro.Fraction * p2 + (1 - ro.Fraction) * p1; } } // the force that is to be applied for this particular ray. // offset is angular coverage. lambda*length of segment is distance. FP impulse = (arclen / (MinRays + insertedRays)) * maxForce * 180.0f / FP.Pi * (1.0f - KBEngine.FPMath.Min(FP.One, minlambda)); // We Apply the impulse!!! FPVector2 vectImp = FPVector2.Dot(impulse * new FPVector2(FP.Cos(j), FP.Sin(j)), -ro.Normal) * new FPVector2(FP.Cos(j), FP.Sin(j)); _data[i].Body.ApplyLinearImpulse(ref vectImp, ref hitpoint); // We gather the fixtures for returning them if (exploded.ContainsKey(f)) { exploded[f] += vectImp; } else { exploded.Add(f, vectImp); } if (minlambda > 1.0f) { hitpoint = p2; } } } } // We check contained shapes for (int i = 0; i < containedShapeCount; ++i) { Fixture fix = containedShapes[i]; if (!IsActiveOn(fix.Body)) { continue; } FP impulse = MinRays * maxForce * 180.0f / FP.Pi; FPVector2 hitPoint; CircleShape circShape = fix.Shape as CircleShape; if (circShape != null) { hitPoint = fix.Body.GetWorldPoint(circShape.Position); } else { PolygonShape shape = fix.Shape as PolygonShape; hitPoint = fix.Body.GetWorldPoint(shape.MassData.Centroid); } FPVector2 vectImp = impulse * (hitPoint - pos); fix.Body.ApplyLinearImpulse(ref vectImp, ref hitPoint); if (!exploded.ContainsKey(fix)) { exploded.Add(fix, vectImp); } } return(exploded); }
public void DoFixedUpdate() { //WrapMode emulator if (overrideAnimatorUpdate) { animator.enabled = false; animator.Update((float)UFE.fixedDeltaTime); } if (currentAnimationData == null || currentAnimationData.clip == null) { return; } deltaDisplacement += animator.deltaPosition; currentAnimationData.secondsPlayed += FPMath.Abs(UFE.fixedDeltaTime * GetSpeed()); if (currentAnimationData.secondsPlayed > currentAnimationData.length) { currentAnimationData.secondsPlayed = currentAnimationData.length; } currentAnimationData.normalizedTime = currentAnimationData.secondsPlayed / currentAnimationData.length; if (currentAnimationData.secondsPlayed == currentAnimationData.length) { if (currentAnimationData.clip.wrapMode == WrapMode.Loop || currentAnimationData.clip.wrapMode == WrapMode.PingPong) { if (MecanimControl.OnAnimationLoop != null) { MecanimControl.OnAnimationLoop(currentAnimationData); } currentAnimationData.timesPlayed++; if (currentAnimationData.clip.wrapMode == WrapMode.Loop) { SetCurrentClipPosition(0); } if (currentAnimationData.clip.wrapMode == WrapMode.PingPong) { SetSpeed(currentAnimationData.clipName, -currentAnimationData.speed); SetCurrentClipPosition(0); } } else if (currentAnimationData.timesPlayed == 0) { if (MecanimControl.OnAnimationEnd != null) { MecanimControl.OnAnimationEnd(currentAnimationData); } currentAnimationData.timesPlayed = 1; if ((currentAnimationData.clip.wrapMode == WrapMode.Once || currentAnimationData.clip.wrapMode == WrapMode.Clamp) && alwaysPlay) { Play(defaultAnimation, currentMirror); } else if (!alwaysPlay) { SetSpeed(0); } } } }
public void Update() { if (_destVector != FPVector.zero) { float disData = Vector3.Distance(transform.position, _ufpTransform.position.ToVector()); FP fixDistan = MoveSpeed * Time.deltaTime; if (disData <= fixDistan) { UpdatePosition(_ufpTransform.position); UpdateRotation(_ufpTransform.rotation); // Debug.Log("======>arrived_____arrived_____arrived_____arrived_____arrived:::" + _ufpTransform.position); } else { transform.position += (_childObj.forward * fixDistan).ToVector(); // Debug.Log("======>_ufpTransform.position_OnLine:::"+ _ufpTransform.position); } } if (_destRoundData != 0) { FP angleData = _destRoundData - _roundData; FP _tempData = RotationSpeed * MoveSpeed * Time.deltaTime; //Debug.Log("======>angleData:::" + angleData.AsFloat() // + ",_tempData::" + _tempData.AsFloat() + ",_destRoundData::"+ _destRoundData); if (FPMath.Abs(angleData) <= FPMath.Abs(_tempData)) { UpdatePosition(_ufpTransform.position); UpdateRotation(_ufpTransform.rotation); _roundData = _destRoundData; //Debug.Log("======>arrived_____round_____arrived_____round_____arrived:::" + _ufpTransform.position // + ",childObj.forward::" + _childObj.forward + ",childObj.forward.toVector3::" + _childObj.forward.ToVector()); } else { transform.RotateAround(_center.ToVector(), transform.up, _tempData.AsFloat()); _roundData += _tempData; Debug.Log("======>_ufpTransform.round_round_OnLine:::" + _ufpTransform.position + ",_ufpTransform.position.toVector3::" + _ufpTransform.position // + ", ufpTransform.rotation:::" + _ufpTransform.rotation // + ",_ufpTransform.rotation.toVector()::" + _ufpTransform.rotation.ToQuaternion() + ",childObj.forward::" + _childObj.forward + ",childObj.forward.toVector3::" + _childObj.forward.ToVector()); } } RaycastHit hitInfo; bool bExitBarrier = (RayBarrierInfo(_childObj.forward.ToVector(), out hitInfo)); RaycastHit _groundHit; RaycastHit _hitInfo; if (bJumpFlag) //处理跳跃 { if (!bJumpArtFlag) //表示第一次开始跳跃 { if (!RayGroundInfo(out _groundHit, true)) { bJumpArtFlag = true; } } else { if (RayGroundInfo(out _groundHit, true)) { bJumpFlag = false; bJumpArtFlag = false; return; } } _jumpSpeed = _jumpSpeed - g * FrameSyncManager.DeltaTime; //垂直上的初速度随时间的改变 _ufpTransform.Translate(FPVector.up * _jumpSpeed * FrameSyncManager.DeltaTime, Space.World); //垂直上的运动 UpdateRotation(_ufpTransform.rotation); UpdatePosition(_ufpTransform.position); //transform.Translate(Vector3.up * _jumpSpeed * FrameSyncManager.DeltaTime, Space.World);//垂直上的运动 //if (_jumpSpeed < 0 && RayGroundInfo(out _groundHit, true)) //增加防止坠落的操作 //{ // transform/*.parent*/.position = new Vector3(transform/*.parent*/.position.x, _groundHit.point.y, transform/*.parent*/.position.z); // bJumpFlag = false; // bJumpArtFlag = false; // return; //} if (bMoveFlag) { _ufpTransform.Translate(_childObj.forward * MoveSpeed * FrameSyncManager.DeltaTime, Space.World);//水平上的运动 UpdateRotation(_ufpTransform.rotation); UpdatePosition(_ufpTransform.position); // transform.Translate(_childObj.forward.ToVector() * (MoveSpeed/** _frameEntityObj.SpeedRate*/).AsFloat() * Time.fixedDeltaTime, Space.World);//水平上的运动 } return; } else if (!RayGroundInfo(out _groundHit) && !RayBarrierInfo(_childObj.forward.ToVector(), out _hitInfo) && _bHasSpeed)//空中调整角度 { //Debug.Log("_childObj.forward.ToVector():::" + _childObj.forward.ToVector() // + ",,,,data__ufpTransform.up::" + _ufpTransform.up.ToVector() + ",,,,,fff::"+ _ufpTransform.forward.ToVector()); _verCurSpeed = _verCurSpeed - g * FrameSyncManager.DeltaTime; //垂直上的初速度随时间的改变 _ufpTransform.Translate(_childObj.forward * MoveSpeed * FrameSyncManager.DeltaTime, Space.World); //水平上的运动 _ufpTransform.Translate(FPVector.up * _verCurSpeed * FrameSyncManager.DeltaTime, Space.World); //垂直上的运动 UpdateRotation(_ufpTransform.rotation); UpdatePosition(_ufpTransform.position); // transform.Translate(_childObj.forward.ToVector() * (MoveSpeed/** _frameEntityObj.SpeedRate*/).AsFloat() * Time.fixedDeltaTime, Space.World);//水平上的运动 // transform.Translate(Vector3.up * _verCurSpeed.AsFloat() * Time.fixedDeltaTime, Space.World);//垂直上的运动 FP angleForward = FPVector.Angle(_ufpTransform.up, FPVector.up); if (angleForward == 0) { return; } FPVector normal = FPVector.Cross(_ufpTransform.up, FPVector.up); // int DirctData = FPMath.Sign(FPVector.Dot(normal, _ufpTransform.up)); float DirctData = Mathf.Sign(Vector3.Dot(normal.ToVector(), _ufpTransform.up.ToVector())); //Debug.Log(" angleForward::" + angleForward.AsFloat() + ",DirctData::"+ DirctData + ",_ufpTransform.up::"+ _ufpTransform.up + " ,"+ _ufpTransform.up.ToVector() + ",FPVector.up::"+ FPVector.up.ToVector() // + ",normal::" + normal + "," + normal.ToVector() + ", FPVector.Dot(normal, _ufpTransform.up)::" + FPVector.Dot(normal, _ufpTransform.up).AsFloat()); //if (DirctData == 0) DirctData = 1; angleForward = angleForward * DirctData; // Debug.Log(" FPMath.Sign(FPVector.Dot(normal, _ufpTransform.up)::" + FPVector.Dot(new FPVector(0,0,1), new FPVector(1, 0, 0))); FPVector forwardVec3 = FPQuaternion.AngleAxis(angleForward, normal) * _ufpTransform.up; FPVector forwardForward = FPQuaternion.AngleAxis(angleForward, normal) * _ufpTransform.forward; FPQuaternion qur = FPQuaternion.LookRotation(forwardForward, forwardVec3); //Debug.Log("forwardForward:::" + forwardForward.ToVector() + ",,forwardVec3::" + forwardVec3.ToVector() // + ",angleForward::"+ angleForward.AsFloat() // + ",_ufpTransform.up::" + _ufpTransform.up.ToVector() + ", _ufpTransform.forward::" + _ufpTransform.forward.ToVector() // + ",normal::" + normal.ToVector()); UpdateRotation(FPQuaternion.Slerp(_ufpTransform.rotation, qur, 0.1f)); //_ufpTransform.SetRotation(); //transform.rotation = FPQuaternion.Slerp(_ufpTransform.rotation, qur, 0.1f); //将玩家处于空中的状态事件发射出去 TriggerEvent(DefineEventId.PlayerInAirEvent); } else { FP angle = FPVector.Angle(FPVector.up, _ufpTransform.ChangeVec3ToTSVec(_groundHit.normal)); if (angle > SlopeAngle) { if (!bMoveFlag) { _ufpTransform.Translate(-1 * (FPVector.up) * g * FrameSyncManager.DeltaTime, Space.World); UpdateRotation(_ufpTransform.rotation); UpdatePosition(_ufpTransform.position); } } else { // transform.position = new Vector3(transform/*.parent*/.position.x, _groundHit.point.y, transform/*.parent*/.position.z); UpdateRotation(_ufpTransform.rotation); UpdatePosition(new FPVector(_ufpTransform.position.x, (FP)(_groundHit.point.y), _ufpTransform.position.z)); } } }
public static FPVector2 Lerp(FPVector2 a, FPVector2 b, pfloat t) { t = FPMath.Clamp01(t); return(new FPVector2(a.x + (b.x - a.x) * t, a.y + (b.y - a.y) * t)); }
public override FP ComputeSubmergedArea(ref FPVector2 normal, FP offset, ref Transform xf, out FPVector2 sc) { sc = FPVector2.zero; FPVector2 p = MathUtils.Mul(ref xf, Position); FP l = -(FPVector2.Dot(normal, p) - offset); if (l < -Radius + Settings.Epsilon) { //Completely dry return(0); } if (l > Radius) { //Completely wet sc = p; return(Settings.Pi * _2radius); } //Magic FP l2 = l * l; FP area = _2radius * (FP)((FPMath.Asin((l / Radius)) + FPMath.PiOver2) + l * FPMath.Sqrt(_2radius - l2)); // TODO - PORT //FP com = -2.0f / 3.0f * (FP)Math.Pow(_2radius - l2, 1.5f) / area; FP com = new FP(-2) / new FP(3) * (FP)Math.Pow((_2radius - l2).AsFloat(), 1.5f) / area; sc.x = p.x + normal.x * com; sc.y = p.y + normal.y * com; return(area); }
/// <summary> /// PrepareForIteration has to be called before <see cref="Iterate"/>. /// </summary> /// <param name="timestep">The timestep of the simulation.</param> public void PrepareForIteration(FP timestep) { FP dvx, dvy, dvz; dvx = (body2.angularVelocity.y * relativePos2.z) - (body2.angularVelocity.z * relativePos2.y) + body2.linearVelocity.x; dvy = (body2.angularVelocity.z * relativePos2.x) - (body2.angularVelocity.x * relativePos2.z) + body2.linearVelocity.y; dvz = (body2.angularVelocity.x * relativePos2.y) - (body2.angularVelocity.y * relativePos2.x) + body2.linearVelocity.z; dvx = dvx - (body1.angularVelocity.y * relativePos1.z) + (body1.angularVelocity.z * relativePos1.y) - body1.linearVelocity.x; dvy = dvy - (body1.angularVelocity.z * relativePos1.x) + (body1.angularVelocity.x * relativePos1.z) - body1.linearVelocity.y; dvz = dvz - (body1.angularVelocity.x * relativePos1.y) + (body1.angularVelocity.y * relativePos1.x) - body1.linearVelocity.z; FP kNormal = FP.Zero; FPVector rantra = FPVector.zero; if (!treatBody1AsStatic) { kNormal += body1.inverseMass; if (!body1IsMassPoint) { // JVector.Cross(ref relativePos1, ref normal, out rantra); rantra.x = (relativePos1.y * normal.z) - (relativePos1.z * normal.y); rantra.y = (relativePos1.z * normal.x) - (relativePos1.x * normal.z); rantra.z = (relativePos1.x * normal.y) - (relativePos1.y * normal.x); // JVector.Transform(ref rantra, ref body1.invInertiaWorld, out rantra); FP num0 = ((rantra.x * body1.invInertiaWorld.M11) + (rantra.y * body1.invInertiaWorld.M21)) + (rantra.z * body1.invInertiaWorld.M31); FP num1 = ((rantra.x * body1.invInertiaWorld.M12) + (rantra.y * body1.invInertiaWorld.M22)) + (rantra.z * body1.invInertiaWorld.M32); FP num2 = ((rantra.x * body1.invInertiaWorld.M13) + (rantra.y * body1.invInertiaWorld.M23)) + (rantra.z * body1.invInertiaWorld.M33); rantra.x = num0; rantra.y = num1; rantra.z = num2; //JVector.Cross(ref rantra, ref relativePos1, out rantra); num0 = (rantra.y * relativePos1.z) - (rantra.z * relativePos1.y); num1 = (rantra.z * relativePos1.x) - (rantra.x * relativePos1.z); num2 = (rantra.x * relativePos1.y) - (rantra.y * relativePos1.x); rantra.x = num0; rantra.y = num1; rantra.z = num2; } } FPVector rbntrb = FPVector.zero; if (!treatBody2AsStatic) { kNormal += body2.inverseMass; if (!body2IsMassPoint) { // JVector.Cross(ref relativePos1, ref normal, out rantra); rbntrb.x = (relativePos2.y * normal.z) - (relativePos2.z * normal.y); rbntrb.y = (relativePos2.z * normal.x) - (relativePos2.x * normal.z); rbntrb.z = (relativePos2.x * normal.y) - (relativePos2.y * normal.x); // JVector.Transform(ref rantra, ref body1.invInertiaWorld, out rantra); FP num0 = ((rbntrb.x * body2.invInertiaWorld.M11) + (rbntrb.y * body2.invInertiaWorld.M21)) + (rbntrb.z * body2.invInertiaWorld.M31); FP num1 = ((rbntrb.x * body2.invInertiaWorld.M12) + (rbntrb.y * body2.invInertiaWorld.M22)) + (rbntrb.z * body2.invInertiaWorld.M32); FP num2 = ((rbntrb.x * body2.invInertiaWorld.M13) + (rbntrb.y * body2.invInertiaWorld.M23)) + (rbntrb.z * body2.invInertiaWorld.M33); rbntrb.x = num0; rbntrb.y = num1; rbntrb.z = num2; //JVector.Cross(ref rantra, ref relativePos1, out rantra); num0 = (rbntrb.y * relativePos2.z) - (rbntrb.z * relativePos2.y); num1 = (rbntrb.z * relativePos2.x) - (rbntrb.x * relativePos2.z); num2 = (rbntrb.x * relativePos2.y) - (rbntrb.y * relativePos2.x); rbntrb.x = num0; rbntrb.y = num1; rbntrb.z = num2; } } if (!treatBody1AsStatic) { kNormal += rantra.x * normal.x + rantra.y * normal.y + rantra.z * normal.z; } if (!treatBody2AsStatic) { kNormal += rbntrb.x * normal.x + rbntrb.y * normal.y + rbntrb.z * normal.z; } massNormal = FP.One / kNormal; FP num = dvx * normal.x + dvy * normal.y + dvz * normal.z; tangent.x = dvx - normal.x * num; tangent.y = dvy - normal.y * num; tangent.z = dvz - normal.z * num; num = tangent.x * tangent.x + tangent.y * tangent.y + tangent.z * tangent.z; if (num != FP.Zero) { num = FP.Sqrt(num); tangent.x /= num; tangent.y /= num; tangent.z /= num; } FP kTangent = FP.Zero; if (treatBody1AsStatic) { rantra.MakeZero(); } else { kTangent += body1.inverseMass; if (!body1IsMassPoint) { // JVector.Cross(ref relativePos1, ref normal, out rantra); rantra.x = (relativePos1.y * tangent.z) - (relativePos1.z * tangent.y); rantra.y = (relativePos1.z * tangent.x) - (relativePos1.x * tangent.z); rantra.z = (relativePos1.x * tangent.y) - (relativePos1.y * tangent.x); // JVector.Transform(ref rantra, ref body1.invInertiaWorld, out rantra); FP num0 = ((rantra.x * body1.invInertiaWorld.M11) + (rantra.y * body1.invInertiaWorld.M21)) + (rantra.z * body1.invInertiaWorld.M31); FP num1 = ((rantra.x * body1.invInertiaWorld.M12) + (rantra.y * body1.invInertiaWorld.M22)) + (rantra.z * body1.invInertiaWorld.M32); FP num2 = ((rantra.x * body1.invInertiaWorld.M13) + (rantra.y * body1.invInertiaWorld.M23)) + (rantra.z * body1.invInertiaWorld.M33); rantra.x = num0; rantra.y = num1; rantra.z = num2; //JVector.Cross(ref rantra, ref relativePos1, out rantra); num0 = (rantra.y * relativePos1.z) - (rantra.z * relativePos1.y); num1 = (rantra.z * relativePos1.x) - (rantra.x * relativePos1.z); num2 = (rantra.x * relativePos1.y) - (rantra.y * relativePos1.x); rantra.x = num0; rantra.y = num1; rantra.z = num2; } } if (treatBody2AsStatic) { rbntrb.MakeZero(); } else { kTangent += body2.inverseMass; if (!body2IsMassPoint) { // JVector.Cross(ref relativePos1, ref normal, out rantra); rbntrb.x = (relativePos2.y * tangent.z) - (relativePos2.z * tangent.y); rbntrb.y = (relativePos2.z * tangent.x) - (relativePos2.x * tangent.z); rbntrb.z = (relativePos2.x * tangent.y) - (relativePos2.y * tangent.x); // JVector.Transform(ref rantra, ref body1.invInertiaWorld, out rantra); FP num0 = ((rbntrb.x * body2.invInertiaWorld.M11) + (rbntrb.y * body2.invInertiaWorld.M21)) + (rbntrb.z * body2.invInertiaWorld.M31); FP num1 = ((rbntrb.x * body2.invInertiaWorld.M12) + (rbntrb.y * body2.invInertiaWorld.M22)) + (rbntrb.z * body2.invInertiaWorld.M32); FP num2 = ((rbntrb.x * body2.invInertiaWorld.M13) + (rbntrb.y * body2.invInertiaWorld.M23)) + (rbntrb.z * body2.invInertiaWorld.M33); rbntrb.x = num0; rbntrb.y = num1; rbntrb.z = num2; //JVector.Cross(ref rantra, ref relativePos1, out rantra); num0 = (rbntrb.y * relativePos2.z) - (rbntrb.z * relativePos2.y); num1 = (rbntrb.z * relativePos2.x) - (rbntrb.x * relativePos2.z); num2 = (rbntrb.x * relativePos2.y) - (rbntrb.y * relativePos2.x); rbntrb.x = num0; rbntrb.y = num1; rbntrb.z = num2; } } if (!treatBody1AsStatic) { kTangent += FPVector.Dot(ref rantra, ref tangent); } if (!treatBody2AsStatic) { kTangent += FPVector.Dot(ref rbntrb, ref tangent); } massTangent = FP.One / kTangent; restitutionBias = lostSpeculativeBounce; speculativeVelocity = FP.Zero; FP relNormalVel = normal.x * dvx + normal.y * dvy + normal.z * dvz; //JVector.Dot(ref normal, ref dv); if (Penetration > settings.allowedPenetration) { restitutionBias = settings.bias * (FP.One / timestep) * FPMath.Max(FP.Zero, Penetration - settings.allowedPenetration); restitutionBias = FPMath.Clamp(restitutionBias, FP.Zero, settings.maximumBias); // body1IsMassPoint = body2IsMassPoint = false; } FP timeStepRatio = timestep / lastTimeStep; accumulatedNormalImpulse *= timeStepRatio; accumulatedTangentImpulse *= timeStepRatio; { // Static/Dynamic friction FP relTangentVel = -(tangent.x * dvx + tangent.y * dvy + tangent.z * dvz); FP tangentImpulse = massTangent * relTangentVel; FP maxTangentImpulse = -staticFriction * accumulatedNormalImpulse; if (tangentImpulse < maxTangentImpulse) { friction = dynamicFriction; } else { friction = staticFriction; } } FPVector impulse; // Simultaneos solving and restitution is simply not possible // so fake it a bit by just applying restitution impulse when there // is a new contact. /*if (relNormalVel < -FP.One && newContact) * { * restitutionBias = TSMath.Max(-restitution * relNormalVel, restitutionBias); * }*/ restitutionBias = FPMath.Max(-restitution * relNormalVel, restitutionBias); // Speculative Contacts! // if the penetration is negative (which means the bodies are not already in contact, but they will // be in the future) we store the current bounce bias in the variable 'lostSpeculativeBounce' // and apply it the next frame, when the speculative contact was already solved. if (penetration < -settings.allowedPenetration) { speculativeVelocity = penetration / timestep; lostSpeculativeBounce = restitutionBias; restitutionBias = FP.Zero; } else { lostSpeculativeBounce = FP.Zero; } impulse.x = normal.x * accumulatedNormalImpulse + tangent.x * accumulatedTangentImpulse; impulse.y = normal.y * accumulatedNormalImpulse + tangent.y * accumulatedTangentImpulse; impulse.z = normal.z * accumulatedNormalImpulse + tangent.z * accumulatedTangentImpulse; if (!treatBody1AsStatic) { body1.linearVelocity.x -= (impulse.x * body1.inverseMass); body1.linearVelocity.y -= (impulse.y * body1.inverseMass); body1.linearVelocity.z -= (impulse.z * body1.inverseMass); if (!body1IsMassPoint) { FP num0, num1, num2; num0 = relativePos1.y * impulse.z - relativePos1.z * impulse.y; num1 = relativePos1.z * impulse.x - relativePos1.x * impulse.z; num2 = relativePos1.x * impulse.y - relativePos1.y * impulse.x; FP num3 = (((num0 * body1.invInertiaWorld.M11) + (num1 * body1.invInertiaWorld.M21)) + (num2 * body1.invInertiaWorld.M31)); FP num4 = (((num0 * body1.invInertiaWorld.M12) + (num1 * body1.invInertiaWorld.M22)) + (num2 * body1.invInertiaWorld.M32)); FP num5 = (((num0 * body1.invInertiaWorld.M13) + (num1 * body1.invInertiaWorld.M23)) + (num2 * body1.invInertiaWorld.M33)); body1.angularVelocity.x -= num3; body1.angularVelocity.y -= num4; body1.angularVelocity.z -= num5; } } if (!treatBody2AsStatic) { body2.linearVelocity.x += (impulse.x * body2.inverseMass); body2.linearVelocity.y += (impulse.y * body2.inverseMass); body2.linearVelocity.z += (impulse.z * body2.inverseMass); if (!body2IsMassPoint) { FP num0, num1, num2; num0 = relativePos2.y * impulse.z - relativePos2.z * impulse.y; num1 = relativePos2.z * impulse.x - relativePos2.x * impulse.z; num2 = relativePos2.x * impulse.y - relativePos2.y * impulse.x; FP num3 = (((num0 * body2.invInertiaWorld.M11) + (num1 * body2.invInertiaWorld.M21)) + (num2 * body2.invInertiaWorld.M31)); FP num4 = (((num0 * body2.invInertiaWorld.M12) + (num1 * body2.invInertiaWorld.M22)) + (num2 * body2.invInertiaWorld.M32)); FP num5 = (((num0 * body2.invInertiaWorld.M13) + (num1 * body2.invInertiaWorld.M23)) + (num2 * body2.invInertiaWorld.M33)); body2.angularVelocity.x += num3; body2.angularVelocity.y += num4; body2.angularVelocity.z += num5; } } lastTimeStep = timestep; newContact = false; }
// Runtime Properties Required for instantiating a destroyed projectile (load/save state) //private int opProjectileLayer; //private int opProjectileMask; void Start() { gameObject.AddComponent <SphereCollider>(); if (mirror == 1) { directionVector.x = -1; } if (totalHits == int.MinValue) { totalHits = data.totalHits; } Fix64 angleRad = ((Fix64)data.directionAngle / 180) * FPMath.Pi; movement = ((FPMath.Sin(angleRad) * FPVector.up) + (FPMath.Cos(angleRad) * directionVector)) * data.speed; fpTransform.Translate(new FPVector(data._castingOffSet.x * -mirror, data._castingOffSet.y, data._castingOffSet.z)); // Create Blockable Area blockableArea = new BlockArea(); blockableArea = data.blockableArea; // Create Hurtbox hurtBox = new HurtBox(); hurtBox = data.hurtBox; // Create Hitbox hitBox = new HitBox(); hitBox.shape = hurtBox.shape; hitBox._rect = hurtBox._rect; hitBox.followXBounds = hurtBox.followXBounds; hitBox.followYBounds = hurtBox.followYBounds; hitBox._radius = hurtBox._radius; hitBox._offSet = hurtBox._offSet; hitBox.position = gameObject.transform; UpdateRenderer(); if (data.spaceBetweenHits == Sizes.Small) { spaceBetweenHits = .15; } else if (data.spaceBetweenHits == Sizes.Medium) { spaceBetweenHits = .2; } else if (data.spaceBetweenHits == Sizes.High) { spaceBetweenHits = .3; } // Create Hit data hit = new Hit(); hit.hitType = data.hitType; hit.spaceBetweenHits = data.spaceBetweenHits; hit.hitStrength = data.hitStrength; hit.hitStunType = HitStunType.Frames; hit._hitStunOnHit = data.hitStunOnHit; hit._hitStunOnBlock = data.hitStunOnBlock; hit._damageOnHit = data._damageOnHit; hit._damageOnBlock = data._damageOnBlock; hit.damageScaling = data.damageScaling; hit.damageType = data.damageType; hit.groundHit = data.groundHit; hit.airHit = data.airHit; hit.downHit = data.downHit; hit.overrideHitEffects = data.overrideHitEffects; hit.armorBreaker = data.armorBreaker; hit.hitEffects = data.hitEffects; hit.resetPreviousHorizontalPush = data.resetPreviousHorizontalPush; hit.resetPreviousVerticalPush = data.resetPreviousVerticalPush; hit.applyDifferentAirForce = data.applyDifferentAirForce; hit.applyDifferentBlockForce = data.applyDifferentBlockForce; hit._pushForce = data._pushForce; hit._pushForceAir = data._pushForceAir; hit._pushForceBlock = data._pushForceBlock; hit.pullEnemyIn = new PullIn(); hit.pullEnemyIn.enemyBodyPart = BodyPart.none; if (data.mirrorOn2PSide && mirror > 0) { transform.localEulerAngles = new Vector3(transform.localEulerAngles.x, transform.localEulerAngles.y + 180, transform.localEulerAngles.z); } }
/// <summary> /// Hull making. /// </summary> /// <remarks>Based/Completely from http://www.xbdev.net/physics/MinkowskiDifference/index.php /// I don't (100%) see why this should always work. /// </remarks> /// <param name="triangleList"></param> /// <param name="generationThreshold"></param> public virtual void MakeHull(ref List <FPVector> triangleList, int generationThreshold) { FP distanceThreshold = FP.Zero; if (generationThreshold < 0) { generationThreshold = 4; } Stack <ClipTriangle> activeTriList = new Stack <ClipTriangle>(); FPVector[] v = new FPVector[] // 6 Array { new FPVector(-1, 0, 0), new FPVector(1, 0, 0), new FPVector(0, -1, 0), new FPVector(0, 1, 0), new FPVector(0, 0, -1), new FPVector(0, 0, 1), }; int[,] kTriangleVerts = new int[8, 3] // 8 x 3 Array { { 5, 1, 3 }, { 4, 3, 1 }, { 3, 4, 0 }, { 0, 5, 3 }, { 5, 2, 1 }, { 4, 1, 2 }, { 2, 0, 4 }, { 0, 2, 5 } }; for (int i = 0; i < 8; i++) { ClipTriangle tri = new ClipTriangle(); tri.n1 = v[kTriangleVerts[i, 0]]; tri.n2 = v[kTriangleVerts[i, 1]]; tri.n3 = v[kTriangleVerts[i, 2]]; tri.generation = 0; activeTriList.Push(tri); } // surfaceTriList while (activeTriList.Count > 0) { ClipTriangle tri = activeTriList.Pop(); FPVector p1; SupportMapping(ref tri.n1, out p1); FPVector p2; SupportMapping(ref tri.n2, out p2); FPVector p3; SupportMapping(ref tri.n3, out p3); FP d1 = (p2 - p1).sqrMagnitude; FP d2 = (p3 - p2).sqrMagnitude; FP d3 = (p1 - p3).sqrMagnitude; if (FPMath.Max(FPMath.Max(d1, d2), d3) > distanceThreshold && tri.generation < generationThreshold) { ClipTriangle tri1 = new ClipTriangle(); ClipTriangle tri2 = new ClipTriangle(); ClipTriangle tri3 = new ClipTriangle(); ClipTriangle tri4 = new ClipTriangle(); tri1.generation = tri.generation + 1; tri2.generation = tri.generation + 1; tri3.generation = tri.generation + 1; tri4.generation = tri.generation + 1; tri1.n1 = tri.n1; tri2.n2 = tri.n2; tri3.n3 = tri.n3; FPVector n = FP.Half * (tri.n1 + tri.n2); n.Normalize(); tri1.n2 = n; tri2.n1 = n; tri4.n3 = n; n = FP.Half * (tri.n2 + tri.n3); n.Normalize(); tri2.n3 = n; tri3.n2 = n; tri4.n1 = n; n = FP.Half * (tri.n3 + tri.n1); n.Normalize(); tri1.n3 = n; tri3.n1 = n; tri4.n2 = n; activeTriList.Push(tri1); activeTriList.Push(tri2); activeTriList.Push(tri3); activeTriList.Push(tri4); } else { if (((p3 - p1) % (p2 - p1)).sqrMagnitude > FPMath.Epsilon) { triangleList.Add(p1); triangleList.Add(p2); triangleList.Add(p3); } } } }
private static void DefaultMoveCursorAction( this UFEScreen screen, Fix64 horizontalAxis, Fix64 verticalAxis, bool horizontalAxisDown, bool verticalAxisDown, bool confirmButtonDown, bool cancelButtonDown, AudioClip sound ) { bool axisDown = horizontalAxisDown || verticalAxisDown; //--------------------------------------------------------------------------------------------------------- // Retrieve the current selected GameObject. // If no GameObject is selected and the player press any button, select the first GameObject at the screen. //--------------------------------------------------------------------------------------------------------- GameObject currentGameObject = UFE.eventSystem.currentSelectedGameObject; if (currentGameObject == null && axisDown || confirmButtonDown || cancelButtonDown) { currentGameObject = screen.FindFirstSelectableGameObject(); } //--------------------------------------------------------------------------------------------------------- // Check if the current Selectable Object is a Slider //--------------------------------------------------------------------------------------------------------- Slider slider = currentGameObject != null?currentGameObject.GetComponent <Slider>() : null; //----------------------------------------------------------------------------------------------------- // If the current Selectable Object is a Slider, check if the user has pressed a button // in the same direction (horizontal / vertical) than the slider, change the slider value. // // If the current Selectable Object is not an Slider or if the user hasn't pressed a button // in the same direction (horizontal / vertical) than the slider, move the cursor //----------------------------------------------------------------------------------------------------- if (slider != null) { if (horizontalAxisDown && slider.direction == Slider.Direction.LeftToRight) { if (slider.wholeNumbers) { slider.value += FPMath.Sign(horizontalAxis); } else { slider.normalizedValue += FPMath.Sign(horizontalAxis) * UFEScreenExtensions.NormalizedSliderSpeed; } } else if (horizontalAxisDown && slider.direction == Slider.Direction.RightToLeft) { if (slider.wholeNumbers) { slider.value -= FPMath.Sign(horizontalAxis); } else { slider.normalizedValue -= FPMath.Sign(horizontalAxis) * UFEScreenExtensions.NormalizedSliderSpeed; } } else if (verticalAxisDown && slider.direction == Slider.Direction.BottomToTop) { if (slider.wholeNumbers) { slider.value += FPMath.Sign(verticalAxis); } else { slider.normalizedValue += FPMath.Sign(verticalAxis) * UFEScreenExtensions.NormalizedSliderSpeed; } } else if (verticalAxisDown && slider.direction == Slider.Direction.TopToBottom) { if (slider.wholeNumbers) { slider.value -= FPMath.Sign(verticalAxis); } else { slider.normalizedValue -= FPMath.Sign(verticalAxis) * UFEScreenExtensions.NormalizedSliderSpeed; } } else if (axisDown) { screen.MoveCursor(new Vector3((float)horizontalAxis, (float)verticalAxis), sound); } } else if (axisDown) { screen.MoveCursor(new Vector3((float)horizontalAxis, (float)verticalAxis), sound); } }
public static pfloat Lerp(pfloat a, pfloat b, pfloat t) { return(a + (b - a) * FPMath.Clamp01(t)); }
public static pfloat Clamp01(pfloat value) { return(FPMath.Clamp(value, 0f, 1f)); }