ZBrushCentral

Orienting View based on Transpose Action Line

Hi I am trying to write a script that orients the tool to look directly down the Transpose action line.

7040b4a7a1c6a5bdab8eeb0c2075fa54.png I’d like to place the transpose as usual.

703918fb6441e8b4ed803bf3514dab38.png Then run script and have the view aligned to be looking down the transpose action line.

I’ve tried to get the start and end positions of the Transpose line and calculate the angle to then rotate the view but I am failing. Is there a better way to achieve this?

Thanks for any assistance!

What I have been doing - and feel would be useful to automate - is manually aligning the transpose line to camera - you can see Zbrush is aware when the alignment occurs. When the alignment is where I want I store the view for later using Zapplink - this helps when using clip curve and other tools, especially for hard surface.

ccce7fcb440e3093389c4b9fbf65e649.png

The script I was trying to slap together would behave like this:

Get location of start of transpose line (t0)
Get location of end of transpose line (t1)
calculate angle between t0 and t1
rotate according to this result to look down the angle
store view in zapplink

I’ll keep trying, any suggestions would be appreciated!

Ok getting closer I am getting the normal angle of the pixol under the mouse cursor
Facing the camera returns 0,0,-1
eacb70392f1ca34aef8bc804031f8897.png

When the pixol is not facing camera:
0b8d47108bca22a55d72bdf36c85b360.png

[IButton,???,“Align View to Plane”,

[VarSet,xNorm,0]
[VarSet,yNorm,0]
[VarSet,zNorm,0]

[VarSet,z,[PixolPick,1,[MouseHPos],[MouseVPos]]]
[If,z < 2800,

[VarSet,xNorm,[PixolPick,6,[MouseHPos],[MouseVPos]]]
[VarSet,yNorm,[PixolPick,7,[MouseHPos],[MouseVPos]]]
[VarSet,zNorm,[PixolPick,8,[MouseHPos],[MouseVPos]]]

]

[Note,[StrMerge,xNorm," : “,yNorm,” : ",zNorm]
]
]

So now I think I just need to TransformSet and rotate against the PixolPick values until they equal 0,0,-1

Any help finishing this would be great thanks.

eebf3c5a77a997cce5d1a3e680af58d0.png

I figured I only have to solve for x,y rotation to get what I want.

When getting the normal info of a pixol under the cursor the ranges are x(-1 to 1) and y(-1 to 1)

066da46c18a240e206df89d978d0a27d.png

I can orient the values to 0,0,0 - The pixol is looking straight down the camera, and the camera is zeroed.

60c102781f4773f2b078d526900e2fe6.png

The value ranges for xRot is -90 to 90
Range for yRot is -90 to 180 (a little confusing as to why)

Order of events I am planning so far:

//Define Variables
//Get Pixol normal info of x,y values “Px,Py”
//Get current camera rotation of x,y “Xrot,Yrot”
//Check <> for values to determine direction of rotation (add to or subtract from X,Yrot)
//Convert Px and Py to rotation friendly values
//Based on check results either add or subtract from the current rotation values.

Result: View rotates X and Y to align the view to the sampled normal.

Any help would be great - I’m learning as I go thanks!97cc4c75eb12b26374489ab39dc30828.png

a877d27f6681911fd6f1f6947fd9d5b0.png

pixols=px,py
rotation=cx,xy

so like… check
if py<0 rotate -cx
else rotate cx
if px<0 rotate cy
else rotate -cy

??? <__<

2468f96bab148b76d0aaa22af91969eb.png

Result:
8da1d55b63dffe159e058eca8de97d5f.png7593171fddf1524e23b4e52270fdac7e.png51b24d89b75fb605d65a0d9ed872645e.png

I’m looking into this for you but haven’t finished investigating. Should be able to post something tomorrow.

0_0 thanks Marcus save me from myself.

92fda34ceaafc2aeeca5e94404683b11.gif

This is as close as I got so far - bound to numpad 0. Can’t seem to get the alignment right.

[IButton,???,“Align View to Plane”,

[VarSet,xNorm,0]
[VarSet,yNorm,0]
[TransformGet, xPos, yPos, zPos, xSc, ySc, zSc, xRot, yRot, zRot]

[VarSet,z,[PixolPick,1,[MouseHPos],[MouseVPos]]]
[If,z < 2800,

[VarSet,xNorm,[PixolPick,6,[MouseHPos],[MouseVPos]]]
[VarSet,yNorm,[PixolPick,7,[MouseHPos],[MouseVPos]]]

]

[If,xNorm < 0,
[TransformSet, , , , , , , , ((yRot)+(xNorm90)), zRot]
,
[TransformSet, , , , , , , , ((yRot)-(xNorm
90)), zRot]

]

[If,yNorm < 0,
[TransformSet, , , , , , , ((xRot)-(yNorm90)), , zRot]
,
[TransformSet, , , , , , , ((xRot)+(yNorm
90)), , zRot]

]

]

