Basically, I'm trying to extract a depth map (by this I mean a matrix with z corresponding to z-coordinates for vertices in GL.glVertex3dv(vertex)
call - obviously, interpolated for plane pixels) after rendering a model (script is loading the model from file with path specified as the first command line argument).
There are several questions which come to mind:
why
glReadPixels
call returns a numpy array with shape(width, shape)
, instead of(height, width)
?why it returns some trash, not connected to the rendered model?
is there an easy way to get z-coordinates on OpenGL legacy code with PyOpenGL framework?
is it correct that maximum I can get here is some array with range
[0; 1]
, basically is some fraction between zNear and zFar (and normalized by glReadPixels, for whatever reason)?
The code itself:
import sys
import argparse
import pyassimp
from pyassimp.postprocess import aiProcess_JoinIdenticalVertices, aiProcess_Triangulate
import numpy as np
import matplotlib.pyplot as plt
from collections import namedtuple
from OpenGL import GL, GLUT
Mesh = namedtuple('Mesh', ('vertices', 'faces'))
def load_mesh(filename):
scene = pyassimp.load(filename, processing=aiProcess_JoinIdenticalVertices | aiProcess_Triangulate)
mesh = scene.mMeshes[0].contents
def get_vector_array(vector):
return [vector.x, vector.y, vector.z]
def get_face_array(face):
return [face.mIndices[i] for i in xrange(face.mNumIndices)]
vertices = np.array([get_vector_array(mesh.mVertices[i]) for i in xrange(mesh.mNumVertices)])
faces = np.array([get_face_array(mesh.mFaces[i]) for i in xrange(mesh.mNumFaces)])
pyassimp.release(scene)
return Mesh(vertices, faces)
def load_ortho():
GL.glMatrixMode(GL.GL_PROJECTION)
GL.glLoadIdentity()
GL.glOrtho(-1, 1, -1, 1, -1, 1)
GL.glMatrixMode(GL.GL_MODELVIEW)
GL.glLoadIdentity()
mesh = None
width, height = 1920, 1080
def draw_mesh():
global mesh, width, height
GL.glClearColor(0, 0, 0, 0)
GL.glClearDepth(0.5)
GL.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT)
GL.glDepthMask(GL.GL_TRUE)
load_ortho()
for face in mesh.faces:
GL.glBegin(GL.GL_POLYGON)
for vertex in mesh.vertices[face]:
GL.glVertex3dv(vertex)
GL.glEnd()
GLUT.glutSwapBuffers()
d = GL.glReadPixels(0, 0, width, height, GL.GL_DEPTH_COMPONENT, GL.GL_FLOAT)
plt.imshow(d)
plt.show()
def reshape(w, h):
GL.glViewport(0, 0, w, h)
GLUT.glutDisplayFunc(draw_mesh)
GLUT.glutPostRedisplay()
def init(width, height):
GLUT.glutInit(sys.argv)
GLUT.glutInitDisplayMode(GLUT.GLUT_RGBA | GLUT.GLUT_DOUBLE)
GLUT.glutInitWindowSize(width, height)
GLUT.glutInitWindowPosition(0, 0)
GLUT.glutCreateWindow("test")
# GLUT.glutDisplayFunc(draw_mesh)
# GLUT.glutIdleFunc(draw_mesh)
GLUT.glutReshapeFunc(reshape)
GLUT.glutIdleFunc(GLUT.glutPostRedisplay)
def keyPressed(self, *args):
if args[0] == '\033':
sys.exit()
GLUT.glutKeyboardFunc(keyPressed)
if __name__ == '__main__':
parser = argparse.ArgumentParser("Test on extracting depth while rendering a model with PyOpenGL")
parser.add_argument("model", type=str)
args = parser.parse_args()
global mesh
mesh = load_mesh(args.model)
init(width, height)
draw_mesh()
The model file I personally used for testing: bunny.obj The snippet's result is here