出于一些不道德的原因,我正在尝试制作一个程序,以使用龟库在纯python 3.6.3中显示线框图形。我已经到了我想跳过为优化目的绘制不必要的tris的地步。不必要的tris意味着tris应该被模型的其他部分遮挡 - 即,正常面向远离3d相机。
程序正在使用的模型数据只是一个巨大的3d数组,每个tri都有以下格式。
[[Vert],[Vert],[Vert],[Normal]]
我当前的代码版本只有一个为它制作的模型(一个立方体),看起来像这样:
from turtle import *
Cube = [[[-50,50,-50],[-50,50,50,],[50,50,50],[0,1,0]],
[[-50,50,-50],[50,50,50,],[50,50,-50],[0,1,0]],
[[-50,50,-50],[-50,50,50],[-50,-50,50],[1,0,0]],
[[-50,50,-50],[-50,-50,-50],[-50,-50,50],[1,0,0]],
[[-50,50,50],[50,50,50],[50,-50,50],[0,0,1]],
[[-50,50,50],[50,-50,50],[-50,50,50],[0,0,1]],
[[-50,-50,-50],[-50,-50,50,],[50,-50,50],[0,-1,0]],
[[-50,-50,-50],[50,-50,50,],[50,-50,-50],[0,-1,0]],
[[50,50,-50],[50,50,50],[50,-50,50],[-1,0,0]],
[[50,50,-50],[50,-50,-50],[50,-50,50],[-1,0,0]],
[[-50,50,-50],[50,50,-50],[50,-50,-50],[0,0,-1]],
[[-50,50,-50],[50,-50,-50],[-50,50,-50],[0,0,-1]]]
CamVector = [0,1,0]
def DrawModel(Model):
for i in range(0,len(Model)):
goto(Model[i][0][0],Model[i][0][1])
pd()
goto(Model[i][1][0],Model[i][1][1])
goto(Model[i][2][0],Model[i][2][1])
goto(Model[i][0][0],Model[i][0][1])
pu()
Model = Cube
DrawModel(Model)
但我想比较每个tri的法线与CamVector,所以代码最终看起来像这样:
def DrawModel(Model):
for i in range(0,len(Model)):
AngleAwayFromCamera = *Math voodoo*
if AngleAwayFromCamera <= 90:
*draw tri*
如果有人对如何提供帮助有任何想法可以解释给像我这样核桃大小的大脑的人会很棒。我看了很多文档,但大多数文件已经飞过我的脑海 - 可能是因为我的GCSE数学失败了。
没有过多的数学细节,在数学中有一种叫做点积的东西:
基本上,它是一种组合两个向量(称为a和b)以获得单个数字的方法。这个数等于a的大小,乘以b的大小,乘以它们之间角度的余弦(我们可以称之为θ)。
多亏了这个等式,通过改变周围的事物,我们最终可以得到我们想要的东西,即θ。
假设我们有:[1, 2, 3]
和b:[4, 5, 6]
。我们可以通过平方元素并取总和的平方根来计算它们的大小。因此,a的大小是(1 ** 2 + 2 ** 2 + 3 ** 2) ** 0.5 = 14 ** 0.5
,而b的大小是(4 ** 2 + 5 ** 2 + 6 ** 2) ** 0.5 = 77 ** 0.5
。
将它们相乘给我们1078 ** 0.5
。因此,点积等于(1078 ** 0.5) * cos θ
。
事实证明,可以通过将两个矢量的相应元素相乘并将结果相加来计算点积。因此,对于上面的a和b,点积是1 * 4 + 2 * 5 + 3 * 6 = 32
。
给定这两个不同(但相等)的点积的表达式,我们可以将它们等同于求解θ,如下(arccos是将cosθ变为θ的函数):
(1078 ** 0.5) * cos θ = 32
cos θ = 32 / (1078 ** 0.5)
θ = arccos(32 / (1078 ** 0.5))
θ ≈ 12.93 (in degrees)
现在,剩下的就是在代码中实现它:
from numpy import arccos
def angle_between_vectors(v1, v2):
def magnitude(v):
return sum(e ** 2 for e in v) ** 0.5
dot_product = sum(e1 * e2 for e1, e2 in zip(v1, v2))
magnitudes = magnitude(v1) * magnitude(v2)
angle = arccos(dot_product / magnitudes)
return angle
将此函数应用于上面的a和b并从弧度转换为度(除以π并乘以180)得到12.93,如预期的那样。