def scaling(s): """Return scaling matrix.""" sx,sy,sz = s return mat4(sx, 0.0, 0.0, 0.0, 0.0, sy, 0.0, 0.0, 0.0, 0.0, sz, 0.0, 0.0, 0.0, 0.0, 1.0)
def translation(t): """Return translation matrix.""" tx,ty,tz = t return mat4(1.0, 0.0, 0.0, tx, 0.0, 1.0, 0.0, ty, 0.0, 0.0, 1.0, tz, 0.0, 0.0, 0.0, 1.0)
def decompose(self): """Decomposes the matrix into a translation, rotation and scaling part. Returns a tuple (translation, rotation, scaling). The translation and scaling parts are given as vec3's, the rotation is still given as a mat4. """ try: dummy = self.ortho() except ZeroDivisionError: return (_vec3(0), mat4(1.0), _vec3(0)) dummy.setRow(3, _vec4(0.0, 0.0, 0.0, 1.0)) dummy.setColumn(3, _vec4(0.0, 0.0, 0.0, 1.0)) x = dummy.getColumn(0) y = dummy.getColumn(1) z = dummy.getColumn(2) xl = x.length() yl = y.length() zl = z.length() scale = _vec3(xl, yl, zl) x /= xl y /= yl z /= zl dummy.setColumn(0, x) dummy.setColumn(1, y) dummy.setColumn(2, z) if dummy.determinant() < 0.0: dummy.setColumn(0, -x) scale.x = -scale.x return (_vec3(self.mlist[3], self.mlist[7], self.mlist[11]), dummy, scale)
def lookAt(pos, target, up=_vec3(0,0,1)): """Look from pos to target. The resulting transformation moves the origin to pos and rotates so that the z-axis points to target. The y-axis is as close as possible to the up vector. """ pos = _vec3(pos) target = _vec3(target) up = _vec3(up) dir = (target - pos).normalize() up = up.normalize() up -= (up * dir) * dir try: up = up.normalize() except: # We're looking along the up direction, so choose # an arbitrary direction that is perpendicular to dir # as new up. up = dir.ortho() right = up.cross(dir).normalize() return mat4(right.x, up.x, dir.x, pos.x, right.y, up.y, dir.y, pos.y, right.z, up.z, dir.z, pos.z, 0.0, 0.0, 0.0, 1.0)
def ortho(self): """Return a matrix with orthogonal base vectors. Makes the x-, y- and z-axis orthogonal. The fourth column and row remain untouched. """ m11,m12,m13,m14,m21,m22,m23,m24,m31,m32,m33,m34,m41,m42,m43,m44 = self.mlist x = _vec3(m11, m21, m31) y = _vec3(m12, m22, m32) z = _vec3(m13, m23, m33) xl = x.length() xl*=xl y = y - ((x*y)/xl)*x z = z - ((x*z)/xl)*x yl = y.length() yl*=yl z = z - ((y*z)/yl)*y return mat4( x.x, y.x, z.x, m14, x.y, y.y, z.y, m24, x.z, y.z, z.z, m34, m41, m42, m43, m44)
def lookAt(pos, target, up=_vec3(0, 0, 1)): """Look from pos to target. The resulting transformation moves the origin to pos and rotates so that the z-axis points to target. The y-axis is as close as possible to the up vector. """ pos = _vec3(pos) target = _vec3(target) up = _vec3(up) dir = (target - pos).normalize() up = up.normalize() up -= (up * dir) * dir try: up = up.normalize() except: # We're looking along the up direction, so choose # an arbitrary direction that is perpendicular to dir # as new up. up = dir.ortho() right = up.cross(dir).normalize() return mat4(right.x, up.x, dir.x, pos.x, right.y, up.y, dir.y, pos.y, right.z, up.z, dir.z, pos.z, 0.0, 0.0, 0.0, 1.0)
def rotation(angle, axis): """Return rotation matrix. angle must be given in radians. axis should be of type vec3. """ axis = _vec3(axis) sqr_a = axis.x*axis.x sqr_b = axis.y*axis.y sqr_c = axis.z*axis.z len2 = sqr_a+sqr_b+sqr_c k2 = math.cos(angle) k1 = (1.0-k2)/len2 k3 = math.sin(angle)/math.sqrt(len2) k1ab = k1*axis.x*axis.y k1ac = k1*axis.x*axis.z k1bc = k1*axis.y*axis.z k3a = k3*axis.x k3b = k3*axis.y k3c = k3*axis.z return mat4( k1*sqr_a+k2, k1ab-k3c, k1ac+k3b, 0.0, k1ab+k3c, k1*sqr_b+k2, k1bc-k3a, 0.0, k1ac-k3b, k1bc+k3a, k1*sqr_c+k2, 0.0, 0.0, 0.0, 0.0, 1.0)
def __rmul__(self, other): T = type(other) # scalar*mat4 if T == types.FloatType or T == types.IntType or T == types.LongType: return mat4(map(lambda x, other=other: other * x, self.mlist)) # vec4*mat4 if isinstance(other, _vec4): m11, m12, m13, m14, m21, m22, m23, m24, m31, m32, m33, m34, m41, m42, m43, m44 = self.mlist return _vec4( other.x * m11 + other.y * m21 + other.z * m31 + other.w * m41, other.x * m12 + other.y * m22 + other.z * m32 + other.w * m42, other.x * m13 + other.y * m23 + other.z * m33 + other.w * m43, other.x * m14 + other.y * m24 + other.z * m34 + other.w * m44) # vec3*mat4 if isinstance(other, _vec3): m11, m12, m13, m14, m21, m22, m23, m24, m31, m32, m33, m34, m41, m42, m43, m44 = self.mlist w = float(other.x * m14 + other.y * m24 + other.z * m34 + m44) return _vec3( other.x * m11 + other.y * m21 + other.z * m31 + m41, other.x * m12 + other.y * m22 + other.z * m32 + m42, other.x * m13 + other.y * m23 + other.z * m33 + m43) / w # mat4*mat4 if isinstance(other, mat4): return self.__mul__(other) # unsupported else: raise TypeError, "unsupported operand type for *"
def __rmul__(self, other): T = type(other) # scalar*mat4 if T==types.FloatType or T==types.IntType or T==types.LongType: return mat4(map(lambda x,other=other: other*x, self.mlist)) # vec4*mat4 if isinstance(other, _vec4): m11,m12,m13,m14,m21,m22,m23,m24,m31,m32,m33,m34,m41,m42,m43,m44 = self.mlist return _vec4(other.x*m11 + other.y*m21 + other.z*m31 + other.w*m41, other.x*m12 + other.y*m22 + other.z*m32 + other.w*m42, other.x*m13 + other.y*m23 + other.z*m33 + other.w*m43, other.x*m14 + other.y*m24 + other.z*m34 + other.w*m44) # vec3*mat4 if isinstance(other, _vec3): m11,m12,m13,m14,m21,m22,m23,m24,m31,m32,m33,m34,m41,m42,m43,m44 = self.mlist w = float(other.x*m14 + other.y*m24 + other.z*m34 + m44) return _vec3(other.x*m11 + other.y*m21 + other.z*m31 + m41, other.x*m12 + other.y*m22 + other.z*m32 + m42, other.x*m13 + other.y*m23 + other.z*m33 + m43)/w # mat4*mat4 if isinstance(other, mat4): return self.__mul__(other) # unsupported else: raise TypeError("unsupported operand type for *")
def rotation(angle, axis): """Return rotation matrix. angle must be given in radians. axis should be of type vec3. """ axis = _vec3(axis) sqr_a = axis.x * axis.x sqr_b = axis.y * axis.y sqr_c = axis.z * axis.z len2 = sqr_a + sqr_b + sqr_c k2 = math.cos(angle) k1 = (1.0 - k2) / len2 k3 = math.sin(angle) / math.sqrt(len2) k1ab = k1 * axis.x * axis.y k1ac = k1 * axis.x * axis.z k1bc = k1 * axis.y * axis.z k3a = k3 * axis.x k3b = k3 * axis.y k3c = k3 * axis.z return mat4(k1 * sqr_a + k2, k1ab - k3c, k1ac + k3b, 0.0, k1ab + k3c, k1 * sqr_b + k2, k1bc - k3a, 0.0, k1ac - k3b, k1bc + k3a, k1 * sqr_c + k2, 0.0, 0.0, 0.0, 0.0, 1.0)
def frustum(self, left, right, bottom, top, near, far): """equivalent to the OpenGL command glFrustum()""" return mat4( (2.0*near)/(right-left), 0.0, float(right+left)/(right-left), 0.0, 0.0, (2.0*near)/(top-bottom), float(top+bottom)/(top-bottom), 0.0, 0.0, 0.0, -float(far+near)/(far-near), -(2.0*far*near)/(far-near), 0.0, 0.0, -1.0, 0.0)
def frustum(left, right, bottom, top, near, far): """Set a perspective transformation. This method is equivalent to the OpenGL command glFrustum(). """ return mat4( (2.0*near)/(right-left), 0.0, float(right+left)/(right-left), 0.0, 0.0, (2.0*near)/(top-bottom), float(top+bottom)/(top-bottom), 0.0, 0.0, 0.0, -float(far+near)/(far-near), -(2.0*far*near)/(far-near), 0.0, 0.0, -1.0, 0.0)
def frustum(self, left, right, bottom, top, near, far): """equivalent to the OpenGL command glFrustum()""" return mat4((2.0 * near) / (right - left), 0.0, float(right + left) / (right - left), 0.0, 0.0, (2.0 * near) / (top - bottom), float(top + bottom) / (top - bottom), 0.0, 0.0, 0.0, -float(far + near) / (far - near), -(2.0 * far * near) / (far - near), 0.0, 0.0, -1.0, 0.0)
def __pos__(self): """ >>> M=mat4(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16) >>> print +M [ 1.0000, 2.0000, 3.0000, 4.0000] [ 5.0000, 6.0000, 7.0000, 8.0000] [ 9.0000, 10.0000, 11.0000, 12.0000] [ 13.0000, 14.0000, 15.0000, 16.0000] """ return mat4(map(lambda x: +x, self.mlist))
def __neg__(self): """Negation. >>> M=mat4(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16) >>> print -M [ -1.0000, -2.0000, -3.0000, -4.0000] [ -5.0000, -6.0000, -7.0000, -8.0000] [ -9.0000, -10.0000, -11.0000, -12.0000] [ -13.0000, -14.0000, -15.0000, -16.0000] """ return mat4(map(lambda x: -x, self.mlist))
def __mod__(self, other): """Modulo. >>> M=mat4(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16) >>> print M%5.0 [ 1.0000, 2.0000, 3.0000, 4.0000] [ 0.0000, 1.0000, 2.0000, 3.0000] [ 4.0000, 0.0000, 1.0000, 2.0000] [ 3.0000, 4.0000, 0.0000, 1.0000] """ T = type(other) # mat4%scalar if T == types.FloatType or T == types.IntType or T == types.LongType: return mat4(map(lambda x, other=other: x % other, self.mlist)) # mat4%mat4 if isinstance(other, mat4): return mat4(map(lambda a, b: a % b, self.mlist, other.mlist)) # unsupported else: raise TypeError("unsupported operand type for %")
def __mod__(self, other): """Modulo. >>> M=mat4(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16) >>> print M%5.0 [ 1.0000, 2.0000, 3.0000, 4.0000] [ 0.0000, 1.0000, 2.0000, 3.0000] [ 4.0000, 0.0000, 1.0000, 2.0000] [ 3.0000, 4.0000, 0.0000, 1.0000] """ T = type(other) # mat4%scalar if T==float or T==int or T==int: return mat4(list(map(lambda x,other=other: x%other, self.mlist))) # mat4%mat4 if isinstance(other, mat4): return mat4([a_b1[0]%a_b1[1] for a_b1 in list(zip(self.mlist, other.mlist))]) # unsupported else: raise TypeError("unsupported operand type for %")
def __mod__(self, other): """Modulo. >>> M=mat4(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16) >>> print M%5.0 [ 1.0000, 2.0000, 3.0000, 4.0000] [ 0.0000, 1.0000, 2.0000, 3.0000] [ 4.0000, 0.0000, 1.0000, 2.0000] [ 3.0000, 4.0000, 0.0000, 1.0000] """ T = type(other) # mat4%scalar if T==types.FloatType or T==types.IntType or T==types.LongType: return mat4(map(lambda x,other=other: x%other, self.mlist)) # mat4%mat4 if isinstance(other, mat4): return mat4(map(lambda a,b: a%b, self.mlist, other.mlist)) # unsupported else: raise TypeError("unsupported operand type for %")
def identity(self): """Return identity matrix. >>> print mat4().identity() [ 1.0000, 0.0000, 0.0000, 0.0000] [ 0.0000, 1.0000, 0.0000, 0.0000] [ 0.0000, 0.0000, 1.0000, 0.0000] [ 0.0000, 0.0000, 0.0000, 1.0000] """ return mat4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0)
def identity(): """Return identity matrix. >>> print mat4().identity() [ 1.0000, 0.0000, 0.0000, 0.0000] [ 0.0000, 1.0000, 0.0000, 0.0000] [ 0.0000, 0.0000, 1.0000, 0.0000] [ 0.0000, 0.0000, 0.0000, 1.0000] """ return mat4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0)
def transpose(self): """Transpose matrix. >>> M=mat4(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16) >>> print M.transpose() [ 1.0000, 5.0000, 9.0000, 13.0000] [ 2.0000, 6.0000, 10.0000, 14.0000] [ 3.0000, 7.0000, 11.0000, 15.0000] [ 4.0000, 8.0000, 12.0000, 16.0000] """ m11, m12, m13, m14, m21, m22, m23, m24, m31, m32, m33, m34, m41, m42, m43, m44 = self.mlist return mat4(m11, m21, m31, m41, m12, m22, m32, m42, m13, m23, m33, m43, m14, m24, m34, m44)
def __sub__(self, other): """Matrix subtraction. >>> M=mat4(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16) >>> print M-M [ 0.0000, 0.0000, 0.0000, 0.0000] [ 0.0000, 0.0000, 0.0000, 0.0000] [ 0.0000, 0.0000, 0.0000, 0.0000] [ 0.0000, 0.0000, 0.0000, 0.0000] """ if isinstance(other, mat4): return mat4(map(lambda x, y: x - y, self.mlist, other.mlist)) else: raise TypeError, "unsupported operand type for -"
def __add__(self, other): """Matrix addition. >>> M=mat4(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16) >>> print M+M [ 2.0000, 4.0000, 6.0000, 8.0000] [ 10.0000, 12.0000, 14.0000, 16.0000] [ 18.0000, 20.0000, 22.0000, 24.0000] [ 26.0000, 28.0000, 30.0000, 32.0000] """ if isinstance(other, mat4): return mat4(map(lambda x, y: x + y, self.mlist, other.mlist)) else: raise TypeError, "unsupported operand type for +"
def __add__(self, other): """Matrix addition. >>> M=mat4(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16) >>> print M+M [ 2.0000, 4.0000, 6.0000, 8.0000] [ 10.0000, 12.0000, 14.0000, 16.0000] [ 18.0000, 20.0000, 22.0000, 24.0000] [ 26.0000, 28.0000, 30.0000, 32.0000] """ if isinstance(other, mat4): return mat4(map(lambda x,y: x+y, self.mlist, other.mlist)) else: raise TypeError("unsupported operand type for +")
def __sub__(self, other): """Matrix subtraction. >>> M=mat4(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16) >>> print M-M [ 0.0000, 0.0000, 0.0000, 0.0000] [ 0.0000, 0.0000, 0.0000, 0.0000] [ 0.0000, 0.0000, 0.0000, 0.0000] [ 0.0000, 0.0000, 0.0000, 0.0000] """ if isinstance(other, mat4): return mat4(map(lambda x,y: x-y, self.mlist, other.mlist)) else: raise TypeError("unsupported operand type for -")
def transpose(self): """Transpose matrix. >>> M=mat4(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16) >>> print M.transpose() [ 1.0000, 5.0000, 9.0000, 13.0000] [ 2.0000, 6.0000, 10.0000, 14.0000] [ 3.0000, 7.0000, 11.0000, 15.0000] [ 4.0000, 8.0000, 12.0000, 16.0000] """ m11,m12,m13,m14,m21,m22,m23,m24,m31,m32,m33,m34,m41,m42,m43,m44 = self.mlist return mat4(m11,m21,m31,m41, m12,m22,m32,m42, m13,m23,m33,m43, m14,m24,m34,m44)
def __mod__(self, other): """Modulo. >>> M=mat4(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16) >>> print M%5.0 [ 1.0000, 2.0000, 3.0000, 4.0000] [ 0.0000, 1.0000, 2.0000, 3.0000] [ 4.0000, 0.0000, 1.0000, 2.0000] [ 3.0000, 4.0000, 0.0000, 1.0000] """ T = type(other) # mat4%scalar if T == float or T == int or T == int: return mat4(list(map(lambda x, other=other: x % other, self.mlist))) # mat4%mat4 if isinstance(other, mat4): return mat4([ a_b1[0] % a_b1[1] for a_b1 in list(zip(self.mlist, other.mlist)) ]) # unsupported else: raise TypeError("unsupported operand type for %")
def __init__(self, *args): "Constructor" # No arguments if len(args) == 0: self.mlist = 16 * [0.0] # 1 argument (list, scalar or mat4) elif len(args) == 1: T = type(args[0]) if T == types.FloatType or T == types.IntType or T == types.LongType: f = float(args[0]) self.mlist = [ f, 0.0, 0.0, 0.0, 0.0, f, 0.0, 0.0, 0.0, 0.0, f, 0.0, 0.0, 0.0, 0.0, f ] # mat4 elif isinstance(args[0], mat4): self.mlist = copy.copy(args[0].mlist) # String elif T == types.StringType: s = args[0].replace(",", " ").replace(" ", " ").strip().split(" ") self.mlist = map(lambda x: float(x), s) else: self.mlist = mat4(*args[0]).mlist # 4 arguments (sequences) elif len(args) == 4: a, b, c, d = args self.mlist = [ a[0], b[0], c[0], d[0], a[1], b[1], c[1], d[1], a[2], b[2], c[2], d[2], a[3], b[3], c[3], d[3] ] self.mlist = map(lambda x: float(x), self.mlist) # 16 arguments elif len(args) == 16: self.mlist = map(lambda x: float(x), args) else: raise TypeError("mat4() arg can't be converted to mat4") # Check if there are really 16 elements in the list if len(self.mlist) != 16: raise TypeError( "mat4(): Wrong number of matrix elements (%s instead of 16)" % (len(self.mlist)))
def __div__(self, other): """Division >>> M=mat4(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16) >>> print M/2.0 [ 0.5000, 1.0000, 1.5000, 2.0000] [ 2.5000, 3.0000, 3.5000, 4.0000] [ 4.5000, 5.0000, 5.5000, 6.0000] [ 6.5000, 7.0000, 7.5000, 8.0000] """ T = type(other) # mat4/scalar if T==types.FloatType or T==types.IntType or T==types.LongType: return mat4(map(lambda x,other=other: x/other, self.mlist)) # unsupported else: raise TypeError("unsupported operand type for /")
def __div__(self, other): """Division >>> M=mat4(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16) >>> print M/2.0 [ 0.5000, 1.0000, 1.5000, 2.0000] [ 2.5000, 3.0000, 3.5000, 4.0000] [ 4.5000, 5.0000, 5.5000, 6.0000] [ 6.5000, 7.0000, 7.5000, 8.0000] """ T = type(other) # mat4/scalar if T == types.FloatType or T == types.IntType or T == types.LongType: return mat4(map(lambda x, other=other: x / other, self.mlist)) # unsupported else: raise TypeError, "unsupported operand type for /"
def __init__(self, *args): "Constructor" # No arguments if len(args)==0: self.mlist = 16*[0.0] # 1 argument (list, scalar or mat4) elif len(args)==1: T = type(args[0]) if T==types.FloatType or T==types.IntType or T==types.LongType: f = float(args[0]) self.mlist = [f,0.0,0.0,0.0, 0.0,f,0.0,0.0, 0.0,0.0,f,0.0, 0.0,0.0,0.0,f] # mat4 elif isinstance(args[0], mat4): self.mlist = copy.copy(args[0].mlist) # String elif T==types.StringType: s=args[0].replace(","," ").replace(" "," ").strip().split(" ") self.mlist=map(lambda x: float(x), s) else: self.mlist = mat4(*args[0]).mlist # 4 arguments (sequences) elif len(args)==4: a,b,c,d=args self.mlist = [a[0], b[0], c[0], d[0], a[1], b[1], c[1], d[1], a[2], b[2], c[2], d[2], a[3], b[3], c[3], d[3]] self.mlist = map(lambda x: float(x), self.mlist) # 16 arguments elif len(args)==16: self.mlist = map(lambda x: float(x), args) else: raise TypeError("mat4() arg can't be converted to mat4") # Check if there are really 16 elements in the list if len(self.mlist)!=16: raise TypeError("mat4(): Wrong number of matrix elements (%s instead of 16)"%(len(self.mlist)))
def inverse(self): """Return inverse matrix. >>> M=mat4(0,-2.0,0,0, 2.0,0,0,0, 0,0,2,0, 0,0,0,2) >>> print M.inverse() [ 0.0000, 0.5000, 0.0000, 0.0000] [ -0.5000, 0.0000, 0.0000, 0.0000] [ 0.0000, 0.0000, 0.5000, 0.0000] [ 0.0000, 0.0000, 0.0000, 0.5000] """ Mi = mat4() d = self.determinant() for i in xrange(4): for j in xrange(4): sign = 1 - ((i + j) % 2) * 2 m3 = self._submat(i, j) Mi[j, i] = sign * m3.determinant() / d return Mi
def inverse(self): """Return inverse matrix. >>> M=mat4(0,-2.0,0,0, 2.0,0,0,0, 0,0,2,0, 0,0,0,2) >>> print M.inverse() [ 0.0000, 0.5000, 0.0000, 0.0000] [ -0.5000, 0.0000, 0.0000, 0.0000] [ 0.0000, 0.0000, 0.5000, 0.0000] [ 0.0000, 0.0000, 0.0000, 0.5000] """ Mi=mat4() d=self.determinant() for i in range(4): for j in range(4): sign=1-((i+j)%2)*2 m3=self._submat(i,j) Mi[j,i]=sign*m3.determinant()/d return Mi
def orthographic(left, right, bottom, top, near, far): """Returns a matrix that represents an orthographic transformation. This method is equivalent to the OpenGL command glOrtho(). """ global _epsilon r_l = float(right - left) t_b = float(top - bottom) f_n = float(far - near) if r_l <= _epsilon: raise ValueError("right-value must be greater than left-value") if t_b <= _epsilon: raise ValueError("top-value must be greater than bottom-value") if f_n <= _epsilon: raise ValueError("far-value must be greater than near-value") return mat4(2.0 / r_l, 0.0, 0.0, -(right + left) / r_l, 0.0, 2.0 / t_b, 0.0, -(top + bottom) / t_b, 0.0, 0.0, -2.0 / f_n, -(far + near) / f_n, 0.0, 0.0, 0.0, 1.0)
def orthographic(left, right, bottom, top, near, far): """Returns a matrix that represents an orthographic transformation. This method is equivalent to the OpenGL command glOrtho(). """ global _epsilon r_l = float(right-left) t_b = float(top-bottom) f_n = float(far-near) if r_l<=_epsilon: raise ValueError("right-value must be greater than left-value") if t_b<=_epsilon: raise ValueError("top-value must be greater than bottom-value") if f_n<=_epsilon: raise ValueError("far-value must be greater than near-value") return mat4(2.0/r_l, 0.0, 0.0, -(right+left)/r_l, 0.0, 2.0/t_b, 0.0, -(top+bottom)/t_b, 0.0, 0.0, -2.0/f_n, -(far+near)/f_n, 0.0, 0.0, 0.0, 1.0)
def decompose(self): """Decomposes the matrix into a translation, rotation and scaling part. Returns a tuple (translation, rotation, scaling). The translation and scaling parts are given as vec3's, the rotation is still given as a mat4. """ try: dummy = self.ortho() except ZeroDivisionError: return (_vec3(0), mat4(1.0), _vec3(0)) dummy.setRow(3,_vec4(0.0, 0.0, 0.0, 1.0)) dummy.setColumn(3,_vec4(0.0, 0.0, 0.0, 1.0)) x = dummy.getColumn(0) y = dummy.getColumn(1) z = dummy.getColumn(2) xl = x.length() yl = y.length() zl = z.length() scale = _vec3(xl,yl,zl) x/=xl y/=yl z/=zl dummy.setColumn(0,x) dummy.setColumn(1,y) dummy.setColumn(2,z) if dummy.determinant()<0.0: dummy.setColumn(0,-x) scale.x=-scale.x return (_vec3(self.mlist[3], self.mlist[7], self.mlist[11]), dummy, scale)
def _pointup_adjust_mat(self): if hasattr(self, "pointup") and self.pointup: # Some primitives have different orientation in the editor compared to # the runtime environment (Maya along Y-axis, RGE along Z-axis). return mat4.rotation(-math.pi/2, vec3(1,0,0)) return mat4(1)
def translation(self, t): """Return translation matrix.""" return mat4(1.0, 0.0, 0.0, t.x, 0.0, 1.0, 0.0, t.y, 0.0, 0.0, 1.0, t.z, 0.0, 0.0, 0.0, 1.0)
def scaling(self, s): """Return scaling matrix.""" return mat4(s.x, 0.0, 0.0, 0.0, 0.0, s.y, 0.0, 0.0, 0.0, 0.0, s.z, 0.0, 0.0, 0.0, 0.0, 1.0)
def __mul__(self, other): """Multiplication. >>> M=mat4(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16) >>> print M*2.0 [ 2.0000, 4.0000, 6.0000, 8.0000] [ 10.0000, 12.0000, 14.0000, 16.0000] [ 18.0000, 20.0000, 22.0000, 24.0000] [ 26.0000, 28.0000, 30.0000, 32.0000] >>> print 2.0*M [ 2.0000, 4.0000, 6.0000, 8.0000] [ 10.0000, 12.0000, 14.0000, 16.0000] [ 18.0000, 20.0000, 22.0000, 24.0000] [ 26.0000, 28.0000, 30.0000, 32.0000] >>> print M*M [ 90.0000, 100.0000, 110.0000, 120.0000] [ 202.0000, 228.0000, 254.0000, 280.0000] [ 314.0000, 356.0000, 398.0000, 440.0000] [ 426.0000, 484.0000, 542.0000, 600.0000] >>> print M*_vec3(1,2,3) (0.1765, 0.4510, 0.7255) >>> print _vec3(1,2,3)*M (0.7083, 0.8056, 0.9028) """ T = type(other) # mat4*scalar if T==types.FloatType or T==types.IntType or T==types.LongType: return mat4(map(lambda x,other=other: x*other, self.mlist)) # mat4*vec3 if isinstance(other, _vec3): m11,m12,m13,m14,m21,m22,m23,m24,m31,m32,m33,m34,m41,m42,m43,m44 = self.mlist w = float(m41*other.x + m42*other.y + m43*other.z + m44) return _vec3(m11*other.x + m12*other.y + m13*other.z + m14, m21*other.x + m22*other.y + m23*other.z + m24, m31*other.x + m32*other.y + m33*other.z + m34)/w # mat4*vec4 if isinstance(other, _vec4): m11,m12,m13,m14,m21,m22,m23,m24,m31,m32,m33,m34,m41,m42,m43,m44 = self.mlist return _vec4(m11*other.x + m12*other.y + m13*other.z + m14*other.w, m21*other.x + m22*other.y + m23*other.z + m24*other.w, m31*other.x + m32*other.y + m33*other.z + m34*other.w, m41*other.x + m42*other.y + m43*other.z + m44*other.w) # mat4*mat4 if isinstance(other, mat4): m11,m12,m13,m14,m21,m22,m23,m24,m31,m32,m33,m34,m41,m42,m43,m44 = self.mlist n11,n12,n13,n14,n21,n22,n23,n24,n31,n32,n33,n34,n41,n42,n43,n44 = other.mlist return mat4( m11*n11+m12*n21+m13*n31+m14*n41, m11*n12+m12*n22+m13*n32+m14*n42, m11*n13+m12*n23+m13*n33+m14*n43, m11*n14+m12*n24+m13*n34+m14*n44, m21*n11+m22*n21+m23*n31+m24*n41, m21*n12+m22*n22+m23*n32+m24*n42, m21*n13+m22*n23+m23*n33+m24*n43, m21*n14+m22*n24+m23*n34+m24*n44, m31*n11+m32*n21+m33*n31+m34*n41, m31*n12+m32*n22+m33*n32+m34*n42, m31*n13+m32*n23+m33*n33+m34*n43, m31*n14+m32*n24+m33*n34+m34*n44, m41*n11+m42*n21+m43*n31+m44*n41, m41*n12+m42*n22+m43*n32+m44*n42, m41*n13+m42*n23+m43*n33+m44*n43, m41*n14+m42*n24+m43*n34+m44*n44) # unsupported else: raise TypeError("unsupported operand type for *")
def __mul__(self, other): """Multiplication. >>> M=mat4(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16) >>> print M*2.0 [ 2.0000, 4.0000, 6.0000, 8.0000] [ 10.0000, 12.0000, 14.0000, 16.0000] [ 18.0000, 20.0000, 22.0000, 24.0000] [ 26.0000, 28.0000, 30.0000, 32.0000] >>> print 2.0*M [ 2.0000, 4.0000, 6.0000, 8.0000] [ 10.0000, 12.0000, 14.0000, 16.0000] [ 18.0000, 20.0000, 22.0000, 24.0000] [ 26.0000, 28.0000, 30.0000, 32.0000] >>> print M*M [ 90.0000, 100.0000, 110.0000, 120.0000] [ 202.0000, 228.0000, 254.0000, 280.0000] [ 314.0000, 356.0000, 398.0000, 440.0000] [ 426.0000, 484.0000, 542.0000, 600.0000] >>> print M*_vec3(1,2,3) (0.1765, 0.4510, 0.7255) >>> print _vec3(1,2,3)*M (0.7083, 0.8056, 0.9028) """ T = type(other) # mat4*scalar if T == types.FloatType or T == types.IntType or T == types.LongType: return mat4(map(lambda x, other=other: x * other, self.mlist)) # mat4*vec3 if isinstance(other, _vec3): m11, m12, m13, m14, m21, m22, m23, m24, m31, m32, m33, m34, m41, m42, m43, m44 = self.mlist w = float(m41 * other.x + m42 * other.y + m43 * other.z + m44) return _vec3( m11 * other.x + m12 * other.y + m13 * other.z + m14, m21 * other.x + m22 * other.y + m23 * other.z + m24, m31 * other.x + m32 * other.y + m33 * other.z + m34) / w # mat4*vec4 if isinstance(other, _vec4): m11, m12, m13, m14, m21, m22, m23, m24, m31, m32, m33, m34, m41, m42, m43, m44 = self.mlist return _vec4( m11 * other.x + m12 * other.y + m13 * other.z + m14 * other.w, m21 * other.x + m22 * other.y + m23 * other.z + m24 * other.w, m31 * other.x + m32 * other.y + m33 * other.z + m34 * other.w, m41 * other.x + m42 * other.y + m43 * other.z + m44 * other.w) # mat4*mat4 if isinstance(other, mat4): m11, m12, m13, m14, m21, m22, m23, m24, m31, m32, m33, m34, m41, m42, m43, m44 = self.mlist n11, n12, n13, n14, n21, n22, n23, n24, n31, n32, n33, n34, n41, n42, n43, n44 = other.mlist return mat4(m11 * n11 + m12 * n21 + m13 * n31 + m14 * n41, m11 * n12 + m12 * n22 + m13 * n32 + m14 * n42, m11 * n13 + m12 * n23 + m13 * n33 + m14 * n43, m11 * n14 + m12 * n24 + m13 * n34 + m14 * n44, m21 * n11 + m22 * n21 + m23 * n31 + m24 * n41, m21 * n12 + m22 * n22 + m23 * n32 + m24 * n42, m21 * n13 + m22 * n23 + m23 * n33 + m24 * n43, m21 * n14 + m22 * n24 + m23 * n34 + m24 * n44, m31 * n11 + m32 * n21 + m33 * n31 + m34 * n41, m31 * n12 + m32 * n22 + m33 * n32 + m34 * n42, m31 * n13 + m32 * n23 + m33 * n33 + m34 * n43, m31 * n14 + m32 * n24 + m33 * n34 + m34 * n44, m41 * n11 + m42 * n21 + m43 * n31 + m44 * n41, m41 * n12 + m42 * n22 + m43 * n32 + m44 * n42, m41 * n13 + m42 * n23 + m43 * n33 + m44 * n43, m41 * n14 + m42 * n24 + m43 * n34 + m44 * n44) # unsupported else: raise TypeError, "unsupported operand type for *"