1

When I run my program the texture on the cube seems to be orientated incorrectly & repeating itself. Also the white in the image has seemed to be replaced by green. I have tried removing the glColor tag but that just throws an error. It would be nice if someone also knew how to make it just show the raw image but it is not the end of the world if no one can.

It looks like this

The texture is meant to be this

This is my code:

import pygame
import sys
from OpenGL.GL import *
from OpenGL.GLU import *
from pygame.locals import *

verticies = (
    (1, 1, 1),      #0
    (1, 1, -1),     #1
    (1, -1, 1),     #2
    (1, -1, -1),    #3
    (-1, 1, 1),     #4
    (-1, 1, -1),    #5
    (-1, -1, 1),    #6
    (-1, -1, -1),   #7
    )

# (<node1>, <node2>)
edges = (
    (0, 1),         #0
    (0, 2),         #1
    (0, 4),         #2
    (1, 3),         #3
    (1, 5),         #4
    (2, 3),         #5
    (2, 6),         #6
    (3, 7),         #7
    (4, 5),         #8
    (4, 6),         #9
    (5, 7),         #10
    (6, 7),         #11
    )

# (<node1>, <node2>, <node3>, <node4>)
faces = (
    (0, 1, 3, 2),   #0
    (0, 1, 5, 4),   #1
    (0, 2, 6, 4),   #2
    (1, 3, 7, 5),   #3
    (2, 3, 7, 6),   #4
    (4, 5, 7, 6),   #5
    )

def cube():
    glBegin(GL_QUADS)
    for face in faces:
        for vertex in face:
            glColor3fv((0, 1, 0))
            glTexCoord2fv(edges[vertex])
            glVertex3fv(verticies[vertex])
    glEnd()

    glBegin(GL_LINES)
    for edge in edges:
        for vertex in edge:
            glColor3fv((0, 0, 0))
            glVertex3fv(verticies[vertex])
    glEnd()


def loadTexture():
    textureSurface = pygame.image.load('test_image.png')
    textureData = pygame.image.tostring(textureSurface, "RGBA", 1)
    width = textureSurface.get_width()
    height = textureSurface.get_height()

    glEnable(GL_TEXTURE_2D)
    texid = glGenTextures(1)

    glBindTexture(GL_TEXTURE_2D, texid)
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height,
                  0, GL_RGBA, GL_UNSIGNED_BYTE, textureData)

    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT)
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT)
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)

def main():
    pygame.init()
    display = (800, 600)
    pygame.display.set_mode(display, DOUBLEBUF|OPENGL)

##    loadTexture()

    gluPerspective(45, (display[0]/display[1]), 0.1, 50.0)

    glTranslatef(0.0, 0.0, -5)

    glRotatef(0, 0, 0, 0)

    shiftActive = 0
    ctrlActive = 0

    while 1:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                quit

        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_LEFT:
                  glTranslatef(0.03, 0, 0)
            if event.key == pygame.K_RIGHT:
                  glTranslatef(-0.03, 0, 0)
            if event.key == pygame.K_UP:
                  glTranslatef(0, -0.03, 0)    
            if event.key == pygame.K_DOWN:
                  glTranslatef(0, 0.03, 0)
            if event.key == pygame.K_LSHIFT:
                shiftActive = 1
            if event.key == pygame.K_LCTRL:
                ctrlActive = 1

        if event.type == pygame.KEYUP:
            if event.key == pygame.K_LSHIFT:
                shiftActive = 0
            if event.key == pygame.K_LCTRL:
                ctrlActive = 0

        # scroll controls  !CURRENTLY IN CLIK MODE BECAUSE OF MOUSE ISSUES!
        if shiftActive:
            if event.type == pygame.MOUSEBUTTONDOWN:
                if event.button == 1:
                    glTranslatef(-0.03, 0, 0)
                if event.button == 3:
                    glTranslatef(0.03, 0, 0)
        elif ctrlActive:
            if event.type == pygame.MOUSEBUTTONDOWN:
                if event.button == 1:
                    glTranslatef(0, 0, 0.03)
                if event.button == 3:
                    glTranslatef(0, 0, -0.03)
        else:
            if event.type == pygame.MOUSEBUTTONDOWN:
                if event.button == 1:
                    glTranslatef(0, -0.03, 0)
                if event.button == 3:
                    glTranslatef(0, 0.03, 0)

##        glRotatef(1, 1, 1, 1)
        glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)
        cube()
        loadTexture()
        pygame.display.flip()
        pygame.time.wait(10)

main()

Anyone know what i'm doing wrong?

Again stack overflow does not like my code to description ratio so I have to add on random sentences to the end of my question to let me post it. I wish this was removed or just made an optional warning. I don't think going into depth to discuss the angle the image is out by & the percentage size the image should be compared to its current size for each face & giving the exact hex value of green that is overlaying the white in the texture will help anyone answer this question. FFS stack overflow.

Rabbid76
  • 202,892
  • 27
  • 131
  • 174
Derpy Bat
  • 11
  • 1

2 Answers2

1

There are some issues. First, the color of the texture is wrong.

If texturing is enabled, then by default the color of the texel is multiplied by the current color, because by default the texture environment mode (GL_TEXTURE_ENV_MODE) is GL_MODULATE. See glTexEnv.

This causes that the color of the texels of the texture is "mixed" by the last color which you have set by glColor3f.

Set a "white" color before you render the texture, to solve your issue:

glColor3f(1, 1, 1)

Likewise you can change the environment mode to GL_REPLACE, instead:

glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE)

Further the texture is not wrapped to the geometry as expected. This is because the texture coordinates are wrong. Read How do opengl texture coordinates work?.

If you want to put the entire texture to each side of the cube, then you've to define a texture coordinate for each corner of the quad which forms a side of the cube. The minimum texture coordinate is (0, 0) and the maximum is (1, 1). e.g.:

(0, 1)        (1, 1)
      +------+
      |      |
      |      |
      +------+
(0, 0)        (1, 0)

Chang the code as follows to draw a proper cube:

uv = ((1, 1), (1, 0), (0, 0), (0, 1))

def cube():
    glColor3f(1, 1, 1)
    glBegin(GL_QUADS)
    for face in faces:
        for i, vertex in enumerate(face):
            glTexCoord2fv(uv[i])
            glVertex3fv(verticies[vertex])
    glEnd()

If you want that the sides of the cube, which are near to the camera, cover the sides which are behind them, then you've to enable the Depth Test by glEnable(GL_DEPTH_TEST).

It is a wast of time to reload the texture in every frame. It is sufficient to load the texture once, before the main loop.:

# load texture
loadTexture()

# enable  the depth test
glEnable(GL_DEPTH_TEST)

while 1:

    # [...]

    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)
    cube()
    pygame.display.flip()
    pygame.time.wait(10)

Note, you've to ensure that the proper texture is bound (glBindTexture(GL_TEXTURE_2D, texid)) and 2 dimenional texturing is enabled (glEnable(GL_TEXTURE_2D)) before the geometry (cube) is drawn.
OpenGL is a state engine. States which are set are kept, til you change them again, even beyond frames.


There are different current matrices, which can be switched by glMatrixMode. The vertex coordinates are transformed by the projection matrix and the model view matrix:

pos = projectionMatrix * modelviewMatrix * vertex

Thus the projection matrix should be set to the current projection matrix and the view respectively model matrix to the mode view matrix:

glMatrixMode(GL_PROJECTION)
gluPerspective(45, (display[0]/display[1]), 0.1, 50.0)

glMatrixMode(GL_MODELVIEW)
glTranslatef(0.0, 0.0, -5)
glRotatef(0, 0, 0, 0)

The current matrices are organized on a stack and can be saved and restored by glPushMatrix()/glPopMatrix

See the following example code for main():

def main():
    pygame.init()
    display = (800, 600)
    pygame.display.set_mode(display, DOUBLEBUF|OPENGL)

    glMatrixMode(GL_PROJECTION)
    gluPerspective(45, (display[0]/display[1]), 0.1, 50.0)

    glMatrixMode(GL_MODELVIEW)
    glTranslatef(0.0, 0.0, -5)

    loadTexture()
    glEnable(GL_DEPTH_TEST)

    shiftActive, ctrlActive = 0, 0
    anglex, angley = 0, 0
    while 1:
        for event in pygame.event.get():
            # [...]
        # [...]

        glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)

        glPushMatrix()
        glRotate(anglex, 1, 0, 0)
        glRotate(angley, 0, 1, 0)
        anglex += 2
        angley += 1

        cube()

        glPopMatrix()

        pygame.display.flip()
        pygame.time.wait(10)
Rabbid76
  • 202,892
  • 27
  • 131
  • 174
0

Try this one (notice glColor3fv((1, 1, 1)) and "textcoords"):

import pygame
import sys
from OpenGL.GL import *
from OpenGL.GLU import *
from pygame.locals import *

verticies = (
    (1, 1, 1),      #0
    (1, 1, -1),     #1
    (1, -1, 1),     #2
    (1, -1, -1),    #3
    (-1, 1, 1),     #4
    (-1, 1, -1),    #5
    (-1, -1, 1),    #6
    (-1, -1, -1),   #7
    )

# (<node1>, <node2>)
edges = (
    (0, 1),         #0
    (0, 2),         #1
    (0, 4),         #2
    (1, 3),         #3
    (1, 5),         #4
    (2, 3),         #5
    (2, 6),         #6
    (3, 7),         #7
    (4, 5),         #8
    (4, 6),         #9
    (5, 7),         #10
    (6, 7),         #11
    )

textcoords = (
    (1, 1),
    (1, 0),
    (0, 0),
    (0, 1)
    )

# (<node1>, <node2>, <node3>, <node4>)
faces = (
    (0, 1, 3, 2),   #0
    (0, 1, 5, 4),   #1
    (0, 2, 6, 4),   #2
    (1, 3, 7, 5),   #3
    (2, 3, 7, 6),   #4
    (4, 5, 7, 6),   #5
    )

def cube():
    glBegin(GL_QUADS)
    for face in faces:
        for vertex, id in zip(face, range(0, 4)):
            glColor3fv((1, 1, 1))
            glTexCoord2fv(textcoords[id])
            glVertex3fv(verticies[vertex])
    glEnd()

    glBegin(GL_LINES)
    for edge in edges:
        for vertex in edge:
            glColor3fv((0, 0, 0))
            glVertex3fv(verticies[vertex])
    glEnd()


def loadTexture():
    textureSurface = pygame.image.load('BkHwp.png')
    textureData = pygame.image.tostring(textureSurface, "RGBA", 1)
    width = textureSurface.get_width()
    height = textureSurface.get_height()

    glEnable(GL_TEXTURE_2D)
    texid = glGenTextures(1)

    glBindTexture(GL_TEXTURE_2D, texid)
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height,
                 0, GL_RGBA, GL_UNSIGNED_BYTE, textureData)

    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT)
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT)
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)
    #glGenerateMipmap(GL_TEXTURE_2D)

def main():
    pygame.init()
    display = (800, 600)
    pygame.display.set_mode(display, DOUBLEBUF|OPENGL)

    gluPerspective(45, (display[0]/display[1]), 0.1, 50.0)

    glTranslatef(0.0, 0.0, -5)

    glRotatef(0, 0, 0, 0)

    shiftActive = 0
    ctrlActive = 0

    while 1:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                quit

        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_LEFT:
                  glTranslatef(0.03, 0, 0)
            if event.key == pygame.K_RIGHT:
                  glTranslatef(-0.03, 0, 0)
            if event.key == pygame.K_UP:
                  glTranslatef(0, -0.03, 0)
            if event.key == pygame.K_DOWN:
                  glTranslatef(0, 0.03, 0)
            if event.key == pygame.K_LSHIFT:
                shiftActive = 1
            if event.key == pygame.K_LCTRL:
                ctrlActive = 1

        if event.type == pygame.KEYUP:
            if event.key == pygame.K_LSHIFT:
                shiftActive = 0
            if event.key == pygame.K_LCTRL:
                ctrlActive = 0

        # scroll controls  !CURRENTLY IN CLIK MODE BECAUSE OF MOUSE ISSUES!
        if shiftActive:
            if event.type == pygame.MOUSEBUTTONDOWN:
                if event.button == 1:
                    glTranslatef(-0.03, 0, 0)
                if event.button == 3:
                    glTranslatef(0.03, 0, 0)
        elif ctrlActive:
            if event.type == pygame.MOUSEBUTTONDOWN:
                if event.button == 1:
                    glTranslatef(0, 0, 0.03)
                if event.button == 3:
                    glTranslatef(0, 0, -0.03)
        else:
            if event.type == pygame.MOUSEBUTTONDOWN:
                if event.button == 1:
                    glTranslatef(0, -0.03, 0)
                if event.button == 3:
                    glTranslatef(0, 0.03, 0)

##        glRotatef(1, 1, 1, 1)
        glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)
        cube()
        loadTexture()
        pygame.display.flip()
        pygame.time.wait(10)

main()