Ben Supnik Wrote:I think "fixing a rounded rotation" is getting way into the territory of a batch process we should consider running on the library, then fast-tracking if the mechanical transformation can be demonstrated and spot-tested to be good. :-)
What I like about pre-processing is that the code runs once and a human can inspect the results. Every bit of 'mesh repair' I put into BrickSmith is code whose results are somewhat hidden to the part author, and whose results (as data) can only be viewed by a programmer with source code and a debugger. It's an opaque process, so the less complicated that black box, the better.
(Or maybe I am just lazy and want to keep my end of the code simple. ;-)
cheers
ben
I Agree!
Furthermore, a lot of code (and time) is spent to fix parts definition problems.
Following a pair of useful (I hope) function to extract the rotation portion of a matrix:
Given the matrix M, you call GetMatrixScale to get scale factor Vs of M along x,y,z axis
vs=GetMatrixScale(M)
then you call the M=PurifyMatrix(M,Vs,vt) to get back M as a pure rotation matrix. The VT parameter is a vector containing original M translation values
Finally you can get the rotation angles along each 3 axles that M was built by:
vRot=GetMatrixRot(M)
vRot is a x,y,z vector containing a value representing the rotation around the specific axle that built M
To recreate M you can multiply the 3 matrix resulting by creating a rotation matrix around any of the 3axles by the amount o vRot:
xM=matrix.rotationaxleX(vrot.x)
yM=matrix.rotationaxleY(vrot.y)
zM=matrix.rotationaxleZ(vrot.z)
M= xM x yM x zM
Hope this could useful for someone...
Sergio
About the code: it is for DirectX matrix notation. For openGL standard you may need to transpose matrix values
Code:
Function GetMatrixScale(ByRef M As Matrix) As Vector3
Dim V As Vector3
With M
V = Vec3(CSng(Math.Sqrt(.M11 * .M11 + .M12 * .M12 + .M13 * .M13)), CSng(Math.Sqrt(.M21 * .M21 + .M22 * .M22 + .M23 * .M23)), CSng(Math.Sqrt(.M31 * .M31 + .M32 * .M32 + .M33 * .M33)))
V.Y = V.Y * Math.Sign(.M21 + .M22 + .M23)
Return RoundV(V)
End With
End Function
Function PurifyMatrix(ByVal M As Matrix, ByRef vS As Vector3, ByRef vT As Vector3) As Matrix
With M
.M11 /= vS.X : .M12 /= vS.X : .M13 /= vS.X
.M21 /= vS.Y : .M22 /= vS.Y : .M23 /= vS.Y
.M31 /= vS.Z : .M32 /= vS.Z : .M33 /= vS.Z
vT = Vec3(.M41, .M42, .M43)
.M41 = 0 : .M42 = 0 : .M43 = 0
End With
Return M
End Function
Function GetMatrixRot(ByVal M As Matrix) As Vector3
Dim vRot As Vector3
With vRot
If Abs(M.M13) > 1 Then M.M13 = Sign(M.M13)
.Y = CSng(Math.Asin(M.M13))
If Math.Sin(.Y) > 0.99999 Or Math.Sin(.Y) < -0.99999 Then
.X = 0
.Z = -CSng(Math.Atan2(M.M21, M.M22))
Else
.X = CSng(Math.Atan2(M.M23, M.M33))
.Z = CSng(Math.Atan2(M.M12, M.M11))
End If
End With
Return vRot
End Function