add vec2.smooth_damp

This commit is contained in:
blueloveTH 2024-01-11 00:35:19 +08:00
parent 8d9555312f
commit 1570e0f207
4 changed files with 56 additions and 20 deletions

View File

@ -27,7 +27,6 @@ class vec2(_StructLike['vec2']):
def length_squared(self) -> float: ... def length_squared(self) -> float: ...
def normalize(self) -> vec2: ... def normalize(self) -> vec2: ...
def rotate(self, radians: float) -> vec2: ... def rotate(self, radians: float) -> vec2: ...
def rotate_(self, radians: float) -> None: ...
@staticmethod @staticmethod
def angle(__from: vec2, __to: vec2) -> float: def angle(__from: vec2, __to: vec2) -> float:
@ -39,6 +38,10 @@ class vec2(_StructLike['vec2']):
+ if y axis is bottom to top, positive value means counter-clockwise + if y axis is bottom to top, positive value means counter-clockwise
""" """
@staticmethod
def smooth_damp(current: vec2, target: vec2, current_velocity: vec2, smooth_time: float, max_speed: float, delta_time: float) -> vec2:
...
class vec3(_StructLike['vec3']): class vec3(_StructLike['vec3']):
x: float x: float
y: float y: float

View File

@ -17,7 +17,6 @@ class vec2(_StructLike['vec2']):
def length_squared(self) -> float: ... def length_squared(self) -> float: ...
def normalize(self) -> vec2: ... def normalize(self) -> vec2: ...
def rotate(self, radians: float) -> vec2: ... def rotate(self, radians: float) -> vec2: ...
def rotate_(self, radians: float) -> None: ...
@staticmethod @staticmethod
def angle(__from: vec2, __to: vec2) -> float: def angle(__from: vec2, __to: vec2) -> float:
@ -29,6 +28,10 @@ class vec2(_StructLike['vec2']):
+ if y axis is bottom to top, positive value means counter-clockwise + if y axis is bottom to top, positive value means counter-clockwise
""" """
@staticmethod
def smooth_damp(current: vec2, target: vec2, current_velocity: vec2, smooth_time: float, max_speed: float, delta_time: float) -> vec2:
...
class vec3(_StructLike['vec3']): class vec3(_StructLike['vec3']):
x: float x: float
y: float y: float

View File

@ -41,6 +41,37 @@ namespace pkpy{
}); });
// https://github.com/Unity-Technologies/UnityCsReference/blob/master/Runtime/Export/Math/Mathf.cs#L309
static float SmoothDamp(float current, float target, float& currentVelocity, float smoothTime, float maxSpeed, float deltaTime)
{
// Based on Game Programming Gems 4 Chapter 1.10
smoothTime = std::max(0.0001F, smoothTime);
float omega = 2.0F / smoothTime;
float x = omega * deltaTime;
float exp = 1.0F / (1.0F + x + 0.48F * x * x + 0.235F * x * x * x);
float change = current - target;
float originalTo = target;
// Clamp maximum speed
float maxChange = maxSpeed * smoothTime;
change = std::clamp(change, -maxChange, maxChange);
target = current - change;
float temp = (currentVelocity + omega * change) * deltaTime;
currentVelocity = (currentVelocity - omega * temp) * exp;
float output = target + (change + temp) * exp;
// Prevent overshooting
if (originalTo - current > 0.0F == output > originalTo)
{
output = originalTo;
currentVelocity = (output - originalTo) / deltaTime;
}
return output;
}
void PyVec2::_register(VM* vm, PyObject* mod, PyObject* type){ void PyVec2::_register(VM* vm, PyObject* mod, PyObject* type){
PY_STRUCT_LIKE(PyVec2) PY_STRUCT_LIKE(PyVec2)
@ -55,6 +86,20 @@ namespace pkpy{
return VAR(Tuple({ VAR(self.x), VAR(self.y) })); return VAR(Tuple({ VAR(self.x), VAR(self.y) }));
}); });
// @staticmethod
vm->bind(type, "smooth_damp(current: vec2, target: vec2, current_velocity: vec2, smooth_time: float, max_speed: float, delta_time: float) -> vec2", [](VM* vm, ArgsView args){
PyVec2 current = CAST(PyVec2, args[0]);
PyVec2 target = CAST(PyVec2, args[1]);
PyVec2& current_velocity = CAST(PyVec2&, args[2]);
float smooth_time = CAST_F(args[3]);
float max_speed = CAST_F(args[4]);
float delta_time = CAST_F(args[5]);
float x = SmoothDamp(current.x, target.x, current_velocity.x, smooth_time, max_speed, delta_time);
float y = SmoothDamp(current.y, target.y, current_velocity.y, smooth_time, max_speed, delta_time);
return VAR(Vec2(x, y));
});
// @staticmethod
vm->bind(type, "angle(__from: vec2, __to: vec2) -> float", [](VM* vm, ArgsView args){ vm->bind(type, "angle(__from: vec2, __to: vec2) -> float", [](VM* vm, ArgsView args){
PyVec2 __from = CAST(PyVec2, args[0]); PyVec2 __from = CAST(PyVec2, args[0]);
PyVec2 __to = CAST(PyVec2, args[1]); PyVec2 __to = CAST(PyVec2, args[1]);
@ -85,18 +130,6 @@ namespace pkpy{
return VAR(self); return VAR(self);
}); });
vm->bind_method<1>(type, "rotate_", [](VM* vm, ArgsView args){
Vec2& self = _CAST(PyVec2&, args[0]);
float radian = CAST(f64, args[1]);
float cr = cosf(radian);
float sr = sinf(radian);
Mat3x3 rotate(cr, -sr, 0.0f,
sr, cr, 0.0f,
0.0f, 0.0f, 1.0f);
self = rotate.transform_vector(self);
return vm->None;
});
BIND_VEC_VEC_OP(2, __add__, +) BIND_VEC_VEC_OP(2, __add__, +)
BIND_VEC_VEC_OP(2, __sub__, -) BIND_VEC_VEC_OP(2, __sub__, -)
BIND_VEC_FLOAT_OP(2, __mul__, *) BIND_VEC_FLOAT_OP(2, __mul__, *)

View File

@ -40,12 +40,9 @@ radians = random.uniform(-10*math.pi, 10*math.pi)
test_vec2_copy = rotated_vec2(test_vec2_copy, radians) test_vec2_copy = rotated_vec2(test_vec2_copy, radians)
assert test_vec2.rotate(radians).__dict__ == test_vec2_copy.__dict__ assert test_vec2.rotate(radians).__dict__ == test_vec2_copy.__dict__
# test rotate_ # test smooth_damp
a = test_vec2.rotate(0.7) ret = vec2.smooth_damp(vec2(1, 2), vec2(3, 4), vec2(5, 6), 7, 8, 9)
assert a is not test_vec2 assert isinstance(ret, vec2)
b = test_vec2.rotate_(0.7)
assert b is None
assert a == test_vec2
# test vec3-------------------------------------------------------------------- # test vec3--------------------------------------------------------------------
# 生成随机测试目标 # 生成随机测试目标