From acd81b6faed3b684c17013b7b732713a5fa6e069 Mon Sep 17 00:00:00 2001 From: blueloveTH Date: Mon, 13 May 2024 16:43:40 +0800 Subject: [PATCH] some fix --- docs/modules/linalg.md | 4 +--- include/pocketpy/bindings.h | 3 ++- include/pocketpy/linalg.h | 3 +++ include/typings/linalg.pyi | 4 +--- src/linalg.cpp | 34 ++++++++++++++++++++++------------ tests/80_linalg.py | 22 +++++++++++----------- 6 files changed, 40 insertions(+), 30 deletions(-) diff --git a/docs/modules/linalg.md b/docs/modules/linalg.md index a53fb378..ec364413 100644 --- a/docs/modules/linalg.md +++ b/docs/modules/linalg.md @@ -13,7 +13,7 @@ https://github.com/pocketpy/pocketpy/blob/main/include/typings/linalg.pyi from typing import overload from c import _StructLike, float_p -class vec2(_StructLike['vec2']): +class vec2: x: float y: float @@ -168,8 +168,6 @@ class mat3x3(_StructLike['mat3x3']): def inverse_transform_point(self, p: vec2) -> vec2: ... def inverse_transform_vector(self, v: vec2) -> vec2: ... -vec2_p = float_p -vec3_p = float_p vec4_p = float_p mat3x3_p = float_p diff --git a/include/pocketpy/bindings.h b/include/pocketpy/bindings.h index b50aaf92..bb4c9d6f 100644 --- a/include/pocketpy/bindings.h +++ b/include/pocketpy/bindings.h @@ -164,11 +164,12 @@ template /*****************************************************************/ #define PY_STRUCT_LIKE(wT) \ static_assert(std::is_trivially_copyable::value); \ + static_assert(!is_sso_v); \ type->attr().set("__struct__", vm->True); \ vm->bind_func(type, "fromstruct", 1, [](VM* vm, ArgsView args){ \ Struct& s = CAST(Struct&, args[0]); \ if(s.size != sizeof(wT)) vm->ValueError("size mismatch"); \ - PyVar obj = vm->new_user_object(); \ + PyVar obj = vm->new_user_object(); \ memcpy(&_CAST(wT&, obj), s.p, sizeof(wT)); \ return obj; \ }, {}, BindType::STATICMETHOD); \ diff --git a/include/pocketpy/linalg.h b/include/pocketpy/linalg.h index ed7d2b59..f65743d7 100644 --- a/include/pocketpy/linalg.h +++ b/include/pocketpy/linalg.h @@ -21,6 +21,7 @@ struct Vec2{ 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); } + float operator[](int i) const { return (&x)[i]; } 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 length() const { return sqrtf(x * x + y * y); } @@ -44,6 +45,7 @@ struct Vec3{ 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); } + float operator[](int i) const { return (&x)[i]; } 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); } 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); } 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 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; } diff --git a/include/typings/linalg.pyi b/include/typings/linalg.pyi index 79ff5f58..7ed41ffa 100644 --- a/include/typings/linalg.pyi +++ b/include/typings/linalg.pyi @@ -1,7 +1,7 @@ from typing import overload from c import _StructLike, float_p -class vec2(_StructLike['vec2']): +class vec2: x: float y: float @@ -168,7 +168,5 @@ class mat3x3(_StructLike['mat3x3']): def inverse_transform_point(self, p: vec2) -> vec2: ... def inverse_transform_vector(self, v: vec2) -> vec2: ... -vec2_p = float_p -vec3_p = float_p vec4_p = float_p mat3x3_p = float_p diff --git a/src/linalg.cpp b/src/linalg.cpp index 6dbab5d6..fb7babae 100644 --- a/src/linalg.cpp +++ b/src/linalg.cpp @@ -31,21 +31,21 @@ namespace pkpy{ #define BIND_VEC_MUL_OP(D) \ 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(_1)){ \ - Vec##D& other = _CAST(Vec##D&, _1); \ + Vec##D other = _CAST(Vec##D, _1); \ return VAR(self * other); \ } \ f64 other = CAST(f64, _1); \ return VAR(self * other); \ }); \ 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]); \ return VAR(self * other); \ }); \ 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); \ return VAR(self / other); \ }); @@ -59,6 +59,20 @@ namespace pkpy{ 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(_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; iattr().set("ZERO", vm->new_user_object(0, 0)); type->attr().set("ONE", vm->new_user_object(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, normalize) BIND_VEC_GETITEM(2) + BIND_SSO_VEC_COMMON(2) } void Vec3::_register(VM* vm, PyVar mod, PyVar type){ - PY_STRUCT_LIKE(Vec3) - type->attr().set("ZERO", vm->new_user_object(0, 0, 0)); type->attr().set("ONE", vm->new_user_object(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, normalize) BIND_VEC_GETITEM(3) + BIND_SSO_VEC_COMMON(3) } 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){ PyVar linalg = vm->new_module("linalg"); - vm->register_user_class(linalg, "vec2", VM::tp_object, true); - vm->register_user_class(linalg, "vec3", VM::tp_object, true); + vm->register_user_class(linalg, "vec2", VM::tp_object); + vm->register_user_class(linalg, "vec3", VM::tp_object); vm->register_user_class(linalg, "vec4", VM::tp_object, true); vm->register_user_class(linalg, "mat3x3", VM::tp_object, true); 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("mat3x3_p", float_p); } diff --git a/tests/80_linalg.py b/tests/80_linalg.py index 1eaca454..d9295d3c 100644 --- a/tests/80_linalg.py +++ b/tests/80_linalg.py @@ -31,11 +31,11 @@ assert str(static_test_vec2_int).startswith('vec2(') # test copy 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] -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 # test rotate -test_vec2_copy = test_vec2.copy() +test_vec2_copy = test_vec2 radians = random.uniform(-10*math.pi, 10*math.pi) test_vec2_copy = rotated_vec2(test_vec2_copy, radians) assert test_vec2.rotate(radians) == test_vec2_copy @@ -61,7 +61,7 @@ assert str(static_test_vec3_int).startswith('vec3(') # test copy element_name_list = ['x', 'y', 'z'] 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 # test vec4-------------------------------------------------------------------- @@ -377,8 +377,8 @@ def trs(t, radian, s): [0.0, 0.0, 1.0]] return elements -test_vec2_copy = test_vec2.copy() -test_vec2_2_copy = test_vec2_2.copy() +test_vec2_copy = test_vec2 +test_vec2_2_copy = test_vec2_2 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] @@ -427,13 +427,13 @@ temp_vec2 = test_mat_copy._s() # test transform_point 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) # test transform_vector 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) # 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) import c -a = vec2(1, 2) +a = vec4(1, 2, 3, 4) b = a.tostruct() -assert a.sizeof() == 8 -assert b.sizeof() == 8 -assert vec2.fromstruct(b) == a +assert a.sizeof() == 16 +assert b.sizeof() == 16 +assert vec4.fromstruct(b) == a val = vec2.angle(vec2(-1, 0), vec2(0, -1)) assert 1.57 < val < 1.58