Как сохранить масштаб при вращении?Python

Программы на Python
Anonymous
Как сохранить масштаб при вращении?

Сообщение Anonymous »

Я возился с OpenGL/ModernGL в Python/Pygame, и после того, как мои изображения были отображены на экране, у меня возникли проблемы с их поворотом.
Я знаю порядок, в котором мне нужно переводить, вращать и затем масштабировать, и это работает нормально, однако моя проблема связана с тем, что масштабирование изображений составляет процент от разрешения экрана. Мой подход заключался в том, чтобы создать шейдер, охватывающий экран, а затем, когда мне нужно, чтобы мое изображение поместилось, я масштабировал его, скажем, до 0,2 (соотношение сторон) по X и 0,1 по Y.
Когда изображение поворачивается на 0 градусов (т. е. по горизонтали), 0,1 по оси Y делает изображение равным 0,1 высоты экрана, однако когда оно поворачивается на При повороте на 90 градусов (по вертикали) то же значение 0,1 теперь масштабирует изображение на 0,1 ширины экрана. Из-за этого, когда я поворачиваю квадрат на 90 градусов, он растягивается по горизонтали.
Некоторые прикрепленные изображения показывают проблемы ниже. Используемое изображение — это просто кнопка «Пуск» из другого моего старого проекта. Кнопка масштабируется до (0,5, 0,5) и первоначально поворачивается на 0, затем на 90 градусов.



повернута на 0 градусов
повернута на 90 градусов





Изображение


Изображение




Я не совсем уверен, существует ли общий способ исправить это или мой подход к рендерингу изображений неправильный.
Ниже приведен соответствующий код:
Внутри vbo.py:

Код: Выделить всё

class SurfaceVBO(BaseVBO):
def __init__(self, app, context):
super().__init__(app, context)
self.format = '2f 2f'
self.attribs = ['in_uv', 'in_position']

def getVertexData(self):
#aspect_ratio = self.app.height / self.app.width
aspect_ratio = 1

vertices = [((-1 * aspect_ratio),-1),((1 * aspect_ratio),-1),((1 * aspect_ratio),1),((-1 * aspect_ratio),1)]
indices = [(0,2,3),(0,1,2)]

tex_coord = [(0,0), (1,0), (1,1), (0,1)]
tex_coord_indices = [(0,2,3),(0,1,2)]

vertex_data = self.getData(vertices, indices)
tex_coord_data = self.getData(tex_coord, tex_coord_indices)
vertex_data = np.hstack([tex_coord_data, vertex_data])

return vertex_data
Внутри Surface.vert:

Код: Выделить всё

#version 330 core

in vec2 in_uv;
in vec2 in_position;

out vec2 uv;

// m_ortho is just a orthographic projection matrix spanning (-1, -1), (1, 1) with near 0, and far 10,000

uniform mat4 m_model;
uniform mat4 m_ortho;

void main()
{
uv = in_uv;
gl_Position = m_ortho * m_model * vec4(in_position.xy, 0, 1.0);
}
Внутри button.py:

Код: Выделить всё

import pygame
import math as m
import glm

class BaseButton:
def __init__(self, game, vao_name='surface', tex_id='game_menu', pos=(0,0), rot=0, scale=(1,1)):
self.game = game
self.pos = pos
self.rot = glm.radians(rot)
self.aspect_ratio = self.game.height / self.game.width
#self.aspect_ratio = 1
self.original_scale = (scale[0], scale[1])
self.scale = (self.aspect_ratio * (self.original_scale[0]), (self.original_scale[1]))
self.m_model = self.getModelMatrix()
self.vao_name = vao_name
self.tex_id = tex_id
self.vao = game.mesh.vao.vaos[vao_name]
self.program = self.vao.program
self.image = self.getPygameImage(path=f'images/{tex_id}.png')
self.rect = self.image.get_rect(center = (((self.pos[0] + 1) / 2) * self.game.width, ((-self.pos[1] + 1) / 2) * self.game.height))
self.texture = self.get2DTexture(image=self.image)
self.tint = 1
self.rend = False

def update(self): ...

def getModelMatrix(self):
# identity matrix
m_model = glm.mat4()
# position
m_model = glm.translate(m_model, (*self.pos, 0))
#print(1, "\n", m_model)
# rotation
m_model = glm.rotate(m_model, self.rot, glm.vec3(0,0,1))
#print(2, "\n", m_model)
# scaling
m_model = glm.scale(m_model, (*self.scale, 1))
#print(3, "\n", m_model)
return m_model

def getPygameImage(self, path):
image = pygame.image.load(path).convert_alpha()
image = pygame.transform.flip(image, flip_x=False, flip_y=True)
image = pygame.transform.scale(image, (self.scale[0] * self.game.width, self.scale[1] * self.game.height))
return image

def get2DTexture(self, image):
texture = self.game.context.texture(size=image.get_size(), components=4,data=pygame.image.tostring(image, 'RGBA'))
return texture

def render(self):
self.update()
if self.rend:
self.vao.render()
# print(f'DEBUG - rendering {self}')
Код работает со скоростью 60 кадров в секунду и для каждого кадра обновляет каждое изображение и отображает каждое изображение на экране.

Вернуться в «Python»