1. Alberto Torres
  2. pygamekit

Source

pygamekit / mathutils.pyx


from prerequisites cimport *
cimport gkmath

cdef class Vector:
    
    def __init__(self, ini=None, ini2=None, ini3=None):
        if ini3!=None:
            self.v = new gkmath.Vector3(ini,ini2,ini3)
        elif isinstance(ini, Vector):
            self.v = new gkmath.Vector3()
            self.v.assign((<Vector>ini).v[0])
            memcpy((<gkmath.Vector3*>self.v).ptr(),(<Vector>ini).v.ptr(),sizeof(Real)*3)
        elif ini!=None:
            self.v = new gkmath.Vector3(ini[0],ini[1],ini[2])
        else:
            self.v = new gkmath.Vector3()

    def __dealloc__(self):
        del self.v
        
    cdef Vector assign(self, gkmath.Vector3 v):
        self.v.assign(v)
        return self
            
    property x:
        def __get__(self): return self.v.x
        def __set__(self, v): self.v.x=v 

    property y:
        def __get__(self): return self.v.y
        def __set__(self, v): self.v.y=v 

    property z:
        def __get__(self): return self.v.z
        def __set__(self, v): self.v.z=v
        
    property length:
        def __get__(self):
            return self.v.length()
            
        def __set__(self, Real v):
            self.v.normalise()
            self.v.imul(v)
        
    def normalize(self):
        return self.v.normalise()

    def normalized(self):
        cdef Vector v = Vector(self)
        v.v.normalise()
        return v
        
    def copy(self):
        return Vector(self)

    def __len__(self): return 3

    def __getitem__(self, i):
        return self.v.getitem(i)
        
    def __add__(self, v):
        cdef Vector ret = Vector(self)
        if isinstance(v, Vector):
            (ret.v).iadd((<Vector>v).v[0])
        else:
            (ret.v).iadd(gkmath.Vector3(v[0],v[1],v[2]))
        return ret

    def __sub__(self, v):
        cdef Vector ret = Vector(self)
        if isinstance(v, Vector):
            (ret.v).isub((<Vector>v).v[0])
        else:
            (ret.v).isub(gkmath.Vector3(v[0],v[1],v[2]))
        return ret

    def __iadd__(self, v):
        if isinstance(v, Vector):
            (self.v).iadd((<Vector>v).v[0])
        else:
            (self.v).iadd(gkmath.Vector3(v[0],v[1],v[2]))
        return self

    def __isub__(self, v):
        cdef Vector ret = Vector(self)
        if isinstance(v, Vector):
            (self.v).isub((<Vector>v).v[0])
        else:
            (self.v).isub(gkmath.Vector3(v[0],v[1],v[2]))
        return self
        
    def __mul__(self, v):
        cdef Vector ret = Vector(self)
        if isinstance(v, Vector):
            (ret.v).imul((<Vector>v).v[0])
        elif getattr(v, '__getitem__', False):
            (ret.v).imul(gkmath.Vector3(v[0],v[1],v[2]))
        else:
            (ret.v).imul(<Real>v)
        return ret

    def __div__(self, v):
        cdef Vector ret = Vector(self)
        if isinstance(v, Vector):
            (ret.v).idiv((<Vector>v).v[0])
        elif getattr(v, '__getitem__', False):
            (ret.v).idiv(gkmath.Vector3(v[0],v[1],v[2]))
        else:
            (ret.v).idiv(<Real>v)
        return ret

    def __truediv__(self, v):
        cdef Vector ret = Vector(self)
        if isinstance(v, Vector):
            (ret.v).idiv((<Vector>v).v[0])
        elif getattr(v, '__getitem__', False):
            (ret.v).idiv(gkmath.Vector3(v[0],v[1],v[2]))
        else:
            (ret.v).idiv(<Real>v)
        return ret

    def __imul__(self, v):
        if isinstance(v, Vector):
            (self.v).imul((<Vector>v).v[0])
        elif getattr(v, '__getitem__', False):
            (self.v).imul(gkmath.Vector3(v[0],v[1],v[2]))
        else:
            (self.v).imul(<Real>v)
        return self

    def __idiv__(self, v):
        if isinstance(v, Vector):
            (self.v).idiv((<Vector>v).v[0])
        elif getattr(v, '__getitem__', False):
            (self.v).idiv(gkmath.Vector3(v[0],v[1],v[2]))
        else:
            (self.v).idiv(<Real>v)
        return self

    def __itruediv__(self, v):
        if isinstance(v, Vector):
            (self.v).idiv((<Vector>v).v[0])
        elif getattr(v, '__getitem__', False):
            (self.v).idiv(gkmath.Vector3(v[0],v[1],v[2]))
        else:
            (self.v).idiv(<Real>v)
        return self

    def __pos__(self): return self
    
    def __neg__(self):
        return self*-1 #optimize this?

    def __getitem__(self, i):
        if isinstance(i,slice):
            return [self.v.x,self.v.y,self.v.z][i]
        elif i<3:
            return self.v.ptr()[i%3]
        else:
            raise IndexError

    def __setitem__(self, i, v):
        if not isinstance(i,slice) and i<3:
            self.v.ptr()[i%3]=v
        else:
            raise IndexError
        
    def __repr__(self):
        return "Vector(%f, %f, %f)"%(self.v.x,self.v.y,self.v.z)
        
    def angle_between(self, other):
        return self.v.angleBetween(Vector(other).v[0]).valueRadians()
        
    def get_rotation_to(self, other, fallbackAxis=None):
        cdef Quaternion q = Quaternion()
        if fallbackAxis!=None:
            q.q.assign(self.v.getRotationTo(Vector(other).v[0], Vector(fallbackAxis).v[0]))
        else:
            q.q.assign(self.v.getRotationTo(Vector(other).v[0]))
        return q
        
    def lerp(self, other, factor):
        factor = max(0.0,min(factor,1.0))
        invf = 1.0-factor
        return Vector(self.x*invf + other[0]*factor,
                      self.y*invf + other[1]*factor,
                      self.z*invf + other[2]*factor)
        
    #cdef assignv(self, gkmath.Vector3 v):
    #    memcpy((<gkmath.Vector3*>self.v).ptr(),v.ptr(),sizeof(Real)*3)
        
