Permalink
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
199 lines (165 sloc) 5.1 KB
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
Very simple transformation library that is needed for some examples.
"""
from __future__ import division
# Note: we use functions (e.g. sin) from math module because they're faster
import math
import numpy as np
def translate(offset, dtype=None):
"""Translate by an offset (x, y, z) .
Parameters
----------
offset : array-like, shape (3,)
Translation in x, y, z.
dtype : dtype | None
Output type (if None, don't cast).
Returns
-------
M : ndarray
Transformation matrix describing the translation.
"""
assert len(offset) == 3
x, y, z = offset
M = np.array([[1., 0., 0., 0.],
[0., 1., 0., 0.],
[0., 0., 1., 0.],
[x, y, z, 1.0]], dtype)
return M
def scale(s, dtype=None):
"""Non-uniform scaling along the x, y, and z axes
Parameters
----------
s : array-like, shape (3,)
Scaling in x, y, z.
dtype : dtype | None
Output type (if None, don't cast).
Returns
-------
M : ndarray
Transformation matrix describing the scaling.
"""
assert len(s) == 3
return np.array(np.diag(np.concatenate([s, (1.,)])), dtype)
def rotate(angle, axis, dtype=None):
"""The 3x3 rotation matrix for rotation about a vector.
Parameters
----------
angle : float
The angle of rotation, in degrees.
axis : ndarray
The x, y, z coordinates of the axis direction vector.
"""
angle = np.radians(angle)
assert len(axis) == 3
x, y, z = axis / np.linalg.norm(axis)
c, s = math.cos(angle), math.sin(angle)
cx, cy, cz = (1 - c) * x, (1 - c) * y, (1 - c) * z
M = np.array([[cx * x + c, cy * x - z * s, cz * x + y * s, .0],
[cx * y + z * s, cy * y + c, cz * y - x * s, 0.],
[cx * z - y * s, cy * z + x * s, cz * z + c, 0.],
[0., 0., 0., 1.]], dtype).T
return M
def ortho(left, right, bottom, top, znear, zfar):
"""Create orthographic projection matrix
Parameters
----------
left : float
Left coordinate of the field of view.
right : float
Right coordinate of the field of view.
bottom : float
Bottom coordinate of the field of view.
top : float
Top coordinate of the field of view.
znear : float
Near coordinate of the field of view.
zfar : float
Far coordinate of the field of view.
Returns
-------
M : ndarray
Orthographic projection matrix (4x4).
"""
assert(right != left)
assert(bottom != top)
assert(znear != zfar)
M = np.zeros((4, 4), dtype=np.float32)
M[0, 0] = +2.0 / (right - left)
M[3, 0] = -(right + left) / float(right - left)
M[1, 1] = +2.0 / (top - bottom)
M[3, 1] = -(top + bottom) / float(top - bottom)
M[2, 2] = -2.0 / (zfar - znear)
M[3, 2] = -(zfar + znear) / float(zfar - znear)
M[3, 3] = 1.0
return M
def frustum(left, right, bottom, top, znear, zfar):
"""Create view frustum
Parameters
----------
left : float
Left coordinate of the field of view.
right : float
Right coordinate of the field of view.
bottom : float
Bottom coordinate of the field of view.
top : float
Top coordinate of the field of view.
znear : float
Near coordinate of the field of view.
zfar : float
Far coordinate of the field of view.
Returns
-------
M : ndarray
View frustum matrix (4x4).
"""
assert(right != left)
assert(bottom != top)
assert(znear != zfar)
M = np.zeros((4, 4), dtype=np.float32)
M[0, 0] = +2.0 * znear / float(right - left)
M[2, 0] = (right + left) / float(right - left)
M[1, 1] = +2.0 * znear / float(top - bottom)
M[2, 1] = (top + bottom) / float(top - bottom)
M[2, 2] = -(zfar + znear) / float(zfar - znear)
M[3, 2] = -2.0 * znear * zfar / float(zfar - znear)
M[2, 3] = -1.0
return M
def perspective(fovy, aspect, znear, zfar):
"""Create perspective projection matrix
Parameters
----------
fovy : float
The field of view along the y axis.
aspect : float
Aspect ratio of the view.
znear : float
Near coordinate of the field of view.
zfar : float
Far coordinate of the field of view.
Returns
-------
M : ndarray
Perspective projection matrix (4x4).
"""
assert(znear != zfar)
h = math.tan(fovy / 360.0 * math.pi) * znear
w = h * aspect
return frustum(-w, w, -h, h, znear, zfar)
def affine_map(points1, points2):
""" Find a 3D transformation matrix that maps points1 onto points2.
Arguments are specified as arrays of four 3D coordinates, shape (4, 3).
"""
A = np.ones((4, 4))
A[:, :3] = points1
B = np.ones((4, 4))
B[:, :3] = points2
# solve 3 sets of linear equations to determine
# transformation matrix elements
matrix = np.eye(4)
for i in range(3):
# solve Ax = B; x is one row of the desired transformation matrix
matrix[i] = np.linalg.solve(A, B[:, i])
return matrix