Search code examples
pythonopenglpygletcoordinate-transformationopengl-compat

How to set clipping planes with opengl and pyglet


I am troubleshooting a problem with my code that if the depth value of any primitive is not zero it will not render on the screen. I suspect that it gets clipped away.

Is there an easy pythonic way to set my clipping planes in pyglet ?

This is my code so far:

import pyglet
from pyglet.gl import *
import pywavefront
from camera import FirstPersonCamera


def drawloop(win,camera):
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
    #glClearColor(255,255,255,255)
    glLoadIdentity()
    camera.draw()

    pyglet.graphics.draw(2, pyglet.gl.GL_POINTS,
    ('v3f', (10.0, 15.0, 0.0, 30.0, 35.0, 150.0))
    )
    glPointSize(20.)
    return pyglet.event.EVENT_HANDLED


def main():
    win = pyglet.window.Window()
    win.set_exclusive_mouse(True)
    win.clear()
    camera = FirstPersonCamera(win)
    @win.event
    def on_draw(): 
        drawloop(win,camera)
    def on_update(delta_time):
        camera.update(delta_time)
    pyglet.clock.schedule(on_update)
    pyglet.app.run()

if __name__ == '__main__':
    main()

I am using the FirstPersonCamera snippet from here:

https://gist.github.com/mr-linch/f6dacd2a069887a47fbc


Solution

  • I am troubleshooting a problem with my code that if the depth value of any primitive is not zero it will not render on the screen. I suspect that it gets clipped away.

    You have to set up a projection matrix to solve the issue. Either set up an orthographic projection matrix or a perspective projection matrix.

    The projection matrix describes the mapping from 3D points of the view on a scene, to 2D points on the viewport. It transforms from eye space to the clip space, and the coordinates in the clip space are transformed to the normalized device coordinates (NDC) by dividing with the w component of the clip coordinates. The NDC are in range (-1,-1,-1) to (1,1,1).
    Every geometry which is out of the clippspace is clipped.

    At Orthographic Projection the coordinates in the view space are linearly mapped to clip space coordinates and the clip space coordinates are equal to the normalized device coordinates, because the w component is 1 (for a cartesian input coordinate).
    The values for left, right, bottom, top, near and far define a box. All the geometry which is inside the volume of the box is "visible" on the viewport.

    orthographic projection

    At Perspective Projection the projection matrix describes the mapping from 3D points in the world as they are seen from of a pinhole camera, to 2D points of the viewport.
    The eye space coordinates in the camera frustum (a truncated pyramid) are mapped to a cube (the normalized device coordinates).

    perspective projection

    To set a projection matrix the projection matrix stack has to be selected by glMatrixMode.

    An orthographic projection can be set by glOrhto:

    w, h = 640, 480 # default pyglet window size
    
    glMatrixMode(GL_PROJECTION)
    glLoadIdentity()
    glOrtho( -w/2, w/2, -h/2, h/2, -1000.0, 1000.0) # [near, far] = [-1000, 1000]
    
    glMatrixMode(GL_MODELVIEW)
    ....
    

    An perspective projection can be set by gluPerspective:

    w, h = 640, 480 # default pyglet window size
    
    glMatrixMode(GL_PROJECTION)
    glLoadIdentity()
    gluPerspective( 90.0, 640.0/480, 0.1, 1000.0) # fov = 90 degrees; [near, far] = [0.1, 1000]
    
    glMatrixMode(GL_MODELVIEW)
    ....
    

    I recommend to use the following coordinates, to "see" the points in both of the above cases:

    e.g.:

    pyglet.graphics.draw(2, pyglet.gl.GL_POINTS,
        ('v3f', (-50.0, -20.0, -200.0, 40.0, 20.0, -250.0)))
    glPointSize(20.0)