[QUOTE=GClements;1280454]Here is what I use.
import math
import numpy as np
def transform(m, v):
return np.asarray(m * np.asmatrix(v).T)[:,0]
def magnitude(v):
return math.sqrt(np.sum(v ** 2))
def normalize(v):
m = magnitude(v)
if m == 0:
return v
return v / m
def ortho(l, r, b, t, n, f):
dx = r - l
dy = t - b
dz = f - n
rx = -(r + l) / (r - l)
ry = -(t + b) / (t - b)
rz = -(f + n) / (f - n)
return np.matrix([[2.0/dx,0,0,rx],
[0,2.0/dy,0,ry],
[0,0,-2.0/dz,rz],
[0,0,0,1]])
def perspective(fovy, aspect, n, f):
s = 1.0/math.tan(math.radians(fovy)/2.0)
sx, sy = s / aspect, s
zz = (f+n)/(n-f)
zw = 2*f*n/(n-f)
return np.matrix([[sx,0,0,0],
[0,sy,0,0],
[0,0,zz,zw],
[0,0,-1,0]])
def frustum(x0, x1, y0, y1, z0, z1):
a = (x1+x0)/(x1-x0)
b = (y1+y0)/(y1-y0)
c = -(z1+z0)/(z1-z0)
d = -2*z1*z0/(z1-z0)
sx = 2*z0/(x1-x0)
sy = 2*z0/(y1-y0)
return np.matrix([[sx, 0, a, 0],
[ 0,sy, b, 0],
[ 0, 0, c, d],
[ 0, 0,-1, 0]])
def translate(xyz):
x, y, z = xyz
return np.matrix([[1,0,0,x],
[0,1,0,y],
[0,0,1,z],
[0,0,0,1]])
def scale(xyz):
x, y, z = xyz
return np.matrix([[x,0,0,0],
[0,y,0,0],
[0,0,z,0],
[0,0,0,1]])
def sincos(a):
a = math.radians(a)
return math.sin(a), math.cos(a)
def rotate(a, xyz):
x, y, z = normalize(xyz)
s, c = sincos(a)
nc = 1 - c
return np.matrix([[x*x*nc + c, x*y*nc - z*s, x*z*nc + y*s, 0],
[y*x*nc + z*s, y*y*nc + c, y*z*nc - x*s, 0],
[x*z*nc - y*s, y*z*nc + x*s, z*z*nc + c, 0],
[ 0, 0, 0, 1]])
def rotx(a):
s, c = sincos(a)
return np.matrix([[1,0,0,0],
[0,c,-s,0],
[0,s,c,0],
[0,0,0,1]])
def roty(a):
s, c = sincos(a)
return np.matrix([[c,0,s,0],
[0,1,0,0],
[-s,0,c,0],
[0,0,0,1]])
def rotz(a):
s, c = sincos(a)
return np.matrix([[c,-s,0,0],
[s,c,0,0],
[0,0,1,0],
[0,0,0,1]])
def lookat(eye, target, up):
F = target[:3] - eye[:3]
f = normalize(F)
U = normalize(up[:3])
s = np.cross(f, U)
u = np.cross(s, f)
M = np.matrix(np.identity(4))
M[:3,:3] = np.vstack([s,u,-f])
T = translate(-eye)
return M * T
def viewport(x, y, w, h):
x, y, w, h = map(float, (x, y, w, h))
return np.matrix([[w/2, 0 , 0,x+w/2],
[0 , h/2, 0,y+h/2],
[0 , 0 , 1, 0],
[0 , 0 , 0, 1]])
Functions which are named similarly to OpenGL/GLU functions have the same conventions (and in many cases, the matrices were taken directly from the OpenGL reference pages).
A note about NumPy matrices: if you transpose the matrix using the .transpose() method or the .T property, you need to use np.ascontiguousarray() to actually re-order the data. Alternatively, you can just use np.asfortranarray() to store the matrix in column-major order. PyOpenGL simply passes a pointer to the underlying buffer, so array views created e.g. by transposition or slicing won’t behave as expected.[/QUOTE]
I tried the lookat and perspective functions but, now, my cube looks like a pyramid and I do not know what’s causing this.
Here is the code of my timer function:
def timer(fps):
global clock
clock += 0.0005*1000.0/fps
theta = clock;
matModel = rotate(theta*180/np.pi, np.array([1,1,1]))
eye = np.array([0,0,1])
target = np.array([0,0,0])
up = np.array([0,1,0])
matView = lookat(eye, target, up)
#matView = np.eye(4)
matProjection = perspective(fovy=45.0, aspect=4/3, n=-3, f=100.0)
#matProjection = np.eye(4)
loc = gl.glGetUniformLocation(program, "Model")
gl.glUniformMatrix4fv(loc, 1, False, np.asfortranarray(matModel))
loc = gl.glGetUniformLocation(program, "View")
gl.glUniformMatrix4fv(loc, 1, False, np.asfortranarray(matView))
loc = gl.glGetUniformLocation(program, "Projection")
gl.glUniformMatrix4fv(loc, 1, False, np.asfortranarray(matProjection))
glut.glutTimerFunc(1000/fps, timer, fps)
glut.glutPostRedisplay()
My display function:
def display():
gl.glClear(gl.GL_COLOR_BUFFER_BIT | gl.GL_DEPTH_BUFFER_BIT)
#gl.glDrawArrays(gl.GL_TRIANGLES, 0, 12)
gl.glEnable(gl.GL_DEPTH_TEST)
gl.glDepthFunc(gl.GL_LESS)
gl.glDrawElements(gl.GL_TRIANGLES, len(index), gl.GL_UNSIGNED_INT, ctypes.c_void_p(0))
glut.glutSwapBuffers()
The vertices and indices of my cube:
positions = [ (-1,-1,1),
(1,-1,1),
(1,1,1),
(-1,1,1),
(-1,-1,-1),
(1,-1,-1),
(1,1,-1),
(-1,1,-1)]
index = np.array([0,1,2,
2,3,0,
1,5,6,
6,2,1,
7,6,5,
5,4,7,
4,0,3,
3,7,4,
4,5,1,
1,0,4,
3,2,6,
6,7,3], dtype=np.uint32)
and my shaders:
vertex_code = """
#version 330 core
uniform float scale;
uniform mat4 Model;
uniform mat4 View;
uniform mat4 Projection;
in vec4 color;
in vec3 position;
out vec4 v_color;
void main()
{
gl_Position = Projection*View*Model*vec4(scale*position, 1.0);
v_color = color;
} """
fragment_code = """
#version 330 core
in vec4 v_color;
void main()
{
gl_FragColor = v_color;
} """