Notifications
Clear all

[Closed] Pivot z min universal

I need a script that

  1. will make my object/group(even if it was rescaled/rotated) world oriented
  2. put the pivot on z.min (for the lowest object in the group) to the group/object
  3. the object should not change at all- no rotate, no rescaled – only the pivot should move.
  4. when you choose local – then before applying the script, the orientation may be different, but after applying the script, the orientation should be strictly world oriented!
  5. very iportant not to add additional modifiers!
  6. No use of collaps stack.
10 Replies
fn alignPivotToWorld node pos: = if isvalidnode node do
(
	tm = node.transform
	node.transform = matrix3 1
	node.objectoffsetscale = tm.scale
	node.objectoffsetrot = tm.rotation
	node.objectoffsetpos = tm.pos
	
	node.pivot = if pos == unsupplied then tm.pos else pos
	
	node.children.transform *= tm
	tm
)
/*
alignPivotToWorld <group> pos:[.pos.x, .pos.y, .min.z]
*/

Try to create a sphere, scale it and rotate it 45 degrees!


Sphere radius:100 smooth:on segs:32 chop:0 slice:off sliceFrom:0 sliceTo:0 mapcoords:on recenter:off pos:[0,0,0] isSelected:on
scale $ [1.5,1.5,1.5]
rotate $ (angleaxis 45 [1,0,0])

then apply this code. You will see that

  1. it doesn’t give the min.z of the sphere, but the min.z of bbox corner.
  2. If you apply this code again, the the sphere changes it’s size.

It means, the code is still not universal

Now create the same sphere again, rescale and rotate it, and create a box, in addition. Group them and apply the script to the group.

  1. Does not always work for groups
2 Replies
(@denist)
Joined: 11 months ago

Posts: 0

i show the idea. using this idea you can make the solution universal. why the second call of this function doesn’t work right? because after the first call we have ‘offset’ for the object transform. so calling this function next time we have to take new offset into account.

(@denist)
Joined: 11 months ago

Posts: 0

you can calculate mesh bbox… there are several samples on this forum. but you asked about ‘universal’ solution. and not every node has a mesh.

1 But why it doesn’t give the minz of the shpere?
Even after applying the script

selection[1].pivot.z = selection[1].min.z
doesn’t give the min.

  1. how to take the offset into account? What if the object was offset at one computer yesterday, and I apply the script again today at another computer?

Denis, I know that you can help me. I’m not too smart to solve this issue.

How heavy are your objects, so finding the vert with lower Z pos is too slow for you?
For example on object with 240 000 verts the code below finds the vert with lower Z pos for ~0.3 sec on my PC.


(
	function FindLowerZpos obj = if isValidNode obj do
	(
		t0 = timestamp()
		local tempMesh = snapShotAsMesh obj
		local minZpos = [0,0,1e9]
-- 		local minZposVert = undefined
		local vertCnt = tempMesh.numverts
		for v = 1 to vertCnt do
		(
			vertPos = getVert tempMesh v
			if vertPos.z < minZpos.z do
			(
				minZpos = vertPos
			)
		)
		delete tempMesh
		t1 = timestamp()
		format "Time: % sec
" ((t1 - t0)/1000.0)
		point pos:minZpos
	)
	FindLowerZposselection[1]
)

I thought like this. What if we:

  1.   (copy transform, position, scale, rotation, pivot) - I still don't know if needed.
    
  2.   if iskindof node Editable_Mesh or iskindof node Editable_Poly do 
    
  3.           add Edit Poly modifier (to protect the mesh from destroying after ResetXform)  
    
  4.    ResetXForm node
    
  5.    worldAlignPivot node
    
  6.    copy position, orientation, rotation, pivot
    
  7.     if iskindof node Editable_Mesh or iskindof node Editable_Poly do 
    
  8.             remove Edit Poly modifier
    
  9.     remove ResetXForm keeping the objects previous position, transform, rotation and scale
    
  10. keep the object's new orientation and new pivot (from point 6)
    

the code that Neuro69 gave is working great!

tmp=$selection[1].modifiers[1].gizmo.transform
    tmp2=$selection[1].position
    deletemodifier $selection[1] 1
    $selection[1].transform=tmp
    $selection[1].position=tmp2
   

I tried by myself to implement this algorithm but I can’t get it right. Please help me to do it. The most difficult for me now are the last two points.

I think I found a solution! Tell me please, is it possible to find out if an object is world oriented or not?

If yes, then how?

Thank youuu!

2 Replies
(@gazybara)
Joined: 11 months ago

Posts: 0
fn isWorldOriented node = (node.dir as string == z_axis as string)
(@denist)
Joined: 11 months ago

Posts: 0

no! this is wrong.
something like:

node.rotation == quat 1