python - 为什么翻译矩阵不影响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])])
解决方案
您正在使用同质坐标来表示模型的顶点。所以 W 分量必须为 1。
加载模型时,您将 W 设置为 0。
verts.append(vec3(float(values[1]), float(values[2]), float(values[3]), 0 ))
通过设置 W=0,您将创建一个齐次向量(也称为“无限远点”或“理想点”),通过设置 W=1,您将创建一个齐次点。
点可以平移,但向量不能。
推荐阅读
- performance - SwiftUI ObservableObject CPU 峰值
- c# - 从 MVC 中控制器中的不同方法向视图发送消息
- node.js - 如何调用 MERN 应用程序中 /src 文件夹之外的节点 indexjs?
- java - Java方法().method().method(); 这个怎么做?
- arcore - 用于谷歌场景查看器的 Realme X2 中缺少“在空间中查看”选项
- c# - 我网站所有页面的 URL 是怎样的:WebName/{title}
- salesforce - 将功能齐全的 Aura 组件包部署到其他环境后,它总是抛出错误“无法读取未定义的属性 __”
- javascript - Vuejs _.orderBy 没有对 json 进行排序
- python - 为什么第一次运行 timeit 通常比后续运行慢?
- javascript - 如何使用两个分开的图像上传预览?