Drawing a house using python opengl does not display

Viewed 176

I want to draw a house with Python OpenGL. It should look like this:

  • filled: enter image description here
  • unfilled: enter image description here

Further information: The house should rotate via key input around the x- and y-axis. By pressing the F-key, it should switch between filled and unfilled mode.

My Problem: The window opens up, but I don't see anything on it. I'm not sure what exactly is wrong here or what I'm missing for drawing. Can somebody explain it?

This is my code:

import pygame
from pygame.locals import *

from OpenGL.GL import *
from OpenGL.GLU import *
from OpenGL.GLUT import *
# from OpenGL.GL import shaders
# from OpenGL.arrays import vbo

# import numpy as np

# general all vertices needed
vertices = (
# front wall
(2, 0, -1, 2, 1, -1, -2, 1, -1, -2, 0, -1),
# back wall
(2, 0, 1, 2, 1, 1, -2, 1, 1, -2, 0, 1, 2, 2, 0, -2, 2, 0),
# roof ridge
(2.2, 2, 0, -2.2, 2, 0),
# roof edges
(2.2, 0.9, -1.1, -2.2, 0.9, -1.1, 2.2, 0.9, 1.1, -2.2, 0.9, 1.1),
# chimney
(1, 0, 0.5, 1.25, 0, 0.5, 1.25, 0, 0.25, 1, 0, 0.25,
 1, 2.5, 0.5, 1.25, 2.5, 0.5, 1.25, 2.5, 0.25, 1, 2.5, 0.25)
)


def DrawHouse():
# house

# back wall
glBegin(GL_LINES)
glColor3f(0.5, 0.5, 0.5)
glVertex3f(2, 0, -1)  # top left
glVertex3f(2, 1, -1)  # top right
glVertex3f(-2, 1, -1)  # bottom right
glVertex3f(-2, 0, -1)  # bottom left
glEnd()

# front wall
glBegin(GL_LINES)
glColor3f(0.5, 0.5, 0.5)
glVertex3f(2, 0, 1)  # top left
glVertex3f(2, 1, 1)  # top right
glVertex3f(-2, 1, 1)  # bottom right
glVertex3f(-2, 0, 1)  # bottom right
glVertex3f(2, 2, 0)   # rooftop
glVertex3f(-2, 2, 0)  # rooftop
glEnd()

# roof
glBegin(GL_LINES)
# roof ridge
glColor3f(0, 0, 0)
glVertex3f(2.2, 2, 0)
glVertex3f(-2.2, 2, 0)
glEnd()

# roof edges
glBegin(GL_TRIANGLES)
glColor3f(0, 0, 0)
glVertex3f(2.2, 0.9, -1.1)
glVertex3f(-2.2, 0.9, -1.1)
glVertex3f(2.2, 0.9, 1.1)
glVertex3f(-2.2, 0.9, 1.1)
glEnd()

# chimney
glBegin(GL_POLYGON)
glColor3f(1, 1, 0)
glVertex3f(1, 0, 0.5)
glVertex3f(1.25, 0, 0.5)
glVertex3f(1.25, 0, 0.25)
glVertex3f(1, 0, 0.25)
glVertex3f(1, 2.5, 0.5)
glVertex3f(1.25, 2.5, 0.5)
glVertex3f(1.25, 2.5, 0.25)
glVertex3f(1, 2.5, 0.25)
glEnd()


def init():
# Switch on z-buffer for calculation of hidden surfaces
glEnable(GL_DEPTH_TEST)

# Display front and back of polygons as border lines only
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE)


def reshape():
# initialize projection matrix, to 60 degrees horizontal field of view
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
gluPerspective(60.0, 1.0, 1.0, 200.0)  # angle, aspect, near and far clip

# make modelview matrix the current matrix again
glMatrixMode(GL_MODELVIEW)


def main():
pygame.init()
window = (800, 800)
display = pygame.display.set_mode(window, DOUBLEBUF | OPENGL)
pygame.display.set_caption('Haus')
clock = pygame.time.Clock()
# GLUT.glutInitDisplayMode(GLUT_DEPTH | GLUT_RGB | GLUT_DOUBLE)  # request render context with z-buffer, doublebuffer for rgb mode
gluOrtho2D(0, 800, 0, 800)

rotX = 0.0
rotY = 0.0
polygonMode = GL_LINE

while True:
    clock.tick(100)
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()

    keys = pygame.key.get_pressed()  # checking pressed keys
    if keys[pygame.K_d]:  # The keys 'a' and 'd' should rotate the house around the y-axis
        rotX -= 5
    if keys[pygame.K_a]:
        rotX += 5
    if keys[pygame.K_w]:  # the keys 'w' and 'd' should rotate the house around the x-axis
        rotY -= 5
    if keys[pygame.K_d]:
        rotY += 5
    if keys[pygame.K_f]:  # Key 'f' is to switch between wireframe and filled surfaces
        if polygonMode is GL_FILL:
            polygonMode = GL_LINE
        else:
            polygonMode = GL_FILL

    # Switch polygon display between outline and filled
    glPolygonMode(GL_FRONT_AND_BACK, polygonMode)

    # GLUT.glutPostRedisplay()  # render image again

    # remove Framebuffer and Z-Buffer
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)

    # initialise Modelview Matrix
    glLoadIdentity()

    # execute Modeltransformation
    glTranslatef(0, 0, -3)  # shift by -3 in z-direction
    glRotatef(rotY, 0, 1, 0)  # rotate y-achse
    glRotatef(rotX, 1, 0, 0)  # rotate x-achse
    glTranslatef(-0.5, -0.5, -0.5)  # shift by -0.5 in all directions

    # copy Back-Buffer in Front-Buffer
    # swapBuffers()

    DrawHouse()

    # Show the screen
    pygame.display.flip()

    # callback functions
    # glutReshapeFunc(reshape)


    if __name__ == "__main__":
         main()
1 Answers

The coordinates of your geometry are in range [-2.2, 2.2]. However you set an orthographic projection in range [0, 800]:

gluOrtho2D(0, 800, 0, 800)

Actually there are 3 reasons why you don't see anything

  1. That results in only a few pixels being drawn on the bottom left of the screen.
  2. gluOrtho2D creates an orthographic projection with a near plane of -1 and a far plane of 1. This will clip your geometry.
  3. You need to choose the GL_PROJECTION for the current matrix. Later in your code, the model view matrix is set to the identity matrix with glLoadIdentity.
def main():
    pygame.init()
    window = (800, 800)
    display = pygame.display.set_mode(window, DOUBLEBUF | OPENGL)
    pygame.display.set_caption('Haus')
    clock = pygame.time.Clock()

    # gluOrtho2D(0, 800, 0, 800)
    
    glMatrixMode(GL_PROJECTION)
    glLoadIdentity()
    glOrtho(-5, 5, -5, 5, -5, 5)
    glMatrixMode(GL_MODELVIEW)

    # [...]

Alternatively you can use the perspective projection from the reshape function:

def main():
    pygame.init()
    window = (800, 800)
    display = pygame.display.set_mode(window, DOUBLEBUF | OPENGL)
    pygame.display.set_caption('Haus')
    clock = pygame.time.Clock()
    
    # gluOrtho2D(0, 800, 0, 800)

    reshape()

    # [...]
Related