I am just trying to learn to draw 3d objects with pyopengl. The first thing I am trying to draw is the following code. The coordinates posat, i.e. the positon of atom is supposed to be a bcc lattice, but I am far from getting anything like a cube. The output is added.
Kindly let me know what I am doing wring here:
#!/usr/bin/env python
import math
import sys
import ase
import ase.io.vasp
import pygame
from OpenGL.GL import *
from OpenGL.GLU import *
from pygame.locals import *
# inpfile = sys.argv[1]
# cell = ase.io.vasp.read_vasp(inpfile)
# numat = len(cell.get_positions())
# posat = cell.get_positions()
posat = [[0, 0, 0], [1, 0, 0], [0, 1, 0], [0, 0, 1], [.5, .5, .5], [1, 1, 0],
[0, 1, 1], [1, 0, 1], [1, 1, 1]]
numat = len(posat)
print(posat)
# print(posat[1][0])
pygame.init()
pygame.display.set_caption('vcrys')
display = (1000, 750)
scree = pygame.display.set_mode(display, DOUBLEBUF | OPENGL)
glEnable(GL_DEPTH_TEST)
glEnable(GL_LIGHTING)
glShadeModel(GL_SMOOTH)
glEnable(GL_COLOR_MATERIAL)
glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE)
glEnable(GL_LIGHT0)
glLightfv(GL_LIGHT0, GL_AMBIENT, [0.5, 0.5, 0.5, 1])
glLightfv(GL_LIGHT0, GL_DIFFUSE, [1.0, 1.0, 1.0, 1])
sphere = gluNewQuadric()
def atoms(qx, qy, qz, cr, cg, cb, r):
glTranslatef(qx, qy, qz)
glColor4f(cr, cg, cb, 1)
gluSphere(sphere, r, 1080, 1080)
glMatrixMode(GL_PROJECTION)
gluPerspective(45, (display[0] / display[1]), 0.01, 50.0)
glMatrixMode(GL_MODELVIEW)
gluLookAt(0, -10, 0, 0, 0, 0, 0, 0, 1)
viewMatrix = glGetFloatv(GL_MODELVIEW_MATRIX)
glLoadIdentity()
# init mouse movement and center mouse on screen
displayCenter = [scree.get_size()[i] // 2 for i in range(2)]
mouseMove = [0, 0]
pygame.mouse.set_pos(displayCenter)
up_down_angle = 0.0
paused = False
run = True
while run:
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE or event.key == pygame.K_RETURN:
run = False
if event.key == pygame.K_PAUSE or event.key == pygame.K_p:
paused = not paused
pygame.mouse.set_pos(displayCenter)
if not paused:
if event.type == pygame.MOUSEMOTION:
mouseMove = [event.pos[i] - displayCenter[i] for i in range(2)]
pygame.mouse.set_pos(displayCenter)
if not paused:
# get keys
keypress = pygame.key.get_pressed()
# mouseMove = pygame.mouse.get_rel()
# init model view matrix
glLoadIdentity()
# apply the look up and down
# up_down_angle += mouseMove[1] * 0.0001
# glRotatef(up_down_angle, .10, 0.0, 0.0)
# init the view matrix
glPushMatrix()
glLoadIdentity()
# apply the movment
if keypress[pygame.K_w]:
glTranslatef(0, 0, 0.1)
if keypress[pygame.K_s]:
glTranslatef(0, 0, -0.1)
if keypress[pygame.K_d]:
glTranslatef(-0.1, 0, 0)
if keypress[pygame.K_a]:
glTranslatef(0.1, 0, 0)
if keypress[pygame.K_u]:
glTranslatef(0.0, 0.1, 0)
if keypress[pygame.K_l]:
glTranslatef(0, -0.1, 0)
# apply the left and right rotation
# glRotatef(mouseMove[0] * 0.01, 0.0, .01, 0.0)
# multiply the current matrix by the get the new view matrix and store the final vie matrix
glMultMatrixf(viewMatrix)
viewMatrix = glGetFloatv(GL_MODELVIEW_MATRIX)
# apply view matrix
glPopMatrix()
glMultMatrixf(viewMatrix)
glLightfv(GL_LIGHT0, GL_POSITION, [1, -1, 1, 0])
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
glPushMatrix()
for a in range(numat):
atoms(posat[a][0], posat[a][1], posat[a][2], 1, 1, 1, 1 / 10)
# atoms(qx=0, cr=0, qy=0, cg=.5, qz=.2, cb=.2, r=1)
# atoms(-3, 0, 0, .2, .2, .5, 1)
glPopMatrix()
pygame.display.flip()
# paused = True
# pygame.time.wait(10)
pygame.quit()
glTranslate defines a translation matrix and multiplies the current matrix with the new translation matrix. Hence all the translations are concatenated.
Use glPushMatrix/glPopMatrx to save the current matrix before specifying the translation and to restore the current matrix after drawing the atom:
def atoms(qx, qy, qz, cr, cg, cb, r):
glPushMatrix()
glTranslatef(qx, qy, qz)
glColor4f(cr, cg, cb, 1)
gluSphere(sphere, r, 1080, 1080)
glPopMatrix()
Related
I am pretty new in using PyOpenGL and I want to load an obj file, move it, then draw a sphere and move it. I want the two objects to move separately when I use different keyboard buttons. Is it possible? (I also need the coordinate of the center of each object).
The problem is that they both move even if I use Push and Pop matrix commands
Here is my code:
rom objloader import *
def main():
pygame.init()
display = (800,600)
pygame.display.set_mode(display, OPENGL | DOUBLEBUF)
glMatrixMode(GL_PROJECTION)
gluPerspective(45.0, display[0]/display[1], 0.1, 100.0)
glLightfv(GL_LIGHT5, GL_POSITION, (-40, 200, 100, 0.0))
glLightfv(GL_LIGHT5, GL_AMBIENT, (0.2, 0.2, 0.2, 1.0))
glLightfv(GL_LIGHT5, GL_DIFFUSE, (0.5, 0.5, 0.5, 1.0))
glEnable(GL_LIGHT5)
glEnable(GL_LIGHTING)
glEnable(GL_COLOR_MATERIAL)
glEnable(GL_DEPTH_TEST)
glShadeModel(GL_SMOOTH)
glMatrixMode(GL_MODELVIEW)
glTranslatef(0, 0, -5)
x = 0
y = 0
z = - 5
xx = 0
yy = 0
zz = -5
# LOAD OBJECT
obj = OBJ(sys.argv[1], swapyz=True)
sphere = gluNewQuadric() #Create new sphere
model = glGetDoublev(GL_MODELVIEW_MATRIX)
rx, ry = (0,0)
tx, ty = (0,0)
zpos = 5
rotate = move = False
clock = pygame.time.Clock()
while 1:
clock.tick(30)
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT) #Clear the screen
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE or event.key == pygame.K_RETURN:
sys.exit()
keypress = pygame.key.get_pressed()
glMatrixMode(GL_MODELVIEW)
glPushMatrix()
glLoadIdentity()
if keypress[pygame.K_w]:
glTranslatef(0,-0.01,0)
y = y - 0.01
if keypress[pygame.K_s]:
glTranslatef(0,0.01,0)
y = y + 0.01
if keypress[pygame.K_d]:
glTranslatef(0.01,0,0)
x = x + 0.01
if keypress[pygame.K_a]:
glTranslatef(-0.01,0,0)
x = x - 0.01
if keypress[pygame.K_z]:
glTranslatef(0, 0, -0.01)
z = z - 0.01
if keypress[pygame.K_x]:
glTranslatef(0,0,0.01)
z = z + 0.01
if keypress[pygame.K_0]:
start = x, y, z
print('start is', start)
#model = glGetDoublev(GL_MODELVIEW_MATRIX)
glMultMatrixf(model)
model = glGetDoublev(GL_MODELVIEW_MATRIX)
glMultMatrixf(model)
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)
glScalef(0.1, 0.1, 0.1)
glColor4f(0.5, 0.2, 0.2, 1)
gluSphere(sphere, 1.0, 32, 16)
glPopMatrix()
glPushMatrix()
glLoadIdentity()
if keypress[pygame.K_u]:
glTranslatef(0,-0.01,0)
yy = yy - 0.01
if keypress[pygame.K_j]:
glTranslatef(0,0.01,0)
yy = yy + 0.01
if keypress[pygame.K_k]:
glTranslatef(0.01,0,0)
xx = xx + 0.01
if keypress[pygame.K_h]:
glTranslatef(-0.01,0,0)
xx = xx - 0.01
if keypress[pygame.K_n]:
glTranslatef(0, 0, -0.01)
zz = zz - 0.01
if keypress[pygame.K_m]:
glTranslatef(0,0,0.01)
zz = zz + 0.01
if keypress[pygame.K_l]:
glRotatef(1, 0, 1, 5)
xx = xx*math.cos(rad)-y*math.sin(rad)
yy = xx*math.sin(rad)+yy*math.cos(rad)
if keypress[pygame.K_g]:
#glTranslatef(xx, yy, zz)
glRotatef(1, 0, 1, -5)
#glTranslatef(-xx, -yy, -zz)
rad = 1*180/math.pi
xx = xx*math.cos(rad)-yy*math.sin(rad)
yy = xx*math.sin(rad)+yy*math.cos(rad)
print(xx, yy, math.sin( rad))
if keypress [pygame.K_9]:
print('obj coord', xx, yy, zz)
glMultMatrixf(model)
model = glGetDoublev(GL_MODELVIEW_MATRIX)
glMultMatrixf(model)
#glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT) --> se lo metti non vedi l'oggetto prima
glScalef(0.1, 0.1, 0.1)
glCallList(obj.gl_list)
glPopMatrix()
pygame.display.flip() #Update the screen
main()
The problem is that they both move even if I use Push and Pop matrix commands
The model matrix defines the position orientation and scale of a single object (mesh) in the scene. Thus you need a separate model matrix for each object:
def main():
# [...]
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
gluPerspective(45.0, display[0]/display[1], 0.1, 100.0)
glMatrixMode(GL_MODELVIEW)
glLoadIdentity()
glTranslatef(0, 0, -5)
model_1 = glGetDoublev(GL_MODELVIEW_MATRIX)
model_2 = model_1
# [...]
while 1:
# [...]
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)
glMatrixMode(GL_MODELVIEW)
# Model 1
glPushMatrix()
glLoadIdentity()
# rotate and translate model 1
# [...]
glMultMatrixf(model_1)
model_1 = glGetDoublev(GL_MODELVIEW_MATRIX)
glScalef(0.1, 0.1, 0.1)
# draw model 1
glColor4f(0.5, 0.2, 0.2, 1)
gluSphere(sphere, 1.0, 32, 16)
glPopMatrix()
# Model 2
glPushMatrix()
glLoadIdentity()
# rotate and translate model 2
# [...]
glMultMatrixf(model_2)
model_2 = glGetDoublev(GL_MODELVIEW_MATRIX)
glScalef(0.1, 0.1, 0.1)
# draw model 1
glCallList(obj.gl_list)
glPopMatrix()
pygame.display.flip() #Update the screen
Write a PYOpenGL code for this operation.
I am able to draw the circle but my code for rotating and translating is not working. The code is executing but not giving the correct result. Help me with the rotation and translation part of the question.
from OpenGL.GL import *
from OpenGL.GLUT import *
from OpenGL.GLU import *
from math import *
def circle():
posx, posy = 40,40
sides = 80
radius = 20
glBegin(GL_POLYGON)
for i in range(100):
cosine= radius * cos(i*2*pi/sides) + posx
sine = radius * sin(i*2*pi/sides) + posy
glVertex2f(cosine,sine)
glEnd()
def iterate():
glViewport(0, 0, 3000, 3000)
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
# glMatrixMode(GL_MODELVIEW)
# glLoadIdentity()
# glTranslatef(0, 0, -3)
# glRotatef(50, 1, 0, 0)
# glRotatef(70, 0, 1, 0)
glOrtho(0.0, 500, 0.0, 500, 0.0, 1.0)
glMatrixMode (GL_MODELVIEW)
glLoadIdentity()
def showScreen():
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
glLoadIdentity()
iterate()
glColor3f(1.0, 0.0, 3.0)
circle()
glutSwapBuffers()
glutInit()
glutInitDisplayMode(GLUT_RGBA)
glutInitWindowSize(400, 400)
glutInitWindowPosition(200, 200)
wind = glutCreateWindow("OpenGL Coding Practice")
glutDisplayFunc(showScreen)
glutIdleFunc(showScreen)
glutMainLoop()
When you transalte the circle along the z axis or rotate the circle it is clipped by the near (= 0) and far plane (= 1) of the Orthographic projection.
Change the distance to the near and far plane (e.g. -100 and 100):
glOrtho(0.0, 500, 0.0, 500, 0.0, 1.0)
glOrtho(0.0, 500, 0.0, 500, -100, 100)
iterate function:
def iterate():
glViewport(0, 0, 3000, 3000)
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
glOrtho(0.0, 500, 0.0, 500, -100, 100)
glMatrixMode (GL_MODELVIEW)
glLoadIdentity()
glTranslatef(0, 0, 20)
glRotatef(30, 1, 0, 0)
I am working on rotating a triangle, under the premise that it does not touch the render part(i think this problem can't using camera)
I want the axis that rotates in the above state to be the center (based on world coordinates (0,0)) rather than local space. When the triangle is not at 0,0 .
this is my code
import glfw
from OpenGL.GL import *
from OpenGL.GLU import *
import numpy as np
def render(T):
glClear(GL_COLOR_BUFFER_BIT)
glLoadIdentity()
# draw cooridnate
glBegin(GL_LINES)
glColor3ub(255, 0, 0)
glVertex2fv(np.array([0.,0.]))
glVertex2fv(np.array([1.,0.]))
glColor3ub(0, 255, 0)
glVertex2fv(np.array([0.,0.]))
glVertex2fv(np.array([0.,1.]))
glEnd()
# draw triangle
glBegin(GL_TRIANGLES)
glColor3ub(255, 255, 255)
glVertex2fv( (T # np.array([.0,.5,1.]))[:-1] )
glVertex2fv( (T # np.array([.0,.0,1.]))[:-1] )
glVertex2fv( (T # np.array([.5,.0,1.]))[:-1] )
glEnd()
def main():
if not glfw.init():
return
window = glfw.create_window(480,480,"1234", None,None)
if not window:
glfw.terminate()
return
glfw.make_context_current(window)
glfw.swap_interval(1)
while not glfw.window_should_close(window):
glfw.poll_events()
t = glfw.get_time()
s= np.sin(t)
q = np.array([[np.cos(t),-np.sin(t),.3],
[np.sin(t), np.cos(t),.3],
[0., 0., 0.]])
#th = np.radians(60)
#R = np.array([[np.cos(th), -np.sin(th),0.],
# [np.sin(th), np.cos(th),0.],
# [0., 0., 1.]])
#T = np.array([[1.,0.,.4],
# [0.,1.,.1],
# [0.,0.,1.]])
render(q)
glfw.swap_buffers(window)
glfw.terminate()
if __name__ == "__main__":
main()
-> This is my current state rotate, but not world space (0,0)
If you want to rotate and object around a pivot point:
Move the object so that the pivot point is at (0, 0).
Rotate the object
Move the object to its position in the world.
def main():
# [...]
while not glfw.window_should_close(window):
glfw.poll_events()
t = glfw.get_time()
pivot = (0.15, 0.15)
world_pos = (0.5, 0.5)
trans_pivot = np.array([[1, 0, -pivot[0]], [0, 1, -pivot[1]], [0, 0, 1]])
rotate = np.array([[np.cos(t),-np.sin(t), 0.0],
[np.sin(t), np.cos(t), 0.0],
[0, 0, 1]])
trans_world = np.array([[1, 0, world_pos[0]], [0, 1, world_pos[0]], [0, 0, 1]])
q = trans_world # rotate # trans_pivot
render(q)
glfw.swap_buffers(window)
So I'm learning OpenGL using pyglet and I'm importing some models from Blender using Assimp ( port: Pyassimp). So the scene is really basic, it is just 2 cubes and I'm saving it in blend format.In the next piece of code I'm just trying to draw one cube simply using its vertex positions, nothing else.
self.scene = pyassimp.load(FILENAME, pyassimp.postprocess.aiProcess_Triangulate) # Load the scene
self.vertices = numpy.array((), dtype=GLfloat)
for v in self.scene.meshes[1].vertices:
self.vertices = numpy.append(self.vertices, v)
self.vbo = pyglet.graphics.vertexbuffer.create_buffer(self.vertices.nbytes, GL_ARRAY_BUFFER, GL_STATIC_DRAW)
glEnableVertexAttribArray(0)
self.vbo.bind()
self.vbo.set_data(self.vertices.ctypes.data)
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0)
And next piece of code is the draw event:
glMatrixMode(GL_MODELVIEW)
glLoadIdentity()
glEnable(GL_DEPTH_TEST)
glEnable(GL_COLOR_MATERIAL)
glEnable(GL_LIGHTING)
glEnable(GL_LIGHT0)
glLightfv(GL_LIGHT0, GL_POSITION, self.lightfv(1.0, 1.0, 1.0, 1.0))
glLightfv(GL_LIGHT0, GL_AMBIENT, self.lightfv(0.0, 0.0, 0.0, 1.0))
glLightfv(GL_LIGHT0, GL_DIFFUSE, self.lightfv(1.0, 1.0, 1.0, 1.0))
glLightfv(GL_LIGHT0, GL_SPECULAR, self.lightfv(1.0, 1.0, 1.0, 1.0))
glTranslated(0, 10, -25)
glRotatef(self.rotation, 0, 1, 0)
glDrawArrays(GL_TRIANGLES, 0, len(self.model.vertices))
Finally the result:
You have to loop over the faces of the mesh, read the vertex index from there and then draw the faces.
See the C example of assimp. It's quite simple, shows how to do and can very easy be ported to python.
https://github.com/assimp/assimp/blob/master/samples/SimpleOpenGL/Sample_SimpleOpenGL.c
For pyglet you can use the following snipped:
for node in self.scene.rootnode.children:
glPushMatrix()
glMultMatrixf((GLfloat * 16)(*node.transformation.transpose().flatten()))
for mesh in node.meshes:
for face in mesh.faces:
num_indices = len(face)
if num_indices == 1:
mode = GL_POINTS
elif num_indices == 2:
mode = GL_LINES
elif num_indices == 3:
mode = GL_TRIANGLES
else:
mode = GL_POLYGON
pyglet.graphics.draw_indexed(len(mesh.vertices), mode, face, ('v3f', mesh.vertices.flatten()))
glPopMatrix()
I've been trying to render a simple teapot with PyOpenGL, but have been running into strange issues. I can't seem to figure out exactly where the error originates from, despite the simplicity of the code.
Main.py
import pygame
from pygame.locals import *
from MV import *
import ctypes
from OpenGL.GL import *
from OpenGL.GL import shaders
from OpenGL.GLU import *
import teapot as tp
vertex_shader = '''
#version 420
in vec3 vpos_modelspace;
in vec3 vnorm_modelspace;
uniform mat4 mvp;
out vec4 vertcolor;
void main(){
vertcolor = vec4(vnorm_modelspace, 1.0);
gl_Position = mvp * vec4(vpos_modelspace, 1.0);
}
'''
fragment_shader = '''
#version 420
in vec4 vertcolor;
out vec4 fragcolor;
void main(){
fragcolor = vertcolor;
}
'''
model = tp.teapot
pygame.init()
canvas = pygame.display.set_mode((800, 600), DOUBLEBUF|OPENGL)
pygame.display.set_caption('Test')
glClearColor(.5, .5, .5, 1)
glEnable(GL_DEPTH_TEST)
glDepthFunc(GL_LESS)
glDisable(GL_CULL_FACE)
VERTEXSHADER = shaders.compileShader(vertex_shader, GL_VERTEX_SHADER)
FRAGMENTSHADER = shaders.compileShader(fragment_shader, GL_FRAGMENT_SHADER)
program = shaders.compileProgram(VERTEXSHADER, FRAGMENTSHADER)
glUseProgram(program)
vpos_loc = glGetAttribLocation(program, 'vpos_modelspace')
vnorm_loc = glGetAttribLocation(program, 'vnorm_modelspace')
mvp_loc = glGetUniformLocation(program, 'mvp')
eye = numpy.array([0, 0, 1], dtype=numpy.float32)
at = numpy.array([0, 0, 0], dtype=numpy.float32)
up = numpy.array([0, 1, 0], dtype=numpy.float32)
mvp = frustum(-1, 1, 1, -1, .1, 1000)#lookAt(eye, at, up)
vao = glGenVertexArrays(1)
glBindVertexArray(vao)
vbo_pos = glGenBuffers(1)
glBindBuffer(GL_ARRAY_BUFFER, vbo_pos)
vbo_norm = glGenBuffers(1)
glBindBuffer(GL_ARRAY_BUFFER, vbo_norm)
verts = []
normals = []
for i in range(0, len(model.faces), 3):
index = model.faces[i:i+3]
verts.extend(model.vertices[3*index[0]:3*index[0]+3])
verts.extend(model.vertices[3*index[1]:3*index[1]+3])
verts.extend(model.vertices[3*index[2]:3*index[2]+3])
normals.extend(model.normals[3*index[0]:3*index[0]+3])
normals.extend(model.normals[3*index[1]:3*index[1]+3])
normals.extend(model.normals[3*index[2]:3*index[2]+3])
verts = numpy.array(verts, dtype=numpy.float32)
normals = numpy.array(normals, dtype=numpy.float32)
glBindBuffer(GL_ARRAY_BUFFER, vbo_pos)
glBufferData(GL_ARRAY_BUFFER, verts.size * verts.itemsize, verts, GL_STATIC_DRAW)
glVertexAttribPointer(vpos_loc, 3, GL_FLOAT, GL_FALSE, 0, ctypes.c_void_p(0))
glEnableVertexAttribArray(vpos_loc)
glBindBuffer(GL_ARRAY_BUFFER, vbo_norm)
glBufferData(GL_ARRAY_BUFFER, normals.size * normals.itemsize, normals, GL_STATIC_DRAW)
glVertexAttribPointer(vnorm_loc, 3, GL_FLOAT, GL_FALSE, 0, ctypes.c_void_p(0))
glEnableVertexAttribArray(vnorm_loc)
glBindBuffer(GL_ARRAY_BUFFER, 0)
glBindVertexArray(0)
while(True):
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
glUseProgram(program)
rotation_matrix = rotate(.01, [0, 1, 0])
mvp = mvp # rotation_matrix
glUniformMatrix4fv(mvp_loc, 1, GL_FALSE, mvp.flatten())
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)
glBindVertexArray(vao)
glDrawArrays(GL_TRIANGLES, 0, int(verts.size/3))
glBindVertexArray(0)
glUseProgram(0)
pygame.display.flip()
main()
MV.py
import numpy
def normalize(vector):
return vector/numpy.linalg.norm(vector)
def translate(pos):
return numpy.array([[1, 0, 0, pos[0]],
[0, 1, 0, pos[1]],
[0, 0, 1, pos[2]],
[0, 0, 0, 1]], dtype=numpy.float32)
def rotate(angle, axis):
rads = angle * numpy.pi/180
v = normalize(axis)
c = numpy.cos(rads)
omc = 1-c
s = numpy.sin(rads)
return numpy.array([[v[0]*v[0]*omc + c, v[0]*v[1]*omc - v[2]*s, v[0]*v[2]*omc + v[1]*s, 0],
[v[0]*v[1]*omc + v[2]*s, v[1]*v[1]*omc + c, v[1]*v[2]*omc - v[0]*s, 0],
[v[0]*v[2]*omc - v[1]*s, v[1]*v[2]*omc + v[0]*s, v[2]*v[2]*omc + c, 0],
[0, 0, 0, 1]], dtype=numpy.float32)
def lookAt(eye, at, up):
n = normalize(at-eye)
u = normalize(numpy.cross(n, up))
v = normalize(numpy.cross(u, n))
rotate = numpy.array([[u[0], v[0], -n[0], 0],
[u[1], v[1], -n[1], 0],
[u[2], v[2], -n[2], 0],
[0, 0, 0, 1]], dtype=numpy.float32).transpose()
return rotate#translate(-eye)
def frustum(left, right, top, bottom, near, far):
rl = right-left
tb = top-bottom
fn = far-near
return numpy.array([[2*near/rl, 0, (right+left)/rl, 0],
[0, 2*near/tb, (top+bottom)/tb, 0],
[0, 0, -(far+near)/fn, -(2*far*near)/fn],
[0, 0, -1, 0]], dtype=numpy.float32)
The output shows the teapot being rotated (though not about the axis that I expected) and sort of shrinking and disappearing at rotations of 0, pi, 2pi, etc. I believe the teapot vertices are being processed correctly, as it does show up when rotated and is correctly shaded with normal values.
Output at 5 degrees - Model is 'growing'
Output at 30 degrees - Strange culling?
Output at 60 degrees - Relatively normal
Output at 170 degrees - Model is 'shrinking'
Output at 190 degrees - Model is 'growing' on the other side of the plane
At rotations 0, pi, 2pi, etc the model is completely invisible/too small to see.