您最多选择25个主题
主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
238 行
7.6 KiB
238 行
7.6 KiB
using System;
|
|
using Unity.UIWidgets.foundation;
|
|
using UnityEngine;
|
|
|
|
namespace Unity.UIWidgets.physics {
|
|
public class SpringDescription {
|
|
public SpringDescription(
|
|
float mass,
|
|
float stiffness,
|
|
float damping
|
|
) {
|
|
this.mass = mass;
|
|
this.stiffness = stiffness;
|
|
this.damping = damping;
|
|
}
|
|
|
|
public static SpringDescription withDampingRatio(
|
|
float mass,
|
|
float stiffness,
|
|
float ratio = 1.0f
|
|
) {
|
|
var damping = ratio * 2.0f * Mathf.Sqrt(mass * stiffness);
|
|
return new SpringDescription(mass, stiffness, damping);
|
|
}
|
|
|
|
public readonly float mass;
|
|
|
|
public readonly float stiffness;
|
|
|
|
public readonly float damping;
|
|
|
|
public override string ToString() {
|
|
return $"{this.GetType()}(mass {this.mass:F1}, stiffness: {this.stiffness:F1}, damping: {this.damping:F1})";
|
|
}
|
|
}
|
|
|
|
public enum SpringType {
|
|
criticallyDamped,
|
|
underDamped,
|
|
overDamped,
|
|
}
|
|
|
|
public class SpringSimulation : Simulation {
|
|
public SpringSimulation(
|
|
SpringDescription spring,
|
|
float start,
|
|
float end,
|
|
float velocity,
|
|
Tolerance tolerance = null
|
|
) : base(tolerance: tolerance) {
|
|
this._endPosition = end;
|
|
this._solution = _SpringSolution.create(spring, start - end, velocity);
|
|
}
|
|
|
|
protected readonly float _endPosition;
|
|
readonly _SpringSolution _solution;
|
|
|
|
public SpringType type {
|
|
get { return this._solution.type; }
|
|
}
|
|
|
|
public override float x(float time) {
|
|
return this._endPosition + this._solution.x(time);
|
|
}
|
|
|
|
public override float dx(float time) {
|
|
return this._solution.dx(time);
|
|
}
|
|
|
|
public override bool isDone(float time) {
|
|
return PhysicsUtils.nearZero(this._solution.x(time), this.tolerance.distance) &&
|
|
PhysicsUtils.nearZero(this._solution.dx(time), this.tolerance.velocity);
|
|
}
|
|
|
|
public override string ToString() {
|
|
return $"{this.GetType()}(end: {this._endPosition}, {this.type}";
|
|
}
|
|
}
|
|
|
|
public class ScrollSpringSimulation : SpringSimulation {
|
|
public ScrollSpringSimulation(
|
|
SpringDescription spring,
|
|
float start,
|
|
float end,
|
|
float velocity,
|
|
Tolerance tolerance = null
|
|
) : base(spring, start, end, velocity, tolerance: tolerance) {
|
|
}
|
|
|
|
public override float x(float time) {
|
|
return this.isDone(time) ? this._endPosition : base.x(time);
|
|
}
|
|
}
|
|
|
|
abstract class _SpringSolution {
|
|
internal static _SpringSolution create(
|
|
SpringDescription spring,
|
|
float initialPosition,
|
|
float initialVelocity
|
|
) {
|
|
D.assert(spring != null);
|
|
float cmk = spring.damping * spring.damping - 4 * spring.mass * spring.stiffness;
|
|
|
|
if (cmk == 0.0) {
|
|
return _CriticalSolution.create(spring, initialPosition, initialVelocity);
|
|
}
|
|
|
|
if (cmk > 0.0) {
|
|
return _OverdampedSolution.create(spring, initialPosition, initialVelocity);
|
|
}
|
|
|
|
return _UnderdampedSolution.create(spring, initialPosition, initialVelocity);
|
|
}
|
|
|
|
public abstract float x(float time);
|
|
public abstract float dx(float time);
|
|
public abstract SpringType type { get; }
|
|
}
|
|
|
|
class _CriticalSolution : _SpringSolution {
|
|
internal new static _CriticalSolution create(
|
|
SpringDescription spring,
|
|
float distance,
|
|
float velocity
|
|
) {
|
|
float r = -spring.damping / (2.0f * spring.mass);
|
|
float c1 = distance;
|
|
float c2 = velocity / (r * distance);
|
|
return new _CriticalSolution(r, c1, c2);
|
|
}
|
|
|
|
_CriticalSolution(
|
|
float r, float c1, float c2
|
|
) {
|
|
this._r = r;
|
|
this._c1 = c1;
|
|
this._c2 = c2;
|
|
}
|
|
|
|
readonly float _r, _c1, _c2;
|
|
|
|
public override float x(float time) {
|
|
return ((this._c1 + this._c2 * time) * Mathf.Pow((float) Math.E, this._r * time));
|
|
}
|
|
|
|
public override float dx(float time) {
|
|
float power = Mathf.Pow((float) Math.E, this._r * time);
|
|
return (this._r * (this._c1 + this._c2 * time) * power + this._c2 * power);
|
|
}
|
|
|
|
public override SpringType type {
|
|
get { return SpringType.criticallyDamped; }
|
|
}
|
|
}
|
|
|
|
class _OverdampedSolution : _SpringSolution {
|
|
internal new static _OverdampedSolution create(
|
|
SpringDescription spring,
|
|
float distance,
|
|
float velocity
|
|
) {
|
|
float cmk = spring.damping * spring.damping - 4 * spring.mass * spring.stiffness;
|
|
float r1 = (-spring.damping - Mathf.Sqrt(cmk)) / (2.0f * spring.mass);
|
|
float r2 = (-spring.damping + Mathf.Sqrt(cmk)) / (2.0f * spring.mass);
|
|
float c2 = (velocity - r1 * distance) / (r2 - r1);
|
|
float c1 = distance - c2;
|
|
return new _OverdampedSolution(r1, r2, c1, c2);
|
|
}
|
|
|
|
_OverdampedSolution(
|
|
float r1, float r2, float c1, float c2
|
|
) {
|
|
this._r1 = r1;
|
|
this._r2 = r2;
|
|
this._c1 = c1;
|
|
this._c2 = c2;
|
|
}
|
|
|
|
readonly float _r1, _r2, _c1, _c2;
|
|
|
|
public override float x(float time) {
|
|
return (this._c1 * Mathf.Pow((float) Math.E, this._r1 * time) +
|
|
this._c2 * Mathf.Pow((float) Math.E, this._r2 * time));
|
|
}
|
|
|
|
public override float dx(float time) {
|
|
return (this._c1 * this._r1 * Mathf.Pow((float) Math.E, this._r1 * time) +
|
|
this._c2 * this._r2 * Mathf.Pow((float) Math.E, this._r2 * time));
|
|
}
|
|
|
|
public override SpringType type {
|
|
get { return SpringType.overDamped; }
|
|
}
|
|
}
|
|
|
|
class _UnderdampedSolution : _SpringSolution {
|
|
internal new static _UnderdampedSolution create(
|
|
SpringDescription spring,
|
|
float distance,
|
|
float velocity
|
|
) {
|
|
float w = Mathf.Sqrt(4.0f * spring.mass * spring.stiffness -
|
|
spring.damping * spring.damping) / (2.0f * spring.mass);
|
|
float r = -(spring.damping / 2.0f * spring.mass);
|
|
float c1 = distance;
|
|
float c2 = (velocity - r * distance) / w;
|
|
return new _UnderdampedSolution(w, r, c1, c2);
|
|
}
|
|
|
|
_UnderdampedSolution(
|
|
float w, float r, float c1, float c2
|
|
) {
|
|
this._w = w;
|
|
this._r = r;
|
|
this._c1 = c1;
|
|
this._c2 = c2;
|
|
}
|
|
|
|
readonly float _w, _r, _c1, _c2;
|
|
|
|
public override float x(float time) {
|
|
return (Mathf.Pow((float) Math.E, this._r * time) *
|
|
(this._c1 * Mathf.Cos(this._w * time) + this._c2 * Mathf.Sin(this._w * time)));
|
|
}
|
|
|
|
public override float dx(float time) {
|
|
float power = Mathf.Pow((float) Math.E, this._r * time);
|
|
float cosine = Mathf.Cos(this._w * time);
|
|
float sine = Mathf.Sin(this._w * time);
|
|
return (power * (this._c2 * this._w * cosine - this._c1 * this._w * sine) +
|
|
this._r * power * (this._c2 * sine + this._c1 * cosine));
|
|
}
|
|
|
|
public override SpringType type {
|
|
get { return SpringType.underDamped; }
|
|
}
|
|
}
|
|
}
|