我决定尝试在Python中使用Pygame进行实验,这样我就可以通过pixelarray绘制到屏幕上了。我决定按照this article
来深入研究3D的数学简而言之,我已经实现了所有功能。我构建了矩阵和向量数学运算并遇到了一些问题,但经过大量(EXTENSIVE)测试后,操作现在完全可以工作(点,十字,正常,标量,平移,旋转等)。我花了很多时间在微软的网站上阅读文档,了解这些功能的工作原理。因此,这些是我的解释:
@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)
其他所有内容与文章完全相同。但是,当我插入相同的点时,我会看到屏幕,只能在屏幕上对角线看到一个随机点。在使用一些打印语句以数学方式观察过程之后,看起来从所有这些中产生的最终3d矢量中提取的x和y包含一些明显被剪裁的INSANELY大数字(根据文章中提到的剪切操作)和没有画在屏幕上。
我唯一的猜测是旋转已关闭,因为微软的网站声明他们首先执行Z旋转,然后是x,然后执行y。然而,这与我到目前为止所阅读的所有内容完全相矛盾(除非左手坐标系旋转遵循不同的排序规则)。此外,即使尝试这种或任何其他组合,我没有一个结果。我知道绘图代码有效,但我知道矩阵和矢量代码是可行的,但我猜它是数学?
另一个比显示更好解释的潜在问题代码可能是我在某种程度上实现的Vector3.TransformCoordinate函数。我猜这个函数只是从x,y,z坐标创建一个4x1矩阵,并将w设置为1,然后将此列矩阵乘以4x4变换矩阵。最后,得到的列矩阵的x和y分量将是像素的假定x和y位置。但是,如果这不正确,我可能不明白该功能究竟做了什么。
正如我所说,一切都与文章完全相同(如果它是用Python而不是C#编写的)。我发布的代码在数学方面似乎是错误的。无论是那个还是我都失去了理智。最近几天我一直在重复这个问题。从字面上看,任何帮助都将受到赞赏。
编辑:这是函数Project的Python版本:
def Project(self, vectorCoord, transMatrix):
#Add a w field to the vector and set it to 1.0
if len(vectorCoord) != 4:
vectorCoord.values.append(1.0)
#Multiply the transformation matrix by the 4x1 column matrix
threePoint = transMatrix * Vector.toColumnMatrix(vectorCoord)
#Extract the x as per the article's and martineau's instructions
x = ((threePoint[0][0]/threePoint[3][0])
* float(self.front_buffer.get_width())
+ float(self.front_buffer.get_width()) / 2.0)
#Extract the y as per the article's and martineau's instructions
y = (-(threePoint[1][0]/threePoint[3][0])
* float(self.front_buffer.get_height())
+ float(self.front_buffer.get_height()) / 2.0)
#Delete this so the 3D vectors will not forever have a w appended to them
del vectorCoord
return Vector([x, y])
编辑:这是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)