找到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个点)。
我有一对刻面,每个刻面由 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个点)。