找到3D面的方向向量

Find the direction vector of 3D facet

我有一对刻面,每个刻面由 4 个点组成,呈 3D space。我知道小平面顶点的缠绕方向,如果两个小平面都面向观察者,每个小平面的点都会逆时针旋转。

我正在尝试确定如何确定第一个面的朝向,以便我可以将第二个面旋转到相同的方向。

我可以使用矩阵乘法旋转点,但我无法确定现有方向。

我需要简单地计算每个平面 (x-y, x-z, y-z) 中顶点的角度还是比这更复杂?


我几乎可以正常工作了。不幸的是,结果是我总是从我想要的方向获得 90 度的转弯。

这个过程是创建两个面向相同方向的小平面,然后在 X、Y 和 Z 轴上随机旋转其中一个。我正在尝试构建的代码应该确定随机旋转面的朝向并生成一个旋转矩阵,该矩阵可以应用于第一个面以使其朝向相同的方向。

我希望旋转矩阵适用于面向任何方向的任何小平面,以便任何小平面都可以旋转到与随机旋转小平面相同的方向。

这是我目前拥有的完整代码 (Lua):

local function newXRotationMatrix( x )
    x = math.rad(x)
    return {
        {1,0,0,0},
        {0,math.cos(x),math.sin(x),0},
        {0,-math.sin(x),math.cos(x),0},
        {0,0,0,1},
    }
end

local function newYRotationMatrix( y )
    y = math.rad(y)
    return {
        {math.cos(y),0,-math.sin(y),0},
        {0,1,0,0},
        {math.sin(y),0,math.cos(y),0},
        {0,0,0,1},
    }
end

local function newZRotationMatrix( z )
    z = math.rad(z)
    return {
        {math.cos(z),math.sin(z),0,0},
        {-math.sin(z),math.cos(z),0,0},
        {0,0,1,0},
        {0,0,0,1},
    }
end

local function multiply( aMatrix, bMatrix )
    if #aMatrix[1] ~= #bMatrix then
        return nil      
    end 

    local empty = {
            {0,0,0,0},
            {0,0,0,0},
            {0,0,0,0},
            {0,0,0,0},
        }

    for aRow = 1, #aMatrix do
        for bCol = 1, #bMatrix[1] do
            local sum = empty[aRow][bCol]
            for bRow = 1, #bMatrix do
                sum = sum + aMatrix[aRow][bRow] * bMatrix[bRow][bCol]
            end
            empty[aRow][bCol] = sum
        end
    end

    return empty
end

local function vector2d3dLength( vector )
    return math.sqrt( vector[1]*vector[1] + vector[2]*vector[2] + vector[3]*vector[3] )
end

local function normalise2d3dVector( vector )
    local len = vector2d3dLength( vector )

    if (len == 0) then
        return vector
    end

    local normalised = { vector[1]/len, vector[2]/len, vector[3]/len }

    return normalised
end

local function subtract2d3dVectors( a, b )
    local sub = { a[1]-b[1], a[2]-b[2], a[3]-b[3] }

    return sub
end

local function crossProduct3d( a, b )
    return {
        a[2]*b[3] - a[3]*b[2],
        a[3]*b[1] - a[1]*b[3],
        a[1]*b[2] - a[2]*b[1],
    }
end

local function new3dMatrix( x, y, z )
    return {
        {x[1],x[2],x[3],0},
        {y[1],y[2],y[3],0},
        {z[1],z[2],z[3],0},
        {0,0,0,1},
    }
end

local function getLookAtMatrix( bt )
    local T = normalise2d3dVector( subtract2d3dVectors( bt[2], bt[1] ) ) -- normalize(P1 - P0)
    local N = normalise2d3dVector( crossProduct3d( subtract2d3dVectors( bt[3], bt[1] ), T ) ) -- normalize(cross(T, P2 - P0))
    local B = normalise2d3dVector( crossProduct3d( T, N ) ) -- normalize(cross(T, N))
    local rotmat = new3dMatrix( T, N, B ) -- rotMat = mat3(T, N, B)
    return rotmat
end

local a = {
    { -100, -100, -100, 1 },
    { -100, 100, -100, 1 },
    { 100, 100, -100, 1 },
    { 100, -100, -100, 1 },
}
local b = {
    { -100, -100, -100, 1 },
    { -100, 100, -100, 1 },
    { 100, 100, -100, 1 },
    { 100, -100, -100, 1 },
}

local matrix = multiply( newZRotationMatrix( 160 ), newYRotationMatrix( 30 ) )
matrix = multiply( matrix, newXRotationMatrix( 40 ) )

-- APPLY 'matrix' MATRIX TO 'b' VECTOR TABLE AND DISPLAY ON SCREEN

local bt = b.transformed

local rotmat = getLookAtMatrix( bt )

-- APPLY 'rotate' MATRIX TO 'a' VECTOR TABLE AND DISPLAY ON SCREEN

这将生成以下图像。绿色的面是 'b' 并已围绕所有三个轴随机旋转。黑色面是 'a' 并且已根据 'rotmat' 矩阵旋转以尝试以与 'b'.

相同的方向面对它

如您所见,黑色面 'a' 已绕 Y 轴旋转 90 度。我试图解释这一点,但我做不到。有人可以解释我做错了什么吗?我遗漏的唯一代码是渲染代码,因为它在这里不相关 - 并且会太冗长而无法包含。

如果你的4个点在同一个平面上,想求平面的法线,只需要归一化两条不平行边的叉积即可(只需要3个点)。