This is a bit of a hack but will perhaps give you some ideas. It uses your original idea of the Transpose line to get the face you want pointed at the screen plane. The rotation is done using a simulated click+drag on the background. This is simpler than trying to cope with the rather awkward rotation system available for scripting!

This is far from perfect, and I’ve probably missed something critical, but hopefully it will help.

AlignToPlane.txt (1.59 KB)AlignToPlane.txt (1.59 KB)

Thanks Marcus I really like this approach. I will test it out and see if I can come up with anything else!

07956a5fe6f462f9bc7b88b70092f0fa.gif

The script you wrote is working great and I will continue to study it so thanks again! But I was wondering about the approach below:

Looking at your script I had the idea to try canvasclick.

Did some testing and found 0 to 100 of canvasclick was pretty damn close to a 90 degree rotation.

So I moved the decimal of the -1 to 1 return values of the Pixol Normal and input that as canvasclick drag.

Seems to work?! Not sure if it’s a viable approach :slight_smile: only have it working on one axis now but maybe you can help me hook it up better?

Here’s my junky script so far:

[IButton,???,“Angle Snap”,
//Get Pixol Info Location and Normal (X -1 to 1 and Y -1 to 1)

[VarSet,z,[PixolPick,1,[MouseHPos],[MouseVPos]]]
[If,z < 2800,

[VarSet,xNorm,[PixolPick,6,[MouseHPos],[MouseVPos]]]
[VarSet,yNorm,[PixolPick,7,[MouseHPos],[MouseVPos]]]

]

//Canvas Drag to Rotate X,Y based on Normal Info

[CanvasClick, (Document:Width*.02), (Document:Width*.02), ((Document:Width*.02)+(xNorm100)), ((Document:Width.02)-(yNorm*100)) ]

]

Sorry, I am late to this thread. I was experimenting with this idea a year ago and I actually got something very similar to what Marcus did but this was my approach…

Method 1.
Orienting the view to the face normal using PixolPick

[VarSet,DocWiCent,(Document:Width*.5)]//Find center of the document
[VarSet,DocHeCent,(Document:Height*.5)]//

[VarSet,Horz,[MouseHPos]]
[VarSet,Vert,[MouseVPos]]
[VarSet,Ux,[PixolPick,6,Horz,Vert]]
[VarSet,Uy,[PixolPick,7,Horz,Vert]]
[VarSet,Uz,[PixolPick,8,Horz,Vert]]
[VarSet, TT, ACOS(Uy)]// Find the vertical angle
[VarSet,PP, ATAN2(Uz,Ux)]//Find horizontal angle