cdef class Quaternion:
    
    def __init__(Quaternion self, ini=None, ini2=None, ini3=None, ini4=None):
        if isinstance(ini, Quaternion):
            self.q = new gkmath.Quaternion()
            self.q.assign((<Quaternion>ini).q[0])
        elif ini4!=None:
            self.q = new gkmath.Quaternion(ini,ini2,ini3,ini4)
        elif ini!=None:
            self.q = new gkmath.Quaternion(ini[0],ini[1],ini[2],ini[3])
        else:
            self.q = new gkmath.Quaternion()
            
    def __dealloc__(self):
        del self.q
            
    property w:
        def __get__(self): return self.q.w
        def __set__(self, v): self.q.w=v 

    property x:
        def __get__(self): return self.q.x
        def __set__(self, v): self.q.x=v 

    property y:
        def __get__(self): return self.q.y
        def __set__(self, v): self.q.y=v 

    property z:
        def __get__(self): return self.q.z
        def __set__(self, v): self.q.z=v
        
    def normalize(Quaternion self):
        return self.q.normalise()

    def normalized(Quaternion self):
        cdef Quaternion v = Quaternion(self)
        v.v.normalise()
        return v
        
    def copy(Quaternion self):
        return Quaternion(self)

    def __len__(self): return 4

    def __pos__(Quaternion self): return self
    
    def __neg__(Quaternion self):
        return self*-1 #optimize this?

    def __getitem__(Quaternion self, i):
        if isinstance(i,slice):
            return [self.q.w,self.q.x,self.q.y,self.q.z][i]
        elif i<4:
            return self.q.ptr()[i%4]
        else:
            raise IndexError

    def __setitem__(Quaternion self, i, v):
        if not isinstance(i,slice) and i<4:
            self.q.ptr()[i%4]=v
        else:
            raise IndexError
        
    def __repr__(Quaternion self):
        return "Quaternion(%f, %f, %f, %f)"%(self.q.w,self.q.x,self.q.y,self.q.z)
 
    def __mul__(Quaternion self, v):
        cdef Quaternion retq
        cdef Vector retv
        if isinstance(v, Quaternion):
            retq = Quaternion()
            (retq.q).assign((retq.q).mul((<Quaternion>v).q[0]))
            return retq
        if isinstance(v, Vector):
            retv = Vector()
            (retv.v).assign((<Quaternion>self).q.mul((<Vector>v).v[0]))
            return retv
        retq = Quaternion()
        (retq.q).assign((retq.q).mul(<Real>v))
        return retq
        
    def inverted(Quaternion self):
        cdef Quaternion q = self.copy()
        q.invert()
        return q
        
    def invert(Quaternion self):
        self.q.x=-(self.q.x)
        self.q.y=-(self.q.y)
        self.q.z=-(self.q.z)
        
    def lerp(self, Quaternion other, factor):
        cdef Quaternion q = Quaternion()
        q.q.assign(gkmath.quat_nlerp(factor, self.q[0], other.q[0], False))
        return q
        
    def slerp(self, Quaternion other, factor):
        cdef Quaternion q = Quaternion()
        q.q.assign(gkmath.quat_Slerp(factor, self.q[0], other.q[0], False))
        return q