1
0
blueloveTH 1 жил өмнө
parent
commit
acd81b6fae

+ 1 - 3
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
 

+ 2 - 1
include/pocketpy/bindings.h

@@ -164,11 +164,12 @@ template<typename Ret, typename T, typename... Params>
 /*****************************************************************/
 #define PY_STRUCT_LIKE(wT)   \
         static_assert(std::is_trivially_copyable<wT>::value);                       \
+        static_assert(!is_sso_v<wT>);                                               \
         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<wT>();                              \
+            PyVar obj = vm->new_user_object<wT>();                                  \
             memcpy(&_CAST(wT&, obj), s.p, sizeof(wT));                              \
             return obj;                                                             \
         }, {}, BindType::STATICMETHOD);                                             \

+ 3 - 0
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; }

+ 1 - 3
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

+ 22 - 12
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<Vec##D>(_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<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
 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){
-        PY_STRUCT_LIKE(Vec2)
-
         type->attr().set("ZERO", vm->new_user_object<Vec2>(0, 0));
         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, 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<Vec3>(0, 0, 0));
         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, 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<Vec2>(linalg, "vec2", VM::tp_object, true);
-    vm->register_user_class<Vec3>(linalg, "vec3", VM::tp_object, true);
+    vm->register_user_class<Vec2>(linalg, "vec2", VM::tp_object);
+    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<Mat3x3>(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);
 }

+ 11 - 11
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