I have a pair of facets, each made of 4 points, in 3D space. I know the winding direction of the facets' vertices such that if both facets were facing the viewer each facet's points would follow anti-clockwise.
I am trying to work out how to determine the first facet's facing direction so that I can rotate the second facet to face in the same direction.
I can rotate points using matrix multiplication, but I cannot determine existing direction.
Do I need to simply calculate the angle of vertices in each plane (x-y, x-z, y-z) or is it more complex than that?
I have this almost working. Unfortunately, the result is that I'm always receiving a 90 degree turn from the direction I'm looking to get.
The process is to create two facets, both facing the same direction, then rotate one of the randomly on the X, Y and Z axis. The code I'm trying to build up should determine the facing direction of the randomly rotated facet and produce a rotation matrix which can be applied to the first facet to make it face the same direction.
I would like the rotation matrix to work for any facet facing in any direction so that any facet can be rotated to face the same direction as the randomly rotated facet.
Here's the full code for what I have so far (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
This produces the following image. The green facet is 'b' and has been randomly rotated around all three axis. The black facet is 'a' and has been rotated per the 'rotmat' matrix to try to face it in the same direction as 'b'.
As you can see, the black facet 'a' has been rotated to 90degrees around the Y axis. I've tried to account for this, but I can't. Can someone explain what I'm doing wrong? The only code I've left out is the rendering code because it's not relevant here - and would be too long winded to include.
If your 4 points are on the same plane and you want to find the normal of the plane, just normalize the cross product of two non-parallel edges (you only need 3 points).