简体   繁体   中英

How can I rotate rectangles in OpenGL?

Rectangles become distorted when I use glRotatef. I know that it's important to bring images to the center of the screen before rotating. I'm pretty sure I'm doing that:

import os
import pygame
from PIL import Image
from pathlib import Path
from numpy import array
import pygame
import math
from pygame.locals import *
from OpenGL.GL import *
from OpenGL.GLU import *
from OpenGL.GL import glClear, GL_COLOR_BUFFER_BIT, glBegin, GL_QUADS, glEnd, glColor3f, glVertex2f, glFlush, glClearColor

os.environ['SDL_VIDEO_CENTERED'] = '1'
windowSize = (1500, 800)
Screen = pygame.display.set_mode(windowSize, pygame.DOUBLEBUF | pygame.OPENGL)

HOME = str(Path.home())
path = HOME + '\\Desktop\piston2.png'
path2 = HOME + '\\Desktop\piston3.png'
path3 = HOME + '\\Desktop\Piston Platformer2\Images\Flower1.png'

def loadTexture(texture, flip):
  try:
    text = Image.open(texture)
  except IOError as ex:
    print("Failed to open texture file: ", texture)
    text = Image.open("0.png")
  textData = array(list(text.getdata()))
  textID = glGenTextures(1)
  glPixelStorei(GL_UNPACK_ALIGNMENT, 1)
  glBindTexture(GL_TEXTURE_2D, textID)
  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)
  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)
  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER)
  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER)
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0)
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0)
  glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, text.size[0], text.size[1], 0, GL_RGBA, GL_UNSIGNED_BYTE, textData)
  text.close()
  return (text.size[0], text.size[1]), textID


def make_opengl_rect(image_sizes, cur_ID, offsets, rotate):
  texts = ((1, 0), (1, 1), (0, 1), (0, 0))
  x_ratio = image_sizes[0]/windowSize[0]
  y_ratio = image_sizes[1]/windowSize[1]
  offset_x = 2*(offsets[0]/windowSize[0])
  offset_y = 2*(offsets[1]/windowSize[1])
  verts = [(2*x_ratio, 2*y_ratio), (2*x_ratio, 0), (0, 0), (0, 2*y_ratio)] # upright, downright, downleft, upleft
  additional_offset_x, additional_offset_y = 0, 0
  verts = [(x-1+offset_x+additional_offset_x, y+1-verts[0][1]-offset_y+additional_offset_y) for (x, y) in verts]
  print('verts', verts)
  if rotate != 0:
    glPushMatrix()
    glTranslatef(-verts[0][0], -verts[0][1], 0)
    glRotatef(rotate, 0, 0, 1)
    glTranslatef(verts[0][0], verts[0][1], 0)
  glEnable(GL_TEXTURE_2D)
  glBindTexture(GL_TEXTURE_2D, cur_ID)
  glBegin(GL_QUADS)
  for i in range(4):
    glTexCoord2f(texts[i][0], texts[i][1])
    glVertex2f(verts[i][0], verts[i][1])
  glEnd()
  print('verts', verts)
  if rotate != 0:
    glPopMatrix()
  glDisable(GL_TEXTURE_2D)


my_image1_sizes, my_image1_ID = loadTexture(path, False)
my_image2_sizes, my_image2_ID = loadTexture(path2, False)
my_image3_sizes, my_image3_ID = loadTexture(path3, True)

glEnable(GL_BLEND)
glBlendEquation(GL_FUNC_ADD)


running = True

while running:
  for event in pygame.event.get():
    if event.type == pygame.QUIT:
      raise SystemExit
    elif event.type == pygame.KEYDOWN:
      if event.key == pygame.K_ESCAPE:
        raise SystemExit
  #
  glClear(GL_COLOR_BUFFER_BIT)
  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
  #make_opengl_rect(my_image1_sizes, my_image1_ID, (100,100), 0)
  #make_opengl_rect(my_image2_sizes, my_image2_ID, (100,100), 0)
  make_opengl_rect(my_image3_sizes, my_image3_ID, (300,300), 340)
  glFlush()
  pygame.display.flip()
  print('')

Am I missing something?

I attached example images.

Rotated:

旋转的

Not rotated:

没有旋转

Your images are distorted because of the aspect ratio of the viewport. You need to set up an Orthographic projection matrix that takes the aspect ratio into account with glOrtho . Set the projection matrix once before the application loop:

w, h = Screen.get_size()
aspect = w / h

glMatrixMode(GL_PROJECTION)
glLoadIdentity()
glOrtho(-aspect, aspect, -1, 1, -1, 1)
glMatrixMode(GL_MODELVIEW)
glLoadIdentity()

running = True
while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            raise SystemExit
        elif event.type == pygame.KEYDOWN:
            if event.key == pygame.K_ESCAPE:
                raise SystemExit
  
    glClear(GL_COLOR_BUFFER_BIT)
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
    #make_opengl_rect(my_image1_sizes, my_image1_ID, (100,100), 0)
    #make_opengl_rect(my_image2_sizes, my_image2_ID, (100,100), 0)
    make_opengl_rect(my_image3_sizes, my_image3_ID, (300,300), 340)
    glFlush()
    pygame.display.flip()

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM