我决定尝试在Python中使用Pygame进行一个实验,这样我就可以通过pixelarray绘制到屏幕上。我决定按照this article来钻研3D的数学
总之,我已经实现了每一个功能。我建立了矩阵和向量的数学运算,并有一些问题,但经过广泛(广泛的)测试,这些运算现在完全可以工作了(点、十字、法线、标量、平移、旋转等)。我花了相当多的时间在微软的网站上阅读这些函数如何工作的文档。因此,我的解释如下:@staticmethod
def lookAtLH(cameraTarget, cameraPosition, cameraUpVector):
zaxis = Vector.norm((cameraTarget - cameraPosition))
xaxis = Vector.norm(Vector.threeCross(cameraUpVector, zaxis))
yaxis = Vector.threeCross(zaxis, xaxis)
return Matrix ([[xaxis[0], yaxis[0], zaxis[0], 0.0],
[xaxis[1], yaxis[1], zaxis[1], 0.0],
[xaxis[2], yaxis[2], zaxis[2], 0.0],
[-Vector.dot(xaxis, cameraPosition), -Vector.dot(yaxis, cameraPosition), -Vector.dot(zaxis, cameraPosition), 1.0]])
@staticmethod
def PerspectiveFovRH(FOV, aspectRatio, NP, FP):
D = (NP - FP)
h = (1.0 / (math.tan(FOV / 2.0)))
w = (h / aspectRatio)
try:
one = FP/D
except ZeroDivisionError:
one = 0.0
try:
two = ((NP*FP)/D)
except ZeroDivisionError:
two = 0.0
return Matrix ([[w, 0.0, 0.0, 0.0],
[0.0, h, 0.0, 0.0],
[0.0, 0.0, one, -1.0],
[0.0, 0.0, two, 0.0]])
@staticmethod
def RotationYawPitchRoll(xRot, yRot, zRot):
zaxis = Matrix([[math.cos(zRot), math.sin(zRot), 0.0, 0.0],
[-math.sin(zRot), math.cos(zRot), 0.0, 0.0],
[0.0, 0.0, 1.0, 0.0],
[0.0, 0.0, 0.0, 1.0]])
yaxis = Matrix([[math.cos(yRot), 0.0, -math.sin(yRot), 0.0],
[0.0, 1.0, 0.0, 0.0],
[math.sin(yRot), 0.0, math.cos(yRot), 0.0],
[0.0, 0.0, 0.0, 1.0]])
xaxis = Matrix([[1.0, 0.0, 0.0, 0.0],
[0.0, math.cos(xRot), math.sin(xRot), 0.0],
[0.0, -math.sin(xRot), math.cos(xRot), 0.0],
[0.0, 0.0, 0.0, 1.0]])
return ((xaxis * yaxis) * zaxis)
其他的都和文章完全一样。然而,当我插入相同的点时,我观察屏幕,只看到一个随机的点斜斜斜地斜放在屏幕上。在使用一些print语句以数学方式观察过程之后,从最终生成的3d向量中提取的x和y似乎包含了一些非常大的数字,这些数字明显被剪裁(根据文章中提到的裁剪操作)而不是在屏幕上绘制的。在
我唯一的猜测是,当微软网站声明他们先执行Z轴旋转,然后x轴旋转,然后y轴旋转时,这是完全错误的(除非左手坐标系的旋转遵循不同的排序规则)。而且,即使是尝试这个或任何其他组合,我也没有得到任何结果。我知道绘图代码是可行的,我也知道矩阵和向量代码是可行的,但我猜这是数学问题?在
另一个潜在的问题代码可能是我实现的Vector3.TransformCoordinate函数。我猜这个函数只是从x,y,z坐标创建一个4x1矩阵,将w设置为1,然后将列矩阵乘以4x4变换矩阵。最后,得到的列矩阵的x和y分量将是像素的假定x和y位置。但是如果这个函数不正确的话,我可能不明白这个函数的真正作用。在
正如我所说,一切都和文章完全一样(如果它是用Python而不是C编写的话)。我发布的代码在数学上似乎是错误的。不是那样,就是我疯了。这几天我真的一次又一次地回顾了这件事。从字面上说,任何帮助都将被感激。在
编辑:以下是函数项目的Python版本:
^{pr2}$
编辑:这里是Render()函数:def Render(self, camera, meshes):
i = j = 0
meshList = [meshes]
viewMatrix = Matrix.lookAtLH(camera.Position, camera.Target, Vector([0.0, 1.0, 0.0]))
projectionMatrix = Matrix.PerspectiveFovRH(0.78, float(self.front_buffer.get_width())/float(self.front_buffer.get_height()), 0.01, 1.0)
for mesh in meshList:
worldMatrix = (Matrix.RotationYawPitchRoll(mesh.Rotation[0],
mesh.Rotation[1],
mesh.Rotation[2])
* Matrix.Translate(mesh.Position))
transformMatrix = worldMatrix * viewMatrix * projectionMatrix
for vector in mesh.Vertices:
point = self.Project(vector, transformMatrix)
self.DrawPoint(point)