为什么平移矩阵不影响python中三维模型的渲染?

为什么平移矩阵不影响python中三维模型的渲染?,python,matrix,3d,Python,Matrix,3d,我对编码非常陌生,决定从python中的3D引擎开始。我遵循OLC的教程,并将其改编为python。但是,我的转换矩阵似乎不会影响模型的渲染方式。任何建议,从代码改进到告诉我自己有多糟糕,都将不胜感激 我尝试过以各种方式重新做向量乘法,各种各样的重新格式化和重新尝试,但我甚至不确定在这种情况下我在寻找什么。任何帮助都将不胜感激 由于我是新来的,我为我在这个网站上所做的任何不礼貌的行为道歉 import math, numpy as np, pygame, sys, os, random, str

我对编码非常陌生,决定从python中的3D引擎开始。我遵循OLC的教程,并将其改编为python。但是,我的转换矩阵似乎不会影响模型的渲染方式。任何建议,从代码改进到告诉我自己有多糟糕,都将不胜感激

我尝试过以各种方式重新做向量乘法,各种各样的重新格式化和重新尝试,但我甚至不确定在这种情况下我在寻找什么。任何帮助都将不胜感激

由于我是新来的,我为我在这个网站上所做的任何不礼貌的行为道歉

import math, numpy as np, pygame, sys, os, random, string
from pygame.locals import *

pygame.init()
width,height = 1600,900;cx,cy = width//2,height//2
screen = pygame.display.set_mode((width,height))
clock = pygame.time.Clock()
font = pygame.font.SysFont("Arial", 18)
pygame.display.set_caption('3D Graphics')

def loadObj(filename):
    tris = []
    verts = []
    try:
        fp = open(filename, "r")
    except:
        print("File: "+filename+" not found")
        sys.exit(1)
    for line in fp:
        if line.startswith('#'): continue
        values = line.split()
        if not values: continue
        if values[0] == 'v':
            #v = vec3(float(values[1]), float(values[2]), float(values[3]))
            #verts.append(vec3(int(values[1]), int(values[2]), int(values[3])))
            verts.append(vec3(float(values[1]), float(values[2]), float(values[3]), 0 ))
            #verts.append(v)
        elif values[0] == 'f':
            p = []
            for v in values[1:]:
                w = v.split("/")
                p.append(int(w[0]))
                #print(p)


            #print(verts[-185])
            triTemp = triangle(verts[p[0] - 1], verts[p[1] - 1], verts[p[2]- 1])
            tris.append(triTemp)
            
    fp.close()
    return tris

class vec3():                                       #Possibly Obsolete
    __slots__ = ['x','y','z','w']
    def __init__(self, x, y, z, w):
        self.x = x
        self.y = y
        self.z = z
        self.w = w
class triangle():
    __slots__ = ['vec1','vec2','vec3']
    def __init__(self, vec1, vec2, vec3):
        self.vec1 = vec1
        self.vec2 = vec2
        self.vec3 = vec3

def matrixMakeTranslation(x, y, z):
    
    matrix = np.zeros((4,4))
    matrix[0,0] = 1.0
    matrix[1,1] = 1.0
    matrix[2,2] = 1.0
    matrix[3,3] = 1.0
    matrix[3,0] = x
    matrix[3,1] = y
    matrix[3,2] = z
    return matrix

def Matrix_MakeRotationX(fAngleRad):
    matrix = np.zeros((4,4))
    matrix[0,0] = 1.0
    matrix[1,1] = (math.cos(fAngleRad * 0.5))
    matrix[1,2] = (math.sin(fAngleRad * 0.5))
    matrix[2,1] = (-math.sin(fAngleRad * 0.5))
    matrix[2,2] = (math.cos(fAngleRad * 0.5))
    matrix[3,3] = 1.0
    return matrix

def Matrix_MakeRotationZ(fAngleRad):

    matrix = np.zeros((4,4))
    matrix[0,0] = (math.cos(fAngleRad))
    matrix[0,1] = (math.sin(fAngleRad))
    matrix[1,0] = (-math.sin(fAngleRad))
    matrix[1,1] = (math.cos(fAngleRad))
    matrix[2,2] = 1.0
    matrix[3,3] = 1.0
    return matrix

fNear = float(0.1)                                                      #Create the Projection Matrix
fFar = float(1000.0)
fFov = float(90.0)
fAspectRatio = float(height/width)
fFovRad = 1/math.tan(fFov * 0.5 / 180 * math.pi)

projectionMatrix = np.zeros((4,4))
projectionMatrix[0,0] = fAspectRatio * fFovRad
projectionMatrix[1,1] = fFovRad
projectionMatrix[2,2] = fFar / (fFar - fNear)
projectionMatrix[3,2] = float((-fFar * fNear) / (fFar - fNear))
projectionMatrix[2,3] = 1.0
projectionMatrix[3,3] = 0.0

meshname = "teapot.obj"                                               #Load the mesh
tris = loadObj(meshname)


vCamera = np.array([0,0,0,0])
fAngleRad = 0

colour = (255,255,255)
colour2 = (0,0,0)

