Normals issue with exported mesh of mirrored linked blocks

Hm. Well, I am guessing a bit at what you need, but, if you get the instance’s transformation matrix and apply that to the WorldXY plane, then there is a chance, assuming the block was created alinged to the orgin and world plane, that the resulting plane’s axes will have some useful relation to the block instance - as far as I know there is no inherent plane or axis in a block instance…

for instance:

Call Main()
Sub Main()
Dim sBlock: sBlock = Rhino.GetObject(, 4096, True, True)
Dim xform: xform = Rhino.BlockInstanceXform(sBlock)
Dim tempPlane: tempPlane = Rhino.PlaneTransform(Rhino.WorldXYPlane(), xform)

’ next bit is all one line
Dim sAxisLIne: sAxisLIne = Rhino.AddLine(tempPlane(0), Rhino.PointAdd(tempPlane(0), Rhino.VectorScale(tempPlane(2), 20)))
’ end all one line.

End Sub

More completely-

Sub Main()
Dim sBlock: sBlock = Rhino.GetObject(, 4096, True, True)
If isNull(sBlock) Then Exit Sub

'the block instance's transform
Dim xform
xform = Rhino.BlockInstanceXform(sBlock)

'Find a plane transformed like the block instance
Dim tempPlane
tempPlane = Rhino.PlaneTransform(Rhino.WorldXYPlane(), xform)

'find a point on the block's Y axis.
Dim py
py = Rhino.PointAdd(tempPlane(0), tempPLane(2))

'find the center of rotation
Dim p1
p1 = Rhino.LinePlaneIntersection(array(tempPlane(0), py), Rhino.WorldYZPlane())

'Get a point on the YZ plane
Dim p2
p2 = Rhino.PlaneClosestPoint(Rhino.WorldYZPlane(), py)

'The block Y vector projected to the World YZ plane
Dim vecDir
vecDir = Rhino.VectorCreate(p1, p2)

Dim ang
ang = Rhino.VectorAngle(tempPLane(2), vecDir) 

'Right to left use - angle, left to right use + angle
Rhino.RotateObject sBlock, p1, -ang * 2, tempPlane(3), True

End Sub


I’m losing my mind here. haha now it’s a challenge though. can’t let it beat us.

I think (strategically) I have a method figured out that I think works every time.

Script as shown works good if objects are only rotated around Z but goes wonky with multiple rotations.

Instead of intersecting the block’s temp plane with with world plane, need to make a temporary mirror of the temp plane, and intersect both temp planes with each other, then rotate about that.

then have special case for if there is no rotation around z and intersect with world in that situation.

i think

Hi Ryan - you can take one extra step and project the block-plane’s Y axis to the World XY plane before projecting it to the YZ plane and before finding the axis line/YZ plane intersection.


I give up. Was a good sport. Test file attached.test file.3dm (253.7 KB)stanchion.3dm (465.5 KB)

Yeah… it works, sort of, but there is no good way to tell how the plane should be handled - X axis, Y axis + angle, - Angle,. I fiddled the model around to Y as a test and it does work if the vectors are all flattened to the WorldXY plane etc. If I have time I’ll see if I can make it smarter…


Not sure I follow…

I’ve added a plane in the stanchions ZY just so we can sortof visualize what’s going on.

If you make a temporary mirror of the block and find same plane of mirrored version also… Should give two planes to intersect, right?

Then rotate the “good” block along this intersection until it hits the temporary block’s position, in either direction, and it should give the desired result, no?

I guess intersecting the block’s ZY with the scene’s ZX actually gives the same result as block ZY and mirror block ZY.


What I did was rotate the block the way I wanted it in Rhino using rotate3d. Then used this script to compare the xform matrix in excel:

Dim strObject
strObject = Rhino.GetObject(“Select block”)
Dim xform
xform = Rhino.BlockInstanceXform(strObject)
Rhino.Print xform(0, 0)
Rhino.Print xform(0, 1)
Rhino.Print xform(0, 2)
Rhino.Print xform(0, 3)
Rhino.Print " "
Rhino.Print xform(1, 0)
Rhino.Print xform(1, 1)
Rhino.Print xform(1, 2)
Rhino.Print xform(1, 3)
Rhino.Print " "
Rhino.Print xform(2, 0)
Rhino.Print xform(2, 1)
Rhino.Print xform(2, 2)
Rhino.Print xform(2, 3)
Rhino.Print " "
Rhino.Print xform(3, 0)
Rhino.Print xform(3, 1)
Rhino.Print xform(3, 2)
Rhino.Print xform(3, 3)

Theres probably a more elegant way to do that with a loop but anyway…

So turned out the only difference were some sign inversions between the original and what I wanted so it became really simple.

	'Get the transforms from the original block
	xform = Rhino.BlockInstanceXform(strObject)
	'Modify the transforms via black box of mystery
	xform(0, 0) = xform(0, 0) * -1
	xform(1, 1) = xform(1, 1) * -1
	xform(1, 2) = xform(1, 2) * -1
	xform(1, 3) = xform(1, 3) * -1
	xform(2, 0) = xform(2, 0) * -1
	'apply the xfrom to the copied block
	Rhino.BlockInstanceXform strCopiedBlock, xform

ToOtherSide.rvb (1.3 KB)