注意:因为我是新成员,我显然需要10个声望来发布图片或超过2个链接,我将提到this imgur album的视觉效果。抱歉给您带来不便。
我试图制作一个程序来在python中可视化3D对象,但是我对将3D坐标投影到2D屏幕坐标上的函数有疑问。它在某些情况下有效,但不是全部。当相机相对远离该点并且在相同水平上时,投影看起来非常好,例如在该图像中描绘了十边形和矩形,其顶点由3D点定义(图2)。然而,当相机向下看时,它们描绘的物体不成比例地变平(图3),当相机接近它必须投射的点时,形状会变形(图4)。
有问题的函数是Camera.projectPoint,我已经包含了它在下面使用的所有函数和类:
class Vector3:
def __init__(self, x, y, z):
self.x = x
self.y = y
self.z = z
self.mag = math.sqrt(x**2+y**2+z**2)
self.yaw = math.atan2(self.y, self.x)
self.pitch = math.atan2(self.z, math.sqrt(self.x**2+self.y**2))
class Point:
def __init__(self, x, y, z):
self.x = x
self.y = y
self.z = z
def vectorTo(self, p):
return(Vector3(p.x-self.x, p.y-self.y, p.z-self.z))
class Camera:
def __init__(self, pos, yaw, pitch, FOV=math.pi/2):
self.pos = pos
self.yaw = yaw
self.pitch = pitch
self.FOV = FOV
def projectPoint(self, point):
## finding the vector from the camera position to the point
v = self.pos.vectorTo(point)
## setting alpha to the difference in yaw between the camera and the vector to the point
## and beta to the difference in pitch
alpha = v.yaw - self.yaw
beta = v.pitch - self.pitch
## making sure that the smallest angle between the two is chosen
## (difference between 300 degrees and 10 degrees is 70, not 290)
alpha = (alpha+math.pi)%(2*math.pi)-math.pi
beta = (beta+math.pi)%(2*math.pi)-math.pi
## Doing the operation pictured in the diagram
h = math.sin(self.FOV/2)/math.cos(self.FOV/2)
x1 = math.sin(alpha)/math.cos(alpha)
y1 = math.sin(beta)/math.cos(beta)
## adjusting for screen resolution
return(x1*1000/h+500, y1*1000/h+325)
我已经四处寻找将3D坐标投影到屏幕上的算法,并找到了许多内容,例如Figure 1中描述的内容(这是我的函数所基于的),但它似乎并没有很好地运作。这是算法的问题吗?我赞美它的方式?它使用的功能之一? (我99%肯定所有其他功能和类都非常好)。关于什么是错的以及如何解决它的任何想法?谢谢。