triProjected = triangle(np.array([0,0,0,0]),np.array([0,0,0,0]),np.array([0,0,0,0]))           #These are used later
triTranslalted = triangle(np.array([0,0,0,0]),np.array([0,0,0,0]),np.array([0,0,0,0]))
triTransformed= triangle(np.array([0,0,0,0]),np.array([0,0,0,0]),np.array([0,0,0,0]))
while True:                                                                                             #Begin Loop
    for event in pygame.event.get():                                                                    #Quit
            if event.type == pygame.QUIT: pygame.quit(); sys.exit()
    dt = clock.tick()/1000
    pygame.display.set_caption('3D Graphics - FPS: %.2f'%int(dt))
    print("fps:", clock.get_fps())                                                                      #Framerate and caption
    pygame.display.update()
    screen.fill((0,0,0))

    fAngleRad += 0.1
    matRotZ = Matrix_MakeRotationZ(fAngleRad * 0.5)                                                     #Set up matricies
    matRotX = Matrix_MakeRotationX(fAngleRad)
    matTrans = matrixMakeTranslation(0.0,0.0,50.0)
    matWorld = np.identity(4)
    matWorld = matRotZ @ matRotX
    matWorld = matWorld @ matTrans                                                                      #Seems to be broken. idk why.

    for i in tris:                                                                                      #For triangle in all triangles

        reDo1 = np.array([i.vec1.x, i.vec1.y, i.vec1.z, i.vec1.w])
        reDo2 = np.array([i.vec2.x, i.vec2.y, i.vec2.z, i.vec2.w])
        reDo3 = np.array([i.vec3.x, i.vec3.y, i.vec3.z, i.vec3.w])

        triTransformed.vec1 = np.matmul(matWorld, reDo1)
        triTransformed.vec2 = np.matmul(matWorld, reDo2)
        triTransformed.vec3 = np.matmul(matWorld, reDo3)

        triProjected.vec1 = np.matmul(projectionMatrix, triTransformed.vec1)
        triProjected.vec2 = np.matmul(projectionMatrix, triTransformed.vec2)
        triProjected.vec3 = np.matmul(projectionMatrix, triTransformed.vec3)

        #Scale Into View
        triProjected.vec1[0] += 1.0
        triProjected.vec1[1] += 1.0
        
        triProjected.vec2[0] += 1.0
        triProjected.vec2[1] += 1.0
        
        triProjected.vec3[0] += 1.0
        triProjected.vec3[1] += 1.0

        triProjected.vec1[0] *= 0.5 * width
        triProjected.vec1[1] *= 0.5 * height
        
        triProjected.vec2[0] *= 0.5 * width
        triProjected.vec2[1] *= 0.5 * height
        
        triProjected.vec3[0] *= 0.5 * width
        triProjected.vec3[1] *= 0.5 * height

            
        pygame.draw.polygon(screen, colour, [(triProjected.vec1[0], triProjected.vec1[1]),(triProjected.vec2[0], triProjected.vec2[1]),(triProjected.vec3[0], triProjected.vec3[1])])

您正在使用同伦坐标来表示模型的顶点。所以W分量必须是1

加载模型时,将W设置为0

verts.append(vec3(float(values[1]), float(values[2]), float(values[3]), 0 ))
通过设置W=0,您创建了一个齐次向量(也称为“无穷远点”或“理想点”),通过设置W=1,您创建了一个齐次点

点可以转换,但向量不能


您正在使用齐次坐标来表示模型的顶点。所以W分量必须是1

加载模型时,将W设置为0

verts.append(vec3(float(values[1]), float(values[2]), float(values[3]), 0 ))
通过设置W=0,您创建了一个齐次向量(也称为“无穷远点”或“理想点”),通过设置W=1,您创建了一个齐次点

点可以转换,但向量不能


非常感谢你的帮助,你说得很对,我把事情搞砸了;我没在想。然而,这似乎没有帮助。我通常会自己去想办法,但我还是迷路了,如果你能给我其他的建议,我将不胜感激。你能描述一下你看到了什么吗?到底出了什么问题?更改“matTrans=MatrixMakeTransation(0.0,0.0,50.0)”似乎不会影响模型的渲染方式;这和我以前遇到的问题是一样的,即使是在实施了您的修复之后。非常感谢您给我的所有帮助。函数MatrixMakeTransformation应该有:矩阵[0,3]=x矩阵[1,3]=y矩阵[2,3]=z,因为它是主列。matWorld的乘法顺序应该是:matWorld=matTrans@matRotX@matRotZ。最后,我认为这个预测是错误的。投影操作涉及按W坐标(或Z坐标,取决于投影模型)进行除法,但这在代码中不存在。我已经实现了这些修复,但我仍然无法使用MatMakeTransformation偏移模型的位置,即使在实现了修复之后也是如此。我有一个旧版本,它没有使用numpy,但它也没有实现w轴,所以可能在某些地方它仍然是一个向量或其他东西。请帮我谢谢你的帮助,你说得很对,我把事情搞砸了;我没在想。然而,这似乎没有帮助。我通常会自己去想办法,但我还是迷路了,如果你能给我其他的建议,我将不胜感激。你能描述一下你看到了什么吗?到底出了什么问题?更改“matTrans=MatrixMakeTransation(0.0,0.0,50.0)”似乎不会影响模型的渲染方式;这和我以前遇到的问题是一样的,即使是在实施了您的修复之后。非常感谢您给我的所有帮助。函数MatrixMakeTransformation应该有:矩阵[0,3]=x矩阵[1,3]=y矩阵[2,3]=z,因为它是主列。matWorld的乘法顺序应该是:matWorld=matTrans@matRotX@matRotZ。最后,我认为这个预测是错误的。投影操作涉及按W坐标(或Z坐标,取决于投影模型)进行除法,但这在代码中不存在。我已经实现了这些修复,但我仍然无法使用MatMakeTransformation偏移模型的位置,即使在实现了修复之后也是如此。我有一个旧版本,它没有使用numpy,但它也没有实现w轴,所以可能在某些地方它仍然是一个向量或其他东西。请帮帮我