[VarSet,RotVer,(TT-90)*2.7777] //vertical angle to pixols length
[VarSet,RotHor,(PP+90)*1.1111] // Horizontal angle to pixol length
[TransformGet, XXX,YYY]
[IFreeze,
//[IPress,Transform:Move]
[CanvasClick,#Horz,#Vert]

[If, Horz>XXX, [VarSet,SUMX, XXX-(Horz-DocWiCent)], [VarSet,SUMX,XXX +(DocWiCent-Horz)]]
[If, Vert>YYY, [VarSet,SUMY, YYY-(Vert-DocHeCent)], [VarSet,SUMY,YYY +(DocHeCent-Vert)]]

[TransformSet, SUMX,SUMY]
]
[IClick,1004,-15,DocHeCent,-15-RotHor,DocHeCent+RotVer] // Drag click to make rotation

Method 2.
Orienting the View Based on the current Transpose line direction OR if using a hotkey it will create one (normal to the surface) when pressing the hotkey over a mesh.

Here I use a tool called reference.ztl that is a simple small low poly sphere. This is not a requirement but it’s there to make sure the transpose line (That it will look just 3 concentric circles ) falls exactly in the center of the document.

[IFreeze,
[VarSet,BaseToolID,[ToolGetActiveIndex]]

[If,[IExists,Tool:Reference],
,//Else
[FileNameSetNext,“Reference.ztl”] [IPress,Tool:Load Tool] ]
[VarSet,DocWiCent,(Document:Width*.5)]//Find center of the document
[VarSet,DocHeCent,(Document:Height*.5)]//

[VarSet, HorO,[MouseHPos]] // Find Mouse Position
[VarSet, VerO,[MouseVPos]]//

[IPress,Transform:Scale]// select the Move mode
[CanvasClick,HorO,VerO]// click to create Transpose line
[IPress,Transform: Draw Pointer]

[TransposeGet, INIx, INIy, INIz, FINIx, FINIy, FINIz, LGT] // Find positions and length of transpose Line
[TransformGet,NxxD,NyyD,NzzD,SCori]

[VarSet,Ux, INIx-FINIx/LGT]// Find the Unit vectors
[VarSet,Uy, INIy-FINIy/LGT]//
[VarSet,Uz, INIz-FINIz/LGT]//

[VarSet, T, ACOS(Uy)]// Find the vertical angle
[VarSet,P, ATAN2(Uz,Ux)]
[If,(T==180) || (T==0),[VarSet,P,90],]
[VarSet,Yangle, 90-P] //Adjust this angle to the Zbrush convention

[If, (Yangle>=90) || (Yangle<=-90),[VarSet,condito,-180],[VarSet,condito,0]]
[TransformSet, 10, 10, 10,0,Yangle,condito] // make the horizontal rotation
[VarSet,RotVer,(T-90)*2.7777] //vertical angle to pixols lenght
[IClick,1004,-15,DocHeCent,-15,DocHeCent-RotVer] // Vertical rotation …rotate this way can cause troubles if there is a mesh at that position and there is no margin

[IPress, Tool:Reference]

[ISet,Tool:Geometry:X Position,INIx]// move the subtool
[ISet,Tool:Geometry:Y Position,INIy]
[ISet,Tool:Geometry:Z Position,INIz]

[IPress,Transform:Fit] //Fit in view
[TransformGet,NxxD,NyyD,NzzD,SCx]
[TransformSet,DocWiCent+((NxxD-DocWiCent)*SCori/SCx),DocHeCent+((NyyD-DocHeCent)*SCori/SCx),0,SCori,SCori,SCori]
[ToolSelect,BaseToolID]

]// Close Freeze

Good stuff, dargelos, many thanks for posting. :+1: I shall take a close look and hopefully improve my math! :wink:

5bf87686e2e3b67eb833c2e736a5877a.png

dargelos thanks for posting! These are great to study and I will be using method 1 for my hard surface stuff I think it will be very useful.

I’m sure others will find these useful as well.

Thanks for responding and solving this for me guys. My brain was overheating.

I made a little plugin and included the code in the txt file.
I hope this can be useful for others.

I included a button to control the camera angles and zoom with sliders. This uses the same trick as Marcus Civis suggested so we don’t really have to cope too much with the TransformSet Angles. It would be ideal to totally understand TransformSet since we could then include the 3rd camera rotation axis. Anyway this can be set manually with the transpose line white little circle and CTRL.

Cc.jpg
CamControl.zip (16.2 KB)CamControl.zip (16.2 KB)

1 Like

Very cool, thanks for including the code to learn from also!

Teriyaki, I think you were close. Rotations can be tricky…
I am not going to talk much about trigonometry, I am not a mathematician, but I think this problem can be understood without using very advanced maths.

It helped me a lot to think of a sphere of R=1.
With Pixolpick you get the x,y,z components of a vector that you can imagine as the radius of the unit sphere in that particular orientation. That vector can also be defined by two angles, T and P.
Let’s say T is the vertical angle, this angle is defined by the value of the y component of your unit vector so T=ACOS(Uy).
Then the P angle depends of the values in the X and Z axis. P=ATAN2(Ux,Uz) … atan2 takes care of all the different cases like when Uz is equal to 0, so we don’t have to worry about it…
These two angles can also be called spherical coordinates and rotating the camera by those angles should do the trick.
Now we have to convert the angles to the equivalent distance (in pixels) to simulate a drag click that moves our camera the exact amount.

For the vertical rotation I found 1 degree is equal to 2.777777 pixels while the horizontal rotation 1 degree is equal to 1.111111 . This means we need to move our pen more pixels to rotate vertically, that’s actually a very cool idea from the pixo guys because very often we just want to rotate our models horizontally to get a good 3D feeling (at least this is why I think they didn’t use the same number)
This method should obviously have a rounding error because pixels are integers but I think it’s not very noticeable

Thanks for the explanations - I will work to understand this :slight_smile:

I am looking for the same function. Thank you for the CamControl plugin. It works almost perfectly. But as you mentioned, it is not exactly normal, causing irregular surfaces when a surface is repositioned and using the Trim-Front brush for example.

Do you know if an exact AlignCameraTosurfaceNormal feature has been added to zbrush2018? Or have another suggestion?

Thank you