blueloveTH 2 years ago
parent
commit
764c699ce4
2 changed files with 432 additions and 87 deletions
  1. 351 87
      src/mat3x3.h
  2. 81 0
      src/mat3x3.pyi

+ 351 - 87
src/mat3x3.h

@@ -5,8 +5,35 @@
 
 
 namespace pkpy{
 namespace pkpy{
 
 
-struct Mat3x3{
-    static constexpr float kEpsilon = 1e-5f;
+static constexpr float kEpsilon = 1e-5f;
+inline static bool isclose(float a, float b){ return fabsf(a - b) < kEpsilon; }
+
+struct Vec2{
+    float x, y;
+    Vec2() : x(0.0f), y(0.0f) {}
+    Vec2(float x, float y) : x(x), y(y) {}
+    Vec2(const Vec2& v) : x(v.x), y(v.y) {}
+
+    Vec2 operator+(const Vec2& v) const { return Vec2(x + v.x, y + v.y); }
+    Vec2& operator+=(const Vec2& v) { x += v.x; y += v.y; return *this; }
+    Vec2 operator-(const Vec2& v) const { return Vec2(x - v.x, y - v.y); }
+    Vec2& operator-=(const Vec2& v) { x -= v.x; y -= v.y; return *this; }
+    Vec2 operator*(float s) const { return Vec2(x * s, y * s); }
+    Vec2& operator*=(float s) { x *= s; y *= s; return *this; }
+    Vec2 operator/(float s) const { return Vec2(x / s, y / s); }
+    Vec2& operator/=(float s) { x /= s; y /= s; return *this; }
+    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 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); }
+    float length_squared() const { return x * x + y * y; }
+    void normalize() { float l = length(); x /= l; y /= l; }
+    Vec2 normalized() const { float l = length(); return Vec2(x / l, y / l); }
+};
+
+struct Mat3x3{    
     union {
     union {
         struct {
         struct {
             float        _11, _12, _13;
             float        _11, _12, _13;
@@ -17,31 +44,79 @@ struct Mat3x3{
         float v[9];
         float v[9];
     };
     };
 
 
-    void set_zeros(){
-        for (int i=0; i<9; ++i) v[i] = 0.0f;
+    Mat3x3() {}
+    Mat3x3(float _11, float _12, float _13,
+           float _21, float _22, float _23,
+           float _31, float _32, float _33)
+        : _11(_11), _12(_12), _13(_13)
+        , _21(_21), _22(_22), _23(_23)
+        , _31(_31), _32(_32), _33(_33) {}
+
+    void set_zeros(){ for (int i=0; i<9; ++i) v[i] = 0.0f; }
+    void set_ones(){ for (int i=0; i<9; ++i) v[i] = 1.0f; }
+    void set_identity(){ set_zeros(); _11 = _22 = _33 = 1.0f; }
+
+    static Mat3x3 zeros(){
+        static Mat3x3 ret(0, 0, 0, 0, 0, 0, 0, 0, 0);
+        return ret;
     }
     }
 
 
-    void set_ones(){
-        for (int i=0; i<9; ++i) v[i] = 1.0f;
+    static Mat3x3 ones(){
+        static Mat3x3 ret(1, 1, 1, 1, 1, 1, 1, 1, 1);
+        return ret;
     }
     }
 
 
-    void set_identity(){
-        _11 = 1.0f;  _12 = 0.0f;  _13 = 0.0f;
-        _21 = 0.0f;  _22 = 1.0f;  _23 = 0.0f;
-        _31 = 0.0f;  _32 = 0.0f;  _33 = 1.0f;
+    static Mat3x3 identity(){
+        static Mat3x3 ret(1, 0, 0, 0, 1, 0, 0, 0, 1);
+        return ret;
     }
     }
 
 
-    void add_(const Mat3x3& other){ for (int i=0; i<9; ++i) v[i] += other.v[i]; }
-    void sub_(const Mat3x3& other){ for (int i=0; i<9; ++i) v[i] -= other.v[i]; }
-    void mul_(float s){ for (int i=0; i<9; ++i) v[i] *= s; }
-    void div_(float s){ for (int i=0; i<9; ++i) v[i] /= s; }
+    Mat3x3 operator+(const Mat3x3& other) const{ 
+        Mat3x3 ret;
+        for (int i=0; i<9; ++i) ret.v[i] = v[i] + other.v[i];
+        return ret;
+    }
 
 
-    Mat3x3 add(const Mat3x3& other) const{ Mat3x3 ret(*this); ret.add_(other); return ret; }
-    Mat3x3 sub(const Mat3x3& other) const{ Mat3x3 ret(*this); ret.sub_(other); return ret; }
-    Mat3x3 mul(float s) const{ Mat3x3 ret(*this); ret.mul_(s); return ret; }
-    Mat3x3 div(float s) const{ Mat3x3 ret(*this); ret.div_(s); return ret; }
+    Mat3x3 operator-(const Mat3x3& other) const{ 
+        Mat3x3 ret;
+        for (int i=0; i<9; ++i) ret.v[i] = v[i] - other.v[i];
+        return ret;
+    }
 
 
-    void matmul(const Mat3x3& other, Mat3x3& ret) const{
+    Mat3x3 operator*(float scalar) const{ 
+        Mat3x3 ret;
+        for (int i=0; i<9; ++i) ret.v[i] = v[i] * scalar;
+        return ret;
+    }
+
+    Mat3x3 operator/(float scalar) const{ 
+        Mat3x3 ret;
+        for (int i=0; i<9; ++i) ret.v[i] = v[i] / scalar;
+        return ret;
+    }
+
+    Mat3x3& operator+=(const Mat3x3& other){ 
+        for (int i=0; i<9; ++i) v[i] += other.v[i];
+        return *this;
+    }
+
+    Mat3x3& operator-=(const Mat3x3& other){ 
+        for (int i=0; i<9; ++i) v[i] -= other.v[i];
+        return *this;
+    }
+
+    Mat3x3& operator*=(float scalar){ 
+        for (int i=0; i<9; ++i) v[i] *= scalar;
+        return *this;
+    }
+
+    Mat3x3& operator/=(float scalar){ 
+        for (int i=0; i<9; ++i) v[i] /= scalar;
+        return *this;
+    }
+
+    Mat3x3 matmul(const Mat3x3& other) const{
+        Mat3x3 ret;
         ret._11 = _11 * other._11 + _12 * other._21 + _13 * other._31;
         ret._11 = _11 * other._11 + _12 * other._21 + _13 * other._31;
         ret._12 = _11 * other._12 + _12 * other._22 + _13 * other._32;
         ret._12 = _11 * other._12 + _12 * other._22 + _13 * other._32;
         ret._13 = _11 * other._13 + _12 * other._23 + _13 * other._33;
         ret._13 = _11 * other._13 + _12 * other._23 + _13 * other._33;
@@ -51,24 +126,19 @@ struct Mat3x3{
         ret._31 = _31 * other._11 + _32 * other._21 + _33 * other._31;
         ret._31 = _31 * other._11 + _32 * other._21 + _33 * other._31;
         ret._32 = _31 * other._12 + _32 * other._22 + _33 * other._32;
         ret._32 = _31 * other._12 + _32 * other._22 + _33 * other._32;
         ret._33 = _31 * other._13 + _32 * other._23 + _33 * other._33;
         ret._33 = _31 * other._13 + _32 * other._23 + _33 * other._33;
-    }
-
-    Mat3x3 matmul(const Mat3x3& other) const{
-        Mat3x3 ret;
-        matmul(other, ret);
         return ret;
         return ret;
     }
     }
 
 
     bool operator==(const Mat3x3& other) const{
     bool operator==(const Mat3x3& other) const{
         for (int i=0; i<9; ++i){
         for (int i=0; i<9; ++i){
-            if (v[i] != other.v[i]) return false;
+            if (!isclose(v[i], other.v[i])) return false;
         }
         }
         return true;
         return true;
     }
     }
 
 
     bool operator!=(const Mat3x3& other) const{
     bool operator!=(const Mat3x3& other) const{
         for (int i=0; i<9; ++i){
         for (int i=0; i<9; ++i){
-            if (v[i] != other.v[i]) return true;
+            if (!isclose(v[i], other.v[i])) return true;
         }
         }
         return false;
         return false;
     }
     }
@@ -102,48 +172,49 @@ struct Mat3x3{
         return true;
         return true;
     }
     }
 
 
-    bool is_identity() const{
-        return _11 == 1.0f && _12 == 0.0f && _13 == 0.0f
-            && _21 == 0.0f && _22 == 1.0f && _23 == 0.0f
-            && _31 == 0.0f && _32 == 0.0f && _33 == 1.0f;
-    }
-
-    /*************** affine transform (no bindings) ***************/
+    /*************** affine transform ***************/
     bool is_affine() const{
     bool is_affine() const{
         float det = _11 * _22 - _12 * _21;
         float det = _11 * _22 - _12 * _21;
         if(fabsf(det) < kEpsilon) return false;
         if(fabsf(det) < kEpsilon) return false;
         return _31 == 0.0f && _32 == 0.0f && _33 == 1.0f;
         return _31 == 0.0f && _32 == 0.0f && _33 == 1.0f;
     }
     }
 
 
-    void set_translate(float x, float y){
-        _11 = 1.0f;  _12 = 0.0f;  _13 = x;
-        _21 = 0.0f;  _22 = 1.0f;  _23 = y;
-        _31 = 0.0f;  _32 = 0.0f;  _33 = 1.0f;
+    static Mat3x3 translate(Vec2 v){
+        return Mat3x3(1.0f, 0.0f, v.x,
+                      0.0f, 1.0f, v.y,
+                      0.0f, 0.0f, 1.0f);
     }
     }
 
 
-    void set_rotate(float radian){
-        float c = cosf(radian);
-        float s = sinf(radian);
-        _11 = c;    _12 = -s;   _13 = 0.0f;
-        _21 = s;    _22 = c;    _23 = 0.0f;
-        _31 = 0.0f; _32 = 0.0f; _33 = 1.0f;
+    static Mat3x3 rotate(float radian){
+        float cr = cosf(radian);
+        float sr = sinf(radian);
+        return Mat3x3(cr,   -sr,  0.0f,
+                      sr,   cr,   0.0f,
+                      0.0f, 0.0f, 1.0f);
     }
     }
 
 
-    void set_scale(float sx, float sy){
-        _11 = sx;    _12 = 0.0f;  _13 = 0.0f;
-        _21 = 0.0f;  _22 = sy;    _23 = 0.0f;
-        _31 = 0.0f;  _32 = 0.0f;  _33 = 1.0f;
+    static Mat3x3 scale(Vec2 s){
+        return Mat3x3(s.x,  0.0f,   0.0f,
+                      0.0f, s.y,    0.0f,
+                      0.0f, 0.0f,   1.0f);
     }
     }
 
 
-    void set_trs(float x, float y, float radian, float sx, float sy){
-        float c = cosf(radian);
-        float s = sinf(radian);
-        _11 = sx * c;   _12 = -sy * s;  _13 = x;
-        _21 = sx * s;   _22 = sy * c;   _23 = y;
-        _31 = 0.0f;     _32 = 0.0f;     _33 = 1.0f;
+    static Mat3x3 trs(Vec2 t, float radian, Vec2 s){
+        float cr = cosf(radian);
+        float sr = sinf(radian);
+        return Mat3x3(s.x * cr,   -s.y * sr,  t.x,
+                      s.x * sr,   s.y * cr,   t.y,
+                      0.0f,       0.0f,       1.0f);
     }
     }
 
 
-    void inverse_affine(Mat3x3& ret) const{
+    static Mat3x3 ortho(float left, float right, float bottom, float top){
+        return Mat3x3(2.0f / (right - left),  0.0f,                       -(right + left) / (right - left),
+                      0.0f,                   2.0f / (top - bottom),      -(top + bottom) / (top - bottom),
+                      0.0f,                   0.0f,                       1.0f);
+    }
+
+    Mat3x3 inverse_affine() const{
+        Mat3x3 ret;
         float det = _11 * _22 - _12 * _21;
         float det = _11 * _22 - _12 * _21;
         float inv_det = 1.0f / det;
         float inv_det = 1.0f / det;
         ret._11 = _22 * inv_det;
         ret._11 = _22 * inv_det;
@@ -155,9 +226,11 @@ struct Mat3x3{
         ret._31 = 0.0f;
         ret._31 = 0.0f;
         ret._32 = 0.0f;
         ret._32 = 0.0f;
         ret._33 = 1.0f;
         ret._33 = 1.0f;
+        return ret;
     }
     }
 
 
-    void matmul_affine(const Mat3x3& other, Mat3x3& ret) const{
+    Mat3x3 matmul_affine(const Mat3x3& other) const{
+        Mat3x3 ret;
         ret._11 = _11 * other._11 + _12 * other._21;
         ret._11 = _11 * other._11 + _12 * other._21;
         ret._12 = _11 * other._12 + _12 * other._22;
         ret._12 = _11 * other._12 + _12 * other._22;
         ret._13 = _11 * other._13 + _12 * other._23 + _13;
         ret._13 = _11 * other._13 + _12 * other._23 + _13;
@@ -167,41 +240,142 @@ struct Mat3x3{
         ret._31 = 0.0f;
         ret._31 = 0.0f;
         ret._32 = 0.0f;
         ret._32 = 0.0f;
         ret._33 = 1.0f;
         ret._33 = 1.0f;
-    }
-
-    Mat3x3 matmul_affine(const Mat3x3& other) const{
-        Mat3x3 ret;
-        matmul_affine(other, ret);
         return ret;
         return ret;
     }
     }
 
 
-    float x() const { return _13; }
-    float y() const { return _23; }
+    Vec2 translation() const { return Vec2(_13, _23); }
     float rotation() const { return atan2f(_21, _11); }
     float rotation() const { return atan2f(_21, _11); }
-    float scale_x() const { return sqrtf(_11 * _11 + _21 * _21); }
-    float scale_y() const { return sqrtf(_12 * _12 + _22 * _22); }
-
-    void transform_point(float& x, float& y) const {
-        float tx = x;
-        float ty = y;
-        x = _11 * tx + _12 * ty + _13;
-        y = _21 * tx + _22 * ty + _23;
+    Vec2 scale() const {
+        return Vec2(
+            sqrtf(_11 * _11 + _21 * _21),
+            sqrtf(_12 * _12 + _22 * _22)
+        );
     }
     }
 
 
-    void transform_vector(float& x, float& y) const {
-        float tx = x;
-        float ty = y;
-        x = _11 * tx + _12 * ty;
-        y = _21 * tx + _22 * ty;
+    Vec2 transform_point(Vec2 v) const {
+        return Vec2(_11 * v.x + _12 * v.y + _13, _21 * v.x + _22 * v.y + _23);
     }
     }
 
 
-    void set_ortho(float left, float right, float bottom, float top){
-        _11 = 2.0f / (right - left);    _12 = 0.0f;                      _13 = -(right + left) / (right - left);
-        _21 = 0.0f;                     _22 = 2.0f / (top - bottom);     _23 = -(top + bottom) / (top - bottom);
-        _31 = 0.0f;                     _32 = 0.0f;                      _33 = 1.0f;
+    Vec2 transform_vector(Vec2 v) const {
+        return Vec2(_11 * v.x + _12 * v.y, _21 * v.x + _22 * v.y);
     }
     }
 };
 };
 
 
+struct PyVec2: Vec2 {
+    PY_CLASS(PyVec2, builtins, vec2)
+
+    PyVec2() : Vec2() {}
+    PyVec2(float x, float y) : Vec2(x, y) {}
+    PyVec2(const Vec2& v) : Vec2(v) {}
+    PyVec2(const PyVec2& v) : Vec2(v) {}
+
+    static void _register(VM* vm, PyObject* mod, PyObject* type){
+        vm->bind_constructor<3>(type, [](VM* vm, ArgsView args){
+            float x = vm->num_to_float(args[1]);
+            float y = vm->num_to_float(args[2]);
+            return VAR_T(PyVec2, x, y);
+        });
+
+        vm->bind_method<0>(type, "__repr__", [](VM* vm, ArgsView args){
+            PyVec2& self = _CAST(PyVec2&, args[0]);
+            std::stringstream ss;
+            ss << "vec2(" << self.x << ", " << self.y << ")";
+            return VAR(ss.str());
+        });
+
+        vm->bind_method<0>(type, "copy", [](VM* vm, ArgsView args){
+            PyVec2& self = _CAST(PyVec2&, args[0]);
+            return VAR_T(PyVec2, self);
+        });
+
+        vm->bind_method<1>(type, "__add__", [](VM* vm, ArgsView args){
+            PyVec2& self = _CAST(PyVec2&, args[0]);
+            PyVec2& other = CAST(PyVec2&, args[1]);
+            return VAR_T(PyVec2, self + other);
+        });
+
+        vm->bind_method<1>(type, "__sub__", [](VM* vm, ArgsView args){
+            PyVec2& self = _CAST(PyVec2&, args[0]);
+            PyVec2& other = CAST(PyVec2&, args[1]);
+            return VAR_T(PyVec2, self - other);
+        });
+
+        vm->bind_method<1>(type, "__mul__", [](VM* vm, ArgsView args){
+            PyVec2& self = _CAST(PyVec2&, args[0]);
+            f64 other = vm->num_to_float(args[1]);
+            return VAR_T(PyVec2, self * other);
+        });
+
+        vm->bind_method<1>(type, "__truediv__", [](VM* vm, ArgsView args){
+            PyVec2& self = _CAST(PyVec2&, args[0]);
+            f64 other = vm->num_to_float(args[1]);
+            return VAR_T(PyVec2, self / other);
+        });
+
+        vm->bind_method<1>(type, "__eq__", [](VM* vm, ArgsView args){
+            PyVec2& self = _CAST(PyVec2&, args[0]);
+            PyVec2& other = CAST(PyVec2&, args[1]);
+            return VAR(self == other);
+        });
+
+        vm->bind_method<1>(type, "__ne__", [](VM* vm, ArgsView args){
+            PyVec2& self = _CAST(PyVec2&, args[0]);
+            PyVec2& other = CAST(PyVec2&, args[1]);
+            return VAR(self != other);
+        });
+
+        type->attr().set("x", vm->property([](VM* vm, ArgsView args){
+            PyVec2& self = _CAST(PyVec2&, args[0]);
+            return VAR(self.x);
+        }, [](VM* vm, ArgsView args){
+            PyVec2& self = _CAST(PyVec2&, args[0]);
+            self.x = vm->num_to_float(args[1]);
+            return vm->None;
+        }));
+
+        type->attr().set("y", vm->property([](VM* vm, ArgsView args){
+            PyVec2& self = _CAST(PyVec2&, args[0]);
+            return VAR(self.y);
+        }, [](VM* vm, ArgsView args){
+            PyVec2& self = _CAST(PyVec2&, args[0]);
+            self.y = vm->num_to_float(args[1]);
+            return vm->None;
+        }));
+
+        vm->bind_method<1>(type, "dot", [](VM* vm, ArgsView args){
+            PyVec2& self = _CAST(PyVec2&, args[0]);
+            PyVec2& other = CAST(PyVec2&, args[1]);
+            return VAR(self.dot(other));
+        });
+
+        vm->bind_method<1>(type, "cross", [](VM* vm, ArgsView args){
+            PyVec2& self = _CAST(PyVec2&, args[0]);
+            PyVec2& other = CAST(PyVec2&, args[1]);
+            return VAR(self.cross(other));
+        });
+
+        vm->bind_method<0>(type, "length", [](VM* vm, ArgsView args){
+            PyVec2& self = _CAST(PyVec2&, args[0]);
+            return VAR(self.length());
+        });
+
+        vm->bind_method<0>(type, "length_squared", [](VM* vm, ArgsView args){
+            PyVec2& self = _CAST(PyVec2&, args[0]);
+            return VAR(self.length_squared());
+        });
+
+        vm->bind_method<0>(type, "normalize", [](VM* vm, ArgsView args){
+            PyVec2& self = _CAST(PyVec2&, args[0]);
+            self.normalize();
+            return vm->None;
+        });
+
+        vm->bind_method<0>(type, "normalized", [](VM* vm, ArgsView args){
+            PyVec2& self = _CAST(PyVec2&, args[0]);
+            return VAR_T(PyVec2, self.normalized());
+        });
+    }
+};
 
 
 struct PyMat3x3: Mat3x3{
 struct PyMat3x3: Mat3x3{
     PY_CLASS(PyMat3x3, builtins, mat3x3)
     PY_CLASS(PyMat3x3, builtins, mat3x3)
@@ -212,7 +386,12 @@ struct PyMat3x3: Mat3x3{
 
 
     static void _register(VM* vm, PyObject* mod, PyObject* type){
     static void _register(VM* vm, PyObject* mod, PyObject* type){
         vm->bind_constructor<-1>(type, [](VM* vm, ArgsView args){
         vm->bind_constructor<-1>(type, [](VM* vm, ArgsView args){
-            if(args.size() == 1+0) return VAR_T(PyMat3x3);
+            if(args.size() == 1+0) return VAR_T(PyMat3x3, Mat3x3::zeros());
+            if(args.size() == 1+9){
+                Mat3x3 mat;
+                for(int i=0; i<9; i++) mat.v[i] = vm->num_to_float(args[1+i]);
+                return VAR_T(PyMat3x3, mat);
+            }
             if(args.size() == 1+1){
             if(args.size() == 1+1){
                 List& a = CAST(List&, args[1]);
                 List& a = CAST(List&, args[1]);
                 if(a.size() != 3) vm->ValueError("Mat3x3.__new__ takes 3x3 list");
                 if(a.size() != 3) vm->ValueError("Mat3x3.__new__ takes 3x3 list");
@@ -253,6 +432,11 @@ struct PyMat3x3: Mat3x3{
             return VAR(ss.str());
             return VAR(ss.str());
         });
         });
 
 
+        vm->bind_method<0>(type, "copy", [](VM* vm, ArgsView args){
+            PyMat3x3& self = _CAST(PyMat3x3&, args[0]);
+            return VAR_T(PyMat3x3, self);
+        });
+
         vm->bind_method<1>(type, "__getitem__", [](VM* vm, ArgsView args){
         vm->bind_method<1>(type, "__getitem__", [](VM* vm, ArgsView args){
             PyMat3x3& self = _CAST(PyMat3x3&, args[0]);
             PyMat3x3& self = _CAST(PyMat3x3&, args[0]);
             Tuple& t = CAST(Tuple&, args[1]);
             Tuple& t = CAST(Tuple&, args[1]);
@@ -311,25 +495,25 @@ struct PyMat3x3: Mat3x3{
         vm->bind_method<1>(type, "__add__", [](VM* vm, ArgsView args){
         vm->bind_method<1>(type, "__add__", [](VM* vm, ArgsView args){
             PyMat3x3& self = _CAST(PyMat3x3&, args[0]);
             PyMat3x3& self = _CAST(PyMat3x3&, args[0]);
             PyMat3x3& other = CAST(PyMat3x3&, args[1]);
             PyMat3x3& other = CAST(PyMat3x3&, args[1]);
-            return VAR_T(PyMat3x3, self.add(other));
+            return VAR_T(PyMat3x3, self + other);
         });
         });
 
 
         vm->bind_method<1>(type, "__sub__", [](VM* vm, ArgsView args){
         vm->bind_method<1>(type, "__sub__", [](VM* vm, ArgsView args){
             PyMat3x3& self = _CAST(PyMat3x3&, args[0]);
             PyMat3x3& self = _CAST(PyMat3x3&, args[0]);
             PyMat3x3& other = CAST(PyMat3x3&, args[1]);
             PyMat3x3& other = CAST(PyMat3x3&, args[1]);
-            return VAR_T(PyMat3x3, self.sub(other));
+            return VAR_T(PyMat3x3, self - other);
         });
         });
 
 
         vm->bind_method<1>(type, "__mul__", [](VM* vm, ArgsView args){
         vm->bind_method<1>(type, "__mul__", [](VM* vm, ArgsView args){
             PyMat3x3& self = _CAST(PyMat3x3&, args[0]);
             PyMat3x3& self = _CAST(PyMat3x3&, args[0]);
             f64 other = vm->num_to_float(args[1]);
             f64 other = vm->num_to_float(args[1]);
-            return VAR_T(PyMat3x3, self.mul(other));
+            return VAR_T(PyMat3x3, self * other);
         });
         });
 
 
         vm->bind_method<1>(type, "__truediv__", [](VM* vm, ArgsView args){
         vm->bind_method<1>(type, "__truediv__", [](VM* vm, ArgsView args){
             PyMat3x3& self = _CAST(PyMat3x3&, args[0]);
             PyMat3x3& self = _CAST(PyMat3x3&, args[0]);
             f64 other = vm->num_to_float(args[1]);
             f64 other = vm->num_to_float(args[1]);
-            return VAR_T(PyMat3x3, self.div(other));
+            return VAR_T(PyMat3x3, self / other);
         });
         });
 
 
         vm->bind_method<1>(type, "__matmul__", [](VM* vm, ArgsView args){
         vm->bind_method<1>(type, "__matmul__", [](VM* vm, ArgsView args){
@@ -338,6 +522,12 @@ struct PyMat3x3: Mat3x3{
             return VAR_T(PyMat3x3, self.matmul(other));
             return VAR_T(PyMat3x3, self.matmul(other));
         });
         });
 
 
+        vm->bind_method<1>(type, "matmul", [](VM* vm, ArgsView args){
+            PyMat3x3& other = CAST(PyMat3x3&, args[0]);
+            PyMat3x3& self = _CAST(PyMat3x3&, args[1]);
+            return VAR_T(PyMat3x3, self.matmul(other));
+        });
+
         vm->bind_method<1>(type, "__eq__", [](VM* vm, ArgsView args){
         vm->bind_method<1>(type, "__eq__", [](VM* vm, ArgsView args){
             PyMat3x3& self = _CAST(PyMat3x3&, args[0]);
             PyMat3x3& self = _CAST(PyMat3x3&, args[0]);
             PyMat3x3& other = _CAST(PyMat3x3&, args[1]);
             PyMat3x3& other = _CAST(PyMat3x3&, args[1]);
@@ -350,7 +540,7 @@ struct PyMat3x3: Mat3x3{
             return VAR(self != other);
             return VAR(self != other);
         });
         });
 
 
-        vm->bind_method<0>(type, "deteminant", [](VM* vm, ArgsView args){
+        vm->bind_method<0>(type, "determinant", [](VM* vm, ArgsView args){
             PyMat3x3& self = _CAST(PyMat3x3&, args[0]);
             PyMat3x3& self = _CAST(PyMat3x3&, args[0]);
             return VAR(self.determinant());
             return VAR(self.determinant());
         });
         });
@@ -368,9 +558,83 @@ struct PyMat3x3: Mat3x3{
             return VAR_T(PyMat3x3, ret);
             return VAR_T(PyMat3x3, ret);
         });
         });
 
 
-        vm->bind_method<0>(type, "is_identity", [](VM* vm, ArgsView args){
+        vm->bind_func<0>(type, "zeros", [](VM* vm, ArgsView args){
+            return VAR_T(PyMat3x3, Mat3x3::zeros());
+        });
+
+        vm->bind_func<0>(type, "ones", [](VM* vm, ArgsView args){
+            return VAR_T(PyMat3x3, Mat3x3::ones());
+        });
+
+        vm->bind_func<0>(type, "identity", [](VM* vm, ArgsView args){
+            return VAR_T(PyMat3x3, Mat3x3::identity());
+        });
+
+        /*************** affine transformations ***************/
+        vm->bind_func<1>(type, "translate", [](VM* vm, ArgsView args){
+            PyVec2& v = CAST(PyVec2&, args[0]);
+            return VAR_T(PyMat3x3, Mat3x3::translate(v));
+        });
+
+        vm->bind_func<1>(type, "rotate", [](VM* vm, ArgsView args){
+            f64 angle = vm->num_to_float(args[0]);
+            return VAR_T(PyMat3x3, Mat3x3::rotate(angle));
+        });
+
+        vm->bind_func<1>(type, "scale", [](VM* vm, ArgsView args){
+            PyVec2& v = CAST(PyVec2&, args[0]);
+            return VAR_T(PyMat3x3, Mat3x3::scale(v));
+        });
+
+        vm->bind_func<3>(type, "trs", [](VM* vm, ArgsView args){
+            PyVec2& t = CAST(PyVec2&, args[0]);
+            f64 r = vm->num_to_float(args[1]);
+            PyVec2& s = CAST(PyVec2&, args[2]);
+            return VAR_T(PyMat3x3, Mat3x3::trs(t, r, s));
+        });
+
+        vm->bind_method<0>(type, "is_affine", [](VM* vm, ArgsView args){
+            PyMat3x3& self = _CAST(PyMat3x3&, args[0]);
+            return VAR(self.is_affine());
+        });
+
+        vm->bind_method<0>(type, "inverse_affine", [](VM* vm, ArgsView args){
+            PyMat3x3& self = _CAST(PyMat3x3&, args[0]);
+            return VAR_T(PyMat3x3, self.inverse_affine());
+        });
+
+        vm->bind_method<1>(type, "matmul_affine", [](VM* vm, ArgsView args){
+            PyMat3x3& self = _CAST(PyMat3x3&, args[0]);
+            PyMat3x3& other = CAST(PyMat3x3&, args[1]);
+            return VAR_T(PyMat3x3, self.matmul_affine(other));
+        });
+
+
+        vm->bind_method<0>(type, "translation", [](VM* vm, ArgsView args){
+            PyMat3x3& self = _CAST(PyMat3x3&, args[0]);
+            return VAR_T(PyVec2, self.translation());
+        });
+
+        vm->bind_method<0>(type, "rotation", [](VM* vm, ArgsView args){
+            PyMat3x3& self = _CAST(PyMat3x3&, args[0]);
+            return VAR(self.rotation());
+        });
+
+        vm->bind_method<0>(type, "scale", [](VM* vm, ArgsView args){
+            PyMat3x3& self = _CAST(PyMat3x3&, args[0]);
+            return VAR_T(PyVec2, self.scale());
+        });
+
+        vm->bind_method<1>(type, "transform_point", [](VM* vm, ArgsView args){
+            PyMat3x3& self = _CAST(PyMat3x3&, args[0]);
+            PyVec2& v = CAST(PyVec2&, args[1]);
+            return VAR_T(PyVec2, self.transform_point(v));
+        });
+
+        vm->bind_method<1>(type, "transform_vector", [](VM* vm, ArgsView args){
             PyMat3x3& self = _CAST(PyMat3x3&, args[0]);
             PyMat3x3& self = _CAST(PyMat3x3&, args[0]);
-            return VAR(self.is_identity());
+            PyVec2& v = CAST(PyVec2&, args[1]);
+            return VAR_T(PyVec2, self.transform_vector(v));
         });
         });
     }
     }
 };
 };

+ 81 - 0
src/mat3x3.pyi

@@ -0,0 +1,81 @@
+from typing import overload
+
+class vec2:
+    x: float
+    y: float
+
+    def __init__(self, x: float, y: float) -> None: ...
+    def copy(self) -> vec2: ...
+    def __add__(self, other: vec2) -> vec2: ...
+    def __sub__(self, other: vec2) -> vec2: ...
+    def __mul__(self, other: float) -> vec2: ...
+    def __truediv__(self, other: float) -> vec2: ...
+    def dot(self, other: vec2) -> float: ...
+    def cross(self, other: vec2) -> float: ...
+    def length(self) -> float: ...
+    def length_squared(self) -> float: ...
+    def normalize(self) -> None: ...
+    def normalized(self) -> vec2: ...
+
+class mat3x3:
+    _11: float
+    _12: float
+    _13: float
+    _21: float
+    _22: float
+    _23: float
+    _31: float
+    _32: float
+    _33: float
+
+    @overload
+    def __init__(self) -> None: ...
+    @overload
+    def __init__(self, _11, _12, _13, _21, _22, _23, _31, _32, _33) -> None: ...
+    @overload
+    def __init__(self, a: list[list]): ...
+
+    def set_zeros(self) -> None: ...
+    def set_ones(self) -> None: ...
+    def set_identity(self) -> None: ...
+
+    def copy(self) -> mat3x3: ...
+    def __getitem__(self, index: tuple[int, int]) -> float: ...
+    def __setitem__(self, index: tuple[int, int], value: float) -> None: ...
+    def __add__(self, other: mat3x3) -> mat3x3: ...
+    def __sub__(self, other: mat3x3) -> mat3x3: ...
+    def __mul__(self, other: float) -> mat3x3: ...
+    def __truediv__(self, other: float) -> mat3x3: ...
+    def __matmul__(self, other: mat3x3) -> mat3x3: ...
+    def matmul(self, other: mat3x3) -> mat3x3: ...
+    def determinant(self) -> float: ...
+    def transpose(self) -> mat3x3: ...
+    def inverse(self) -> mat3x3: ...
+
+    @staticmethod
+    def zeros() -> mat3x3: ...
+    @staticmethod
+    def ones() -> mat3x3: ...
+    @staticmethod
+    def identity() -> mat3x3: ...
+
+    # affine transformations    
+    @staticmethod
+    def translate(v: vec2) -> mat3x3: ...
+    @staticmethod
+    def rotate(rad: float) -> mat3x3: ...
+    @staticmethod
+    def scale(v: vec2) -> mat3x3: ...
+    @staticmethod
+    def trs(t: vec2, r: float, s: vec2) -> mat3x3: ...
+
+    def is_affine(self) -> bool: ...
+    def inverse_affine(self) -> mat3x3: ...
+    def matmul_affine(self, other: mat3x3) -> mat3x3: ...
+
+    def translation(self) -> vec2: ...
+    def rotation(self) -> float: ...
+    def scale(self) -> vec2: ...
+
+    def transform_point(self, p: vec2) -> vec2: ...
+    def transform_vector(self, v: vec2) -> vec2: ...