有没有popMatrix,pushMatrix,在pygame中翻译?

时间:2017-10-15 05:45:01

标签: python canvas graphics pygame

是否有PopMatrix,PushMatrix,在pygame中翻译和/或旋转等效方法?

如果没有,开发它们会遇到什么挑战?为什么它们不存在?

1 个答案:

答案 0 :(得分:2)

开发矩阵堆栈以跟踪转换将相对简单。这是我制作的一个简单的类(没有仔细检查这段代码的错误),它复制了你在Processing's API reference中可能会看到的很多功能(看看转换 section):

<强> matstack.py

import math
import numpy as np

_stack = [np.identity(4)]

def apply_mat(mat):
    _stack[-1] = np.dot(_stack[-1], mat)

def pop_mat():
    _stack.pop()

def push_mat():
    _stack.append(get_mat())

def get_mat():
    return _stack[-1]

def reset_mat():
    _stack[-1] = np.identity(4)

def rotate_mat(radians):
    c = math.cos(radians)
    s = math.sin(radians)
    rotate = np.array([
        [c, s, 0, 0],
        [-s, c, 0, 0],
        [0, 0, 1, 0],
        [0, 0, 0, 1],
    ], dtype=np.float32)
    apply_mat(rotate)

def translate_mat(x_shift, y_shift):
    x, y = x_shift, y_shift
    translate = np.array([
        [1, 0, 0, 0],
        [0, 1, 0, 0],
        [0, 0, 1, 0],
        [x, y, 0, 1],
    ], dtype=np.float32)
    apply_mat(translate)

def scale_mat(x_scale, y_scale):
    x, y = x_scale, y_scale
    scale = np.array([
        [x, 0, 0, 0],
        [0, y, 0, 0],
        [0, 0, 1, 0],
        [0, 0, 0, 1],
    ], dtype=np.float32)
    apply_mat(scale)

这个类的用法也很简单:

<强> main.py

import math
import matstack as ms

if __name__ == "__main__":
    ms.reset_mat()
    ms.translate_mat(rect.x, rect.y)
    ms.rotate_mat(math.radians(45))
    ms.scale_mat(2, 0.5)
    print(ms.get_mat())

然而,问题在于决定我们如何应用这些矩阵,以便它们实际上影响pygame 中的曲面绘制。问题是pygame中的所有内容都围绕着低pygame.Rect个对象。如果我们查看documentation,我们会发现pygame.Rect构造函数的格式为Rect(left, top, width, height) -> Rect。这意味着,从根本上说,pygame.Rect必须是轴对齐的最小边界框(AABB),其边必须始终与x = 0y = 0平行。这有许多有用的属性(请参阅文档中的所有辅助函数!),但最终可以防止像旋转这样的复杂转换。

至于为什么就是这种情况,我相信这可归因于pygame所依赖的父技术,即SDL,特别是(过时的)SDL 1.2。虽然Processing(可能依赖于OpenGL)之类的东西使用硬件加速来绘制(将4x4矩阵传递给GPU并执行超快速转换),但SDL 1.2是一个软件渲染器,并未考虑GPU设计。由于GPU不能用于执行转换,因此必须在CPU级别完成工作,操作和“blitting”像素框以获得所需的效果。

为了解决这个限制,SDL有一个模块SDL_gfx,这可能是pygame在其pygame.transform模块下使用的模块。这可以使用内置函数处理几个固定选项,如旋转和缩放。但是,这些函数只返回包含新变换像素的Surface个对象。因此,管道中没有任何地方可以通过我们的矩阵!

如果你真的需要在你的应用程序中使用矩阵和堆栈,我建议使用PyOpenGL使用OpenGL。然后你可以使用我在你的问题评论中谈到的固定函数(顺便说一下是非常过时的)矩阵堆栈操作。您可以在此过程中使用pygame来管理窗口和输入。

如果您特别想要一些受处理启发的东西,但对于已经采用此方法的python,我在网上搜索时找到了this p5 library。如果您只想使用Processing生态系统,但使用“python”语法(在Java中实现),python-mode可能是更好的选择。希望这能让您深入了解这个问题以及一些可能的解决方案!