首页 > 解决方案 > 为什么翻译矩阵不影响python中3d模型的渲染?

问题描述

我对编码非常陌生,因此决定从 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])])

标签: pythonmatrix3d

解决方案


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

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

verts.append(vec3(float(values[1]), float(values[2]), float(values[3]), 0 ))

通过设置 W=0,您将创建一个齐次向量(也称为“无限远点”或“理想点”),通过设置 W=1,您将创建一个齐次点。

点可以平移,但向量不能。

https://en.m.wikipedia.org/wiki/Homogeneous_coordinates


推荐阅读