Xform 4x4 matrix dizzyness -> transposing for export

I am trying to write a script that transposes block xforms so they relate to Unity’s cooridnate system for my VR. Would really like to maintain firm single source of the model. Rhino is so much better for obvious reasons.

I thought I had this solved but then did some more different blocks… and no. Some blocks will work depending on their symmetry and rotations.

Unity has Y as up and rhino’s X+ is unity’s X- and Rhino’s Y+ is unity’s Z-. I know, right?

So in the matrix row 3 relates to position in both. That’s solved and easy.

rows and colums 0-2 however are a bit trickier. I think I’ve got the order correct. This is the setup I’ve had the most success with, and it’s the only one I’ve deduced through trial and error that has a pattern to it… I.e. every row and column follows the same order (0,2,1) but rows for columns. Easier to see in picture:

	unityXform(0, 0) = rhinoXform(0, 0) '* -1
	unityXform(0, 1) = rhinoXform(2, 0) '* -1
	unityXform(0, 2) = rhinoXform(1, 0) '* -1
	unityXform(1, 0) = rhinoXform(0, 2) '* -1
	unityXform(1, 1) = rhinoXform(2, 2) '* -1
	unityXform(1, 2) = rhinoXform(1, 2) '* -1
	unityXform(2, 0) = rhinoXform(0, 1) '* -1
	unityXform(2, 1) = rhinoXform(2, 1) '* -1
	unityXform(2, 2) = rhinoXform(1, 1) '* -1	
	'correct position
	unityXform(0, 3) = rhinoXform(0, 3) * -1
	unityXform(1, 3) = rhinoXform(2, 3)
	unityXform(2, 3) = rhinoXform(1, 3) * -1
	' correct units
	unityXform(0, 3) = unityXform(0, 3) / 1000
	unityXform(1, 3) = unityXform(1, 3) / 1000
	unityXform(2, 3) = unityXform(2, 3) / 1000

So, assuming I’ve got the transposition part right, that leaves sign inversion.

These matricies are an absolute mystery to me and I’m doing this just by transforming the result in Unity and then spitting the numbers back out and comparing in excel. I think I’m starting to go a bit insane.

Hoping first that the solution is obvious to someone, and second to that… Interested in trying a brute force approach to the sign inversions. I think there’s 512 different possible combinations… So if I could write a loop that just exported all of them and then I could look for the correct transforms in unity and delete the wrong ones. 512 isn’t really that many, considering the way I’m doing this sortof in a dark room with a flashlight.

I have ZERO idea how to approach that though.

EDIT: I think I have tried all the obvious patterns for inversion, like inverting first of each row, first of each column, middle everything, first two, first and last, … etc. been working on this for a while. A small error on a pass though could have caused me to skip over an otherwise correct solution I suppose.


Use rhinoscript’s xform.rotation to get it to make the correct matrix for you.


Jim good idea doing this in the scripting instead of manually. Duh.

So… this transform is just inverting (2,0) and not actually moving the insert point in row 3… Am I doing something wrong? (goal being to invert the X coordinate at (0,3) in addition to actually mirroring the object)

Dim origin: origin = Array(0, 0, 0)
Dim PtX: PtX = Array(1.0, 0.0, 0.0)

Dim Xmirror: Xmirror = Rhino.XformMirror(origin, PtX)
For Each strObject In arrObjects
	unityXform = Rhino.BlockInstanceXform(strObject)
	unityXform = Rhino.XformMultiply(unityXform, Xmirror)

Maybe I’m getting confused and I don’t want any inversions except for the positional coordinates?

As a hint to convert from Rhino to Cycles I multiply object transforms with a matrix that scales negatively on the Z axis. This effectively gives the right coordinate system conversion.

You want to figure out a similar conversion matrix to multiply your transforms with.

I think I just need whatever math the OBJ exporter is using. The only reason my project is living in X- and Y- (labelled z in unity) is because that’s how the OBJ exports from Rhino naturally import and I didn’t want to have to pivot everything. (There’s no matrix mirroring built into unity) I think this has given me the right idea though. Hold my beer…

Transforming with a unit matrix should do. Relevant math from here :

// Rolf

OK I think I had some wires crossed as a sortof double-correction on the matrix read side in unity, which made all my previous pre-export transform attempts useless.

Seem to have it sortof working. Still some gremlins. I suspect there’s an alternate series of transforms I should be using now.

Am I correct in saying that if this was working correctly, it wouldn’t matter what orientation the blocks are? It should just work always no matter the rotation.

At least fairly confident my groundwork is in place at this stage.

Yes, true.

@wynott, Did you solve the rotation? If not, here’s some hints about how to define the transformation. I’m not sure if the last step is rotated in the right direction though, but if not, just remove the negative chars from Y and Z then it should rotate the other way around the X-axis.

Two step rotation with final unit matrix :

// Rolf

It seems I do! As of just now.


Worst thing I ever had to do.

Hope I don’t find out it’s wrong.

I can’t even say anything anyone would find useful.

It’s just been like… errors and assumptions because lack of understanding.

In the end it took a XformChangeBasis, plus two rotations, plus inverting two cells in the matrix deduced just from trial and error and comparing output.

I will distill it to a single transform matrix another day. Tired of this!

Thanks for the help All.

What a hate mission.


Hi all

I think I’m late on this … anyway here is my attempt:
change of basis, then mirror

unity.rvb (316 Bytes)
unity.3dm (30.1 KB)

… assuming I got it right.
I am alway quite confused about these things … :blush:


1 Like

Nice code example! That looks like changing from Right handed to Left handed (I could have read wynott’s description wrong, but it for sure sounds more probable that Unity would use Lefthanded instead of some other odd rotation).

Anyway, to do the same rotation in one shot you remove the negative sign on the swapped Z->Y -axis (last parenthesis):

Sub main
    obj = rhino.getobject("Object to rotate: ")
    xform = rhino.xformchangebasis( _
        array( 1, 0, 0), array(0, 1,  0), array(0, 0, 1), _
        array(-1, 0, 0), array(0, 0, -1), array(0, 1, 0))
    rhino.transformobject obj, xform
end sub

// Rolf

Hi Rolf

Hmmm … I thought I had tried that and that it was not working …
Anyway, I agree that that is the cleaner solution. :slight_smile: