首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >投影矩阵的几个问题及图像有时变形的原因

投影矩阵的几个问题及图像有时变形的原因
EN

Stack Overflow用户
提问于 2021-11-27 04:27:22
回答 1查看 127关注 0票数 1

我目前正在进行3d渲染,并且我试图在没有任何附加库的情况下完成它(除了游戏、数学、系统),.I已经做了很多研究,但仍然不能完全理解数学(我正在使用维基百科上的方法)。它确实输出了正确的坐标,但有时会出现严重的变形。结果是这样的。我不太明白矩阵,所以我很难调试。我真的可以用一些帮助,为什么它是变形或简单的矩阵如何工作,非常感谢!

这是我的密码:

代码语言:javascript
复制
import pygame
import math
import sys

width = 600
height = 480

class Triangle:
    def __init__(self, verts):
        for i in range(len(verts)):
            for r in range(3):
                verts[i][r] = int(float(verts[i][r]))
        self.verts = verts

类三角形是为了使代码更易于阅读

代码语言:javascript
复制
def getobj(filename):
    verts = []
    ind = []
    triangles = []
    data = None
    with open(filename, 'r') as f:
        data = f.readline()
        while data:
            data = data.rstrip("\n").split(" ")
            if data[0] == 'v':
                verts.append([-1 * int(float(data[1])), -1 * int(float(data[2])), -1 * int(float(data[3]))])
            elif data[0] == 'f':
                v = []
                t = []
                n = []
                for i in range(3):
                    l = data[i + 1].split('/')
                    v.append(int(l[0]))
                    t.append(int(l[1]))
                    n.append(int(l[2]))
                ind.append([v, t, n])
            data = f.readline()
    for points in ind:
        v = []
        for i in points[0]:
            v.append(verts[i - 1])
        triangles.append(Triangle(v))
    return triangles

从obj文件中获取顶点和行

代码语言:javascript
复制
class Matrix:
    def __init__(self, matrix):
        self.matrix = matrix
        self.height = len(matrix)
        self.width = len(matrix[0])

    def __add__(self, other):
        result = []
        for h in range(self.height):
            row = []
            for w in range(self.width):
                row.append(self.matrix[h][w] + other.matrix[h][w])
            result.append(row)
        return Matrix(result)

    def __sub__(self, other):
        result = []
        for h in range(self.height):
            row = []
            for w in range(self.width):
                row.append(self.matrix[h][w] - other.matrix[h][w])
            result.append(row)
        return Matrix(result)
    
    def __mul__(self, other):
        result = []
        for h in range(self.height):
            SUM = 0
            for w in range(self.width):
                SUM += self.matrix[h][w] * other.matrix[0][w]
            result.append(SUM)
        return Matrix([result])

类矩阵是为了使矩阵的加法、减法和乘法更加容易。

代码语言:javascript
复制
class Cam:
    def __init__(self):
        self.pos = Matrix([[0, 0, 0]])
        self.rot = [0, 0, 0]
    
    def getcoord(self, coord):
        m = Matrix([coord])
        data = m - self.pos
        F = Matrix([
            [math.cos(self.rot[2]), math.sin(self.rot[2]), 0],
            [-1 * math.sin(self.rot[2]), math.cos(self.rot[2]), 0],
            [0, 0, 1]
        ])
        S = Matrix([
            [math.cos(self.rot[1]), 0, -1 * math.sin(self.rot[1])],
            [0, 1, 0],
            [math.sin(self.rot[1]), 0, math.cos(self.rot[1])]
        ])
        T = Matrix([
            [1, 0, 0],
            [0, math.cos(self.rot[0]), math.sin(self.rot[0])],
            [0, -1 * math.sin(self.rot[0]), math.cos(self.rot[0])]
        ])
        data = F * data
        data = S * data
        data = T * data
        x = (width / 2) * data.matrix[0][0] / data.matrix[0][2]
        y = (height / 2) * data.matrix[0][1] / data.matrix[0][2]
        return [x, y]

    def events(self, event):
        if event.type == pygame.MOUSEMOTION:
            x, y = event.rel
            x /= 300
            y /= 300
            self.rot[0] -= y
            self.rot[1] += x
    
    def update(self, dt, key):
        s = dt * 2
        if key[pygame.K_LSHIFT]: self.pos.matrix[0][1] -= s
        if key[pygame.K_SPACE]: self.pos.matrix[0][1] += s

        x, y = s*math.sin(self.rot[1]), s*math.cos(self.rot[1])

        if key[pygame.K_w]: self.pos.matrix[0][0] -= x; self.pos.matrix[0][2] -= y
        if key[pygame.K_s]: self.pos.matrix[0][0] += x; self.pos.matrix[0][2] += y
        if key[pygame.K_a]: self.pos.matrix[0][0] += y; self.pos.matrix[0][2] -= x
        if key[pygame.K_d]: self.pos.matrix[0][0] -= y; self.pos.matrix[0][2] += x

控制移动和旋转的位置,以及使用投影矩阵的位置。

代码语言:javascript
复制
cam = Cam()

pygame.init()
screen = pygame.display.set_mode((width, height))
clock = pygame.time.Clock()

pygame.event.get()
pygame.mouse.get_rel()
pygame.mouse.set_visible(0)
pygame.event.set_grab(1)

初始化

代码语言:javascript
复制
# tris = getobj("untitled.obj")
tris = [
    Triangle([[1, -1, 1], [-1, -1, -1], [-1, -1, 1]]),
    Triangle([[-1, -1, -1], [1, 1, -1], [-1, 1, -1]]),
    Triangle([[1, -1, -1], [1, 1, 1], [1, 1, -1]]),
    Triangle([[-1, 1, 1], [1, 1, -1], [1, 1, 1]]),
    Triangle([[-1, -1, 1], [-1, 1, -1], [-1, 1, 1]]),
    Triangle([[1, -1, 1], [-1, 1, 1], [1, 1, 1]]),
    Triangle([[1, -1, 1], [1, -1, -1], [-1, -1, -1]]),
    Triangle([[-1, -1, -1], [1, -1, -1], [1, 1, -1]]),
    Triangle([[1, -1, -1], [1, -1, 1], [1, 1, 1]]),
    Triangle([[-1, 1, 1], [-1, 1, -1], [1, 1, -1]]),
    Triangle([[-1, -1, 1], [-1, -1, -1], [-1, 1, -1]]),
    Triangle([[1, -1, 1], [-1, -1, 1], [-1, 1, 1]])
]

我使用的obj文件中的数据。

代码语言:javascript
复制
while True:
    dt = clock.tick()/1000
    screen.fill((255, 255, 255))
    for event in pygame.event.get():
        if event.type == pygame.QUIT: pygame.quit(); sys.exit()
        cam.events(event)
    for tri in tris:
        coord1 = cam.getcoord(tri.verts[0])
        coord2 = cam.getcoord(tri.verts[1])
        coord3 = cam.getcoord(tri.verts[2])
        pygame.draw.line(screen, (0, 0, 0), (int(coord1[0]), int(coord1[1])), (int(coord2[0]), int(coord2[1])))
        pygame.draw.line(screen, (0, 0, 0), (int(coord1[0]), int(coord1[1])), (int(coord3[0]), int(coord3[1])))
        pygame.draw.line(screen, (0, 0, 0), (int(coord2[0]), int(coord2[1])), (int(coord3[0]), int(coord3[1])))
    pygame.display.flip()
    
    key = pygame.key.get_pressed()
    cam.update(dt, key)

在屏幕上画点。

EN

回答 1

Stack Overflow用户

发布于 2021-11-27 04:52:50

矩阵乘法的定义不正确。我已经用呈现的风格重写了它,不过我要评论的是,有更多的节奏曲方法可以做到这一点:

代码语言:javascript
复制
def __mul__(self, other):
    if self.width != other.height:
        raise ValueError("incompatible matrices")

    result = []
    for h in range(self.height):
        row = []
        for w in range(other.width):
            SUM = 0
            for i in range(self.width):
                SUM += self.matrix[h][i] * other.matrix[i][w]
            row.append(SUM)
        result.append(row)
    return Matrix(result)
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/70132049

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档