您最多选择25个主题 主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
 
 
 
 
 
 

238 行
7.3 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 $"{GetType()}(mass {mass:F1}, stiffness: {stiffness:F1}, damping: {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) {
_endPosition = end;
_solution = _SpringSolution.create(spring, start - end, velocity);
}
protected readonly float _endPosition;
readonly _SpringSolution _solution;
public SpringType type {
get { return _solution.type; }
}
public override float x(float time) {
return _endPosition + _solution.x(time);
}
public override float dx(float time) {
return _solution.dx(time);
}
public override bool isDone(float time) {
return PhysicsUtils.nearZero(_solution.x(time), tolerance.distance) &&
PhysicsUtils.nearZero(_solution.dx(time), tolerance.velocity);
}
public override string ToString() {
return $"{GetType()}(end: {_endPosition}, {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 isDone(time) ? _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
) {
_r = r;
_c1 = c1;
_c2 = c2;
}
readonly float _r, _c1, _c2;
public override float x(float time) {
return ((_c1 + _c2 * time) * Mathf.Pow((float) Math.E, _r * time));
}
public override float dx(float time) {
float power = Mathf.Pow((float) Math.E, _r * time);
return (_r * (_c1 + _c2 * time) * power + _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
) {
_r1 = r1;
_r2 = r2;
_c1 = c1;
_c2 = c2;
}
readonly float _r1, _r2, _c1, _c2;
public override float x(float time) {
return (_c1 * Mathf.Pow((float) Math.E, _r1 * time) +
_c2 * Mathf.Pow((float) Math.E, _r2 * time));
}
public override float dx(float time) {
return (_c1 * _r1 * Mathf.Pow((float) Math.E, _r1 * time) +
_c2 * _r2 * Mathf.Pow((float) Math.E, _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
) {
_w = w;
_r = r;
_c1 = c1;
_c2 = c2;
}
readonly float _w, _r, _c1, _c2;
public override float x(float time) {
return (Mathf.Pow((float) Math.E, _r * time) *
(_c1 * Mathf.Cos(_w * time) + _c2 * Mathf.Sin(_w * time)));
}
public override float dx(float time) {
float power = Mathf.Pow((float) Math.E, _r * time);
float cosine = Mathf.Cos(_w * time);
float sine = Mathf.Sin(_w * time);
return (power * (_c2 * _w * cosine - _c1 * _w * sine) +
_r * power * (_c2 * sine + _c1 * cosine));
}
public override SpringType type {
get { return SpringType.underDamped; }
}
}
}