纯Python 3.6.3-查找2个3d向量之间的度差

时间:2019-03-10 23:06:53

标签: python 3d turtle-graphics normals

出于某种不敬虔的原因,我试图通过龟库制作一个程序来显示纯Python 3.6.3中的线框图形。我已经到了要跳过为优化目的而绘制不必要的Tris的地步。不必要的Tris表示应由模型的其他部分(即法线背对3D摄像机)遮盖的Tris。

程序使用的模型数据只是一个巨大的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数学。

1 个答案:

答案 0 :(得分:0)

在数学上没有过多介绍的细节,在数学中有一种叫做点积的东西。

enter image description here

基本上,这是一种将两个向量(分别称为 a b )组合在一起的方法。此数字等于 a 的大小,再乘以 b 的大小,再乘以它们之间的夹角余弦(可以称为θ)。

借助此等式,通过四处移动,我们最终可以得到所需的θ。

假设我们有 a [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,如预期的那样。