This commit is contained in:
blueloveTH 2024-05-13 16:43:40 +08:00
parent e19c2ccf96
commit acd81b6fae
6 changed files with 40 additions and 30 deletions

View File

@ -13,7 +13,7 @@ https://github.com/pocketpy/pocketpy/blob/main/include/typings/linalg.pyi
from typing import overload from typing import overload
from c import _StructLike, float_p from c import _StructLike, float_p
class vec2(_StructLike['vec2']): class vec2:
x: float x: float
y: float y: float
@ -168,8 +168,6 @@ class mat3x3(_StructLike['mat3x3']):
def inverse_transform_point(self, p: vec2) -> vec2: ... def inverse_transform_point(self, p: vec2) -> vec2: ...
def inverse_transform_vector(self, v: vec2) -> vec2: ... def inverse_transform_vector(self, v: vec2) -> vec2: ...
vec2_p = float_p
vec3_p = float_p
vec4_p = float_p vec4_p = float_p
mat3x3_p = float_p mat3x3_p = float_p

View File

@ -164,11 +164,12 @@ template<typename Ret, typename T, typename... Params>
/*****************************************************************/ /*****************************************************************/
#define PY_STRUCT_LIKE(wT) \ #define PY_STRUCT_LIKE(wT) \
static_assert(std::is_trivially_copyable<wT>::value); \ static_assert(std::is_trivially_copyable<wT>::value); \
static_assert(!is_sso_v<wT>); \
type->attr().set("__struct__", vm->True); \ type->attr().set("__struct__", vm->True); \
vm->bind_func(type, "fromstruct", 1, [](VM* vm, ArgsView args){ \ vm->bind_func(type, "fromstruct", 1, [](VM* vm, ArgsView args){ \
Struct& s = CAST(Struct&, args[0]); \ Struct& s = CAST(Struct&, args[0]); \
if(s.size != sizeof(wT)) vm->ValueError("size mismatch"); \ if(s.size != sizeof(wT)) vm->ValueError("size mismatch"); \
PyVar obj = vm->new_user_object<wT>(); \ PyVar obj = vm->new_user_object<wT>(); \
memcpy(&_CAST(wT&, obj), s.p, sizeof(wT)); \ memcpy(&_CAST(wT&, obj), s.p, sizeof(wT)); \
return obj; \ return obj; \
}, {}, BindType::STATICMETHOD); \ }, {}, BindType::STATICMETHOD); \

View File

