Having an issue where the normals are getting flipped on the exported mesh when I mirror linked blocks.
Both of these stanchions are instances of the same block. Left side looks correct, where as right side is rendering inside out.
No real way for me to correct this, other than not mirror things (Which is a disaster for workload when making a symmetrical boat) or possibly having a duplicate block that starts out inside out then replace block on the other side?
As an aside this explains why my mirrored lights don’t render in Maxwell. Maxwell generally doesn’t care about normal direction… except with materials that are emitters! Feel dumb for not figuring it out sooner. I’ve been lighting both sides of boats manually for years like a chump. Hopefully this is a simple fix.
Hi Ryan - for now, see if making a mesh first, (Mesh command on the flipped block instance) checking the resulting mesh’s direction (Dir) and flipping if needed before export is any help.
OK I am making some progress with this script. Some gaps in my knowledge though… Namely digging out the Y dimension from the origin block so I can do math on it and plug it into the destination.
Call ToOtherSide()
Sub ToOtherSide
Dim arrObjects
arrObjects = Rhino.GetObjects("Select blocks to copy across boat", 4096, True, True)
If Not IsArray(arrObjects) Then Exit Sub
Rhino.EnableRedraw True
' For each selected block object
Dim strObject, arrPoint, arrEnd, strCopiedBlock, arrCopiedBlockInsertPoint
For Each strObject In arrObjects
' Get the block's insertion point
arrPoint = Rhino.BlockInstanceInsertPoint(strObject)
'Get the destination//////// HELP
arrEnd = Rhino.GetPoint("to here", arrPoint)
' Copy the object across the boat
strCopiedBlock = Rhino.CopyObject(strObject, arrPoint, arrEnd)
'Find copied object inert point
arrCopiedBlockInsertPoint = Rhino.BlockInstanceInsertPoint(strCopiedBlock)
'Rotate 180 on Z
Rhino.RotateObject strCopiedBlock, arrCopiedBlockInsertPoint, 180
Next
Rhino.EnableRedraw True
Dim strObject, arrPoint, arrEnd, strCopiedBlock, arrCopiedBlockInsertPoint
For Each strObject In arrObjects
’ Get the block’s insertion point
arrPoint = Rhino.BlockInstanceInsertPoint(strObject)
‘Get the destination
arrEnd = arrPoint
arrEnd(1) = arrEnd(1) * -1
’ Copy the object across the boat
strCopiedBlock = Rhino.CopyObject(strObject, arrPoint, arrEnd)
'Find copied object inert point
arrCopiedBlockInsertPoint = Rhino.BlockInstanceInsertPoint(strCopiedBlock)
'Rotate 180 on Z
Rhino.RotateObject strCopiedBlock, arrCopiedBlockInsertPoint, 180
Get two points from the user and with the cplane Z axis define a mirror plane
Find the block instance insertion point’s closest point to the plane. Make a vector from these points and use that to find the target location.
But, I’m not clear on how the rest works or in what axis the blocks are symmetrical (in themselves or just across the mirror plane?) so that you could get there by rotation…
For now, I’d Mesh and then export the flipped mesh…
The idea of doing it that way didn’t actually occur to me until after drawing the sketch.
I was thinking that BlockInstanceXform knows the rotation of the initial block and it would be easy to just invert a sign or something in there and apply the transform to the copied block.
Hi Ryan - if you allow user input for the axis of symmetry (Rhino.GetPoints()), this should not be too bad, work-flow wise, especially if the mirror plane can be a CPlane or World Axis. Got it handled? The target point for rotation is one of the axis points mirrored, so the rotation on the symmetry axis/mirror plane intersection can be figured out.
If I’m understanding what you’re saying… You are suggesting user input of the symmetry of each block to be copied across… Don’t think that will fly. There will be hundreds of light fixtures alone on this boat and like 200 lifeline stanchions alone.
Would something in here be helpful?:
Option Explicit
’Script written by Jarek Bieda
Call ResetBlockZRotation()
Sub ResetBlockZRotation()
'f will be added to the angle result value
' f=0 origin at 9 oclock, f=-90 if origin at 12 oclock, -180 origin at 3 oclock, etc
Dim f : f = 0
Dim d,i,r,v,block
block = Rhino.GetObject("Block Instance ?", 4096,, True)
r = DecomposeXformRotation(Rhino.BlockInstanceXform(block)) 'get rotation in radians
v = Round(r(2) * (-180 / (4 * Atn(1))), 0) + f 'conver into degrees and add 'Vray' factor
'Minus sign at 180 if clockwise
If v < 0 Then
v = v + 360
End If
Rhino.RotateObject block, Rhino.BlockInstanceInsertPoint(block), v, , False
Call Rhino.Print("Block rotation reset to zero")
End Sub
Function DecomposeXformRotation(arrXform)
Dim arrRotate(2)
arrRotate(0) = Rhino.ATan2(-arrXform(2, 1), arrXform(2, 2))
arrRotate(1) = Rhino.ASin(arrXform(2, 0))
arrRotate(2) = Rhino.ATan2(arrXform(1, 0), arrXform(0, 0))
DecomposeXformRotation = arrRotate
End Function
Hrmm I’m getting into the weeds here. I think my vectors for rotation actually need to be along the block’s axes, not the world’s… Is there an easy way to do that?