@ -21,6 +21,7 @@ struct Vec2{
Vec2 operator-() const { return Vec2(-x, -y); } Vec2 operator-() const { return Vec2(-x, -y); }
bool operator==(const Vec2& v) const { return isclose(x, v.x) && isclose(y, v.y); } bool operator==(const Vec2& v) const { return isclose(x, v.x) && isclose(y, v.y); }
bool operator!=(const Vec2& v) const { return !isclose(x, v.x) || !isclose(y, v.y); } bool operator!=(const Vec2& v) const { return !isclose(x, v.x) || !isclose(y, v.y); }
float operator[](int i) const { return (&x)[i]; }
float dot(const Vec2& v) const { return x * v.x + y * v.y; } float dot(const Vec2& v) const { return x * v.x + y * v.y; }
float cross(const Vec2& v) const { return x * v.y - y * v.x; } float cross(const Vec2& v) const { return x * v.y - y * v.x; }
float length() const { return sqrtf(x * x + y * y); } float length() const { return sqrtf(x * x + y * y); }
@ -44,6 +45,7 @@ struct Vec3{
Vec3 operator-() const { return Vec3(-x, -y, -z); } Vec3 operator-() const { return Vec3(-x, -y, -z); }
bool operator==(const Vec3& v) const { return isclose(x, v.x) && isclose(y, v.y) && isclose(z, v.z); } bool operator==(const Vec3& v) const { return isclose(x, v.x) && isclose(y, v.y) && isclose(z, v.z); }
bool operator!=(const Vec3& v) const { return !isclose(x, v.x) || !isclose(y, v.y) || !isclose(z, v.z); } bool operator!=(const Vec3& v) const { return !isclose(x, v.x) || !isclose(y, v.y) || !isclose(z, v.z); }
float operator[](int i) const { return (&x)[i]; }
float dot(const Vec3& v) const { return x * v.x + y * v.y + z * v.z; } float dot(const Vec3& v) const { return x * v.x + y * v.y + z * v.z; }
Vec3 cross(const Vec3& v) const { return Vec3(y * v.z - z * v.y, z * v.x - x * v.z, x * v.y - y * v.x); } Vec3 cross(const Vec3& v) const { return Vec3(y * v.z - z * v.y, z * v.x - x * v.z, x * v.y - y * v.x); }
float length() const { return sqrtf(x * x + y * y + z * z); } float length() const { return sqrtf(x * x + y * y + z * z); }
@ -66,6 +68,7 @@ struct Vec4{
Vec4 operator-() const { return Vec4(-x, -y, -z, -w); } Vec4 operator-() const { return Vec4(-x, -y, -z, -w); }
bool operator==(const Vec4& v) const { return isclose(x, v.x) && isclose(y, v.y) && isclose(z, v.z) && isclose(w, v.w); } bool operator==(const Vec4& v) const { return isclose(x, v.x) && isclose(y, v.y) && isclose(z, v.z) && isclose(w, v.w); }
bool operator!=(const Vec4& v) const { return !isclose(x, v.x) || !isclose(y, v.y) || !isclose(z, v.z) || !isclose(w, v.w); } bool operator!=(const Vec4& v) const { return !isclose(x, v.x) || !isclose(y, v.y) || !isclose(z, v.z) || !isclose(w, v.w); }
float operator[](int i) const { return (&x)[i]; }
float dot(const Vec4& v) const { return x * v.x + y * v.y + z * v.z + w * v.w; } float dot(const Vec4& v) const { return x * v.x + y * v.y + z * v.z + w * v.w; }
float length() const { return sqrtf(x * x + y * y + z * z + w * w); } float length() const { return sqrtf(x * x + y * y + z * z + w * w); }
float length_squared() const { return x * x + y * y + z * z + w * w; } float length_squared() const { return x * x + y * y + z * z + w * w; }

View File

@ -1,7 +1,7 @@
from typing import overload from typing import overload
from c import _StructLike, float_p from c import _StructLike, float_p
class vec2(_StructLike['vec2']): class vec2:
x: float x: float
y: float y: float
@ -168,7 +168,5 @@ class mat3x3(_StructLike['mat3x3']):
def inverse_transform_point(self, p: vec2) -> vec2: ... def inverse_transform_point(self, p: vec2) -> vec2: ...
def inverse_transform_vector(self, v: vec2) -> vec2: ... def inverse_transform_vector(self, v: vec2) -> vec2: ...
vec2_p = float_p
vec3_p = float_p
vec4_p = float_p vec4_p = float_p
mat3x3_p = float_p mat3x3_p = float_p

View File

@ -31,21 +31,21 @@ namespace pkpy{
#define BIND_VEC_MUL_OP(D) \ #define BIND_VEC_MUL_OP(D) \
vm->bind__mul__(PK_OBJ_GET(Type, type), [](VM* vm, PyVar _0, PyVar _1){ \ vm->bind__mul__(PK_OBJ_GET(Type, type), [](VM* vm, PyVar _0, PyVar _1){ \
Vec##D& self = _CAST(Vec##D&, _0); \ Vec##D self = _CAST(Vec##D, _0); \
if(vm->is_user_type<Vec##D>(_1)){ \ if(vm->is_user_type<Vec##D>(_1)){ \
Vec##D& other = _CAST(Vec##D&, _1); \ Vec##D other = _CAST(Vec##D, _1); \
return VAR(self * other); \ return VAR(self * other); \
} \ } \
f64 other = CAST(f64, _1); \ f64 other = CAST(f64, _1); \
return VAR(self * other); \ return VAR(self * other); \
}); \ }); \
vm->bind_func(type, "__rmul__", 2, [](VM* vm, ArgsView args){ \ vm->bind_func(type, "__rmul__", 2, [](VM* vm, ArgsView args){ \
Vec##D& self = _CAST(Vec##D&, args[0]); \ Vec##D self = _CAST(Vec##D, args[0]); \
f64 other = CAST(f64, args[1]); \ f64 other = CAST(f64, args[1]); \
return VAR(self * other); \ return VAR(self * other); \
}); \ }); \
vm->bind__truediv__(PK_OBJ_GET(Type, type), [](VM* vm, PyVar _0, PyVar _1){ \ vm->bind__truediv__(PK_OBJ_GET(Type, type), [](VM* vm, PyVar _0, PyVar _1){ \
Vec##D& self = _CAST(Vec##D&, _0); \ Vec##D self = _CAST(Vec##D, _0); \
f64 other = CAST(f64, _1); \ f64 other = CAST(f64, _1); \
return VAR(self / other); \ return VAR(self / other); \
}); });
@ -59,6 +59,20 @@ namespace pkpy{
return VAR(v[i]); \ return VAR(v[i]); \
}); });
#define BIND_SSO_VEC_COMMON(D) \
vm->bind__eq__(PK_OBJ_GET(Type, type), [](VM* vm, PyVar _0, PyVar _1){ \
Vec##D self = _CAST(Vec##D, _0); \
if(!vm->is_user_type<Vec##D>(_1)) return vm->NotImplemented; \
Vec##D other = _CAST(Vec##D, _1); \
return VAR(self == other); \
}); \
vm->bind_func(type, "__getnewargs__", 1, [](VM* vm, ArgsView args){ \
Vec##D self = _CAST(Vec##D, args[0]); \
Tuple t(D); \
for(int i=0; i<D; i++) t[i] = VAR(self[i]); \
return VAR(std::move(t)); \
});
// https://github.com/Unity-Technologies/UnityCsReference/blob/master/Runtime/Export/Math/Vector2.cs#L289 // https://github.com/Unity-Technologies/UnityCsReference/blob/master/Runtime/Export/Math/Vector2.cs#L289
static Vec2 SmoothDamp(Vec2 current, Vec2 target, Vec2& currentVelocity, float smoothTime, float maxSpeed, float deltaTime) static Vec2 SmoothDamp(Vec2 current, Vec2 target, Vec2& currentVelocity, float smoothTime, float maxSpeed, float deltaTime)
{ {
@ -115,8 +129,6 @@ static Vec2 SmoothDamp(Vec2 current, Vec2 target, Vec2& currentVelocity, float s
} }
void Vec2::_register(VM* vm, PyVar mod, PyVar type){ void Vec2::_register(VM* vm, PyVar mod, PyVar type){
PY_STRUCT_LIKE(Vec2)
type->attr().set("ZERO", vm->new_user_object<Vec2>(0, 0)); type->attr().set("ZERO", vm->new_user_object<Vec2>(0, 0));
type->attr().set("ONE", vm->new_user_object<Vec2>(1, 1)); type->attr().set("ONE", vm->new_user_object<Vec2>(1, 1));
@ -176,11 +188,10 @@ static Vec2 SmoothDamp(Vec2 current, Vec2 target, Vec2& currentVelocity, float s
BIND_VEC_FUNCTION_0(2, length_squared) BIND_VEC_FUNCTION_0(2, length_squared)
BIND_VEC_FUNCTION_0(2, normalize) BIND_VEC_FUNCTION_0(2, normalize)
BIND_VEC_GETITEM(2) BIND_VEC_GETITEM(2)
BIND_SSO_VEC_COMMON(2)
} }
void Vec3::_register(VM* vm, PyVar mod, PyVar type){ void Vec3::_register(VM* vm, PyVar mod, PyVar type){
PY_STRUCT_LIKE(Vec3)
type->attr().set("ZERO", vm->new_user_object<Vec3>(0, 0, 0)); type->attr().set("ZERO", vm->new_user_object<Vec3>(0, 0, 0));
type->attr().set("ONE", vm->new_user_object<Vec3>(1, 1, 1)); type->attr().set("ONE", vm->new_user_object<Vec3>(1, 1, 1));
@ -212,6 +223,7 @@ static Vec2 SmoothDamp(Vec2 current, Vec2 target, Vec2& currentVelocity, float s
BIND_VEC_FUNCTION_0(3, length_squared) BIND_VEC_FUNCTION_0(3, length_squared)
BIND_VEC_FUNCTION_0(3, normalize) BIND_VEC_FUNCTION_0(3, normalize)
BIND_VEC_GETITEM(3) BIND_VEC_GETITEM(3)
BIND_SSO_VEC_COMMON(3)
} }
void Vec4::_register(VM* vm, PyVar mod, PyVar type){ void Vec4::_register(VM* vm, PyVar mod, PyVar type){
@ -539,14 +551,12 @@ static Vec2 SmoothDamp(Vec2 current, Vec2 target, Vec2& currentVelocity, float s
void add_module_linalg(VM* vm){ void add_module_linalg(VM* vm){
PyVar linalg = vm->new_module("linalg"); PyVar linalg = vm->new_module("linalg");
vm->register_user_class<Vec2>(linalg, "vec2", VM::tp_object, true); vm->register_user_class<Vec2>(linalg, "vec2", VM::tp_object);
vm->register_user_class<Vec3>(linalg, "vec3", VM::tp_object, true); vm->register_user_class<Vec3>(linalg, "vec3", VM::tp_object);
vm->register_user_class<Vec4>(linalg, "vec4", VM::tp_object, true); vm->register_user_class<Vec4>(linalg, "vec4", VM::tp_object, true);
vm->register_user_class<Mat3x3>(linalg, "mat3x3", VM::tp_object, true); vm->register_user_class<Mat3x3>(linalg, "mat3x3", VM::tp_object, true);
PyVar float_p = vm->_modules["c"]->attr("float_p"); PyVar float_p = vm->_modules["c"]->attr("float_p");
linalg->attr().set("vec2_p", float_p);
linalg->attr().set("vec3_p", float_p);
linalg->attr().set("vec4_p", float_p); linalg->attr().set("vec4_p", float_p);
linalg->attr().set("mat3x3_p", float_p); linalg->attr().set("mat3x3_p", float_p);
} }

View File

@ -31,11 +31,11 @@ assert str(static_test_vec2_int).startswith('vec2(')
# test copy # test copy
element_name_list = [e for e in dir(test_vec2) if e in 'x,y,z,w'] element_name_list = [e for e in dir(test_vec2) if e in 'x,y,z,w']
element_value_list = [getattr(test_vec2, attr) for attr in element_name_list] element_value_list = [getattr(test_vec2, attr) for attr in element_name_list]
copy_element_value_list = [getattr(test_vec2.copy(), attr) for attr in element_name_list] copy_element_value_list = [getattr(test_vec2, attr) for attr in element_name_list]
assert element_value_list == copy_element_value_list assert element_value_list == copy_element_value_list
# test rotate # test rotate
test_vec2_copy = test_vec2.copy() test_vec2_copy = test_vec2
radians = random.uniform(-10*math.pi, 10*math.pi) 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) == test_vec2_copy assert test_vec2.rotate(radians) == test_vec2_copy
@ -61,7 +61,7 @@ assert str(static_test_vec3_int).startswith('vec3(')
# test copy # test copy
element_name_list = ['x', 'y', 'z'] element_name_list = ['x', 'y', 'z']
element_value_list = [getattr(test_vec3, attr) for attr in element_name_list] element_value_list = [getattr(test_vec3, attr) for attr in element_name_list]
copy_element_value_list = [getattr(test_vec3.copy(), attr) for attr in element_name_list] copy_element_value_list = [getattr(test_vec3, attr) for attr in element_name_list]
assert element_value_list == copy_element_value_list assert element_value_list == copy_element_value_list
# test vec4-------------------------------------------------------------------- # test vec4--------------------------------------------------------------------
@ -377,8 +377,8 @@ def trs(t, radian, s):
[0.0, 0.0, 1.0]] [0.0, 0.0, 1.0]]
return elements return elements
test_vec2_copy = test_vec2.copy() test_vec2_copy = test_vec2
test_vec2_2_copy = test_vec2_2.copy() test_vec2_2_copy = test_vec2_2
test_vec2_list = [test_vec2_copy.x, test_vec2_copy.y] test_vec2_list = [test_vec2_copy.x, test_vec2_copy.y]
test_vec2_2_list = [test_vec2_2_copy.x, test_vec2_2_copy.y] test_vec2_2_list = [test_vec2_2_copy.x, test_vec2_2_copy.y]
@ -427,13 +427,13 @@ temp_vec2 = test_mat_copy._s()
# test transform_point # test transform_point
test_mat_copy = test_mat.copy() test_mat_copy = test_mat.copy()
test_mat_copy = test_mat.copy() test_mat_copy = test_mat.copy()
test_vec2_copy = test_vec2.copy() test_vec2_copy = test_vec2
temp_vec2 = test_mat_copy.transform_point(test_vec2_copy) temp_vec2 = test_mat_copy.transform_point(test_vec2_copy)
# test transform_vector # test transform_vector
test_mat_copy = test_mat.copy() test_mat_copy = test_mat.copy()
test_mat_copy = test_mat.copy() test_mat_copy = test_mat.copy()
test_vec2_copy = test_vec2.copy() test_vec2_copy = test_vec2
temp_vec2 = test_mat_copy.transform_vector(test_vec2_copy) temp_vec2 = test_mat_copy.transform_vector(test_vec2_copy)
# test inverse_transform_point # test inverse_transform_point
@ -442,11 +442,11 @@ assert test_mat_copy.inverse_transform_point(test_vec2_copy) == test_mat_copy.in
assert test_mat_copy.inverse_transform_vector(test_vec2_copy) == test_mat_copy.inverse().transform_vector(test_vec2_copy) assert test_mat_copy.inverse_transform_vector(test_vec2_copy) == test_mat_copy.inverse().transform_vector(test_vec2_copy)
import c import c
a = vec2(1, 2) a = vec4(1, 2, 3, 4)
b = a.tostruct() b = a.tostruct()
assert a.sizeof() == 8 assert a.sizeof() == 16
assert b.sizeof() == 8 assert b.sizeof() == 16
assert vec2.fromstruct(b) == a assert vec4.fromstruct(b) == a
val = vec2.angle(vec2(-1, 0), vec2(0, -1)) val = vec2.angle(vec2(-1, 0), vec2(0, -1))
assert 1.57 < val < 1.58 assert 1.57 < val < 1.58