ZBrushCentral

Question: Need help creating a Batch Render script

Ultimately, I’m trying to setup a batch render script.

I’m having a difficult time understanding how zBrush handles Position, Scale and Rotate data. I want to use the TransformGet and Set commands which use xPos,yPos,zPos,xScale,yScale,zScale,xRotate,yRotate,zRotate.

EXHIBIT A …
[IButton,“mButton”,“myButton”,
[TransformSet,0,0,0,0,0,0,0,0,0]
[IPress,Transform:Fit]
]

…gives this result…

[IButton,“mButton”,“myButton”,
[TransformSet,0,0,0,0,0,0,0,89,0]
[IPress,Transform:Fit]
]

…gives this result …

So far so good, but here is where I get confused …

[IButton,“mButton”,“myButton”,
[TransformSet,0,0,0,0,0,0,0,90,0]
[IPress,Transform:Fit]
]

…gives this result…

…and…

[IButton,“mButton”,“myButton”,
[TransformSet,0,0,0,0,0,0,0,180,0]
[IPress,Transform:Fit]
]

…gives this result…

Question 1: Why does any Y rotational value over 90 flip the model upside down?

EXHIBIT B …
XYZ Position of 0,0,0 puts the model off the canvas somewhere. The command [IPress,Transform:Fit] is the only reason the model was on the canvas in the above examples.

Question 2: Is there a way to get the current position data of a model and see what those values are? Or figure out the values for the center of the canvas?

EXHIBIT C …
So, I’ve set a Front View in Documents:ZAppLink Properties and I’m trying to use this piece of code …
[IPress,Document:ZAppLinkProperties:Front:Front] //this line switches to the Front View saved in Documents:ZAppLink Properties
[IPress,Render:Best]
[IPress,Render:BPR RenderPass:Render Best Preview]
[VarSet,filePath,[GetActiveToolPath]]
[FileNameSetNext,[StrMerge,#filePatch,"_Front.psd"]][IPress,Document:Export]

zBrush doesn’t have any problem switching to the Front view I’ve set up (top line of code). The problem is that none of the code after this command will fire. When I remove that line of code the rest fires without a problem.

Question 3: Why won’t anything fire after switching to the Front view?

Thanks for the help!

Attachments

yRot_0.jpg

yRot_89.jpg

yRot_90.jpg

yRot_180.jpg

  1. You’ve come up against a problem called Gimbal Lock. With what you are trying to do it is relatively easy to solve, by not quite setting to exactly 90/180 degrees at the critical moments:

[IButton,Front,"Show view",
	[TransformGet,xPos,yPos,zPos,xScale,yScale,zScale,xRotate,yRotate,zRotate]
	[TransformSet,xPos,yPos,zPos,xScale,yScale,zScale,0,0,0]			
]

[IButton,Back,"Show view",
	[TransformGet,xPos,yPos,zPos,xScale,yScale,zScale,xRotate,yRotate,zRotate]
	[TransformSet,xPos,yPos,zPos,xScale,yScale,zScale,0,-179.999,180]			
]

[IButton,Right,"Show view",
	[TransformGet,xPos,yPos,zPos,xScale,yScale,zScale,xRotate,yRotate,zRotate]
	[TransformSet,xPos,yPos,zPos,xScale,yScale,zScale,0,90,180]			
]

[IButton,Left,"Show view",
	[TransformGet,xPos,yPos,zPos,xScale,yScale,zScale,xRotate,yRotate,zRotate]
	[TransformSet,xPos,yPos,zPos,xScale,yScale,zScale,0,-90,180]			
]

[IButton,Top,"Show view",
	[TransformGet,xPos,yPos,zPos,xScale,yScale,zScale,xRotate,yRotate,zRotate]
	[TransformSet,xPos,yPos,zPos,xScale,yScale,zScale,-89.999,0,0]			
]

[IButton,Bottom,"Show view",
	[TransformGet,xPos,yPos,zPos,xScale,yScale,zScale,xRotate,yRotate,zRotate]
	[TransformSet,xPos,yPos,zPos,xScale,yScale,zScale,-89.999,180,180]			
]
  1. You can get the position of the model using TransformGet, just as I have done in the code above. (You need to draw the model on the canvas but after that it will stay at the same size and position.) To examine a value you can use a note:

[Note, xPos]

The X,Y,Z position 0,0,0 is the top left corner of the canvas (Z depth of 0). But with your code you won’t see anything because you are setting the XYZ scale values to zero. You can use pixels to set the position, so the center of the canvas can be set by using xPos = ([IGet,Document:Width]/2) and yPos = ([IGet, Document:Height]/2).

  1. Your code will not run because ZAppLink is actually a plugin and only one plugin can be active at a time. What happens is that the moment your code presses the ZAppLinkProperties ‘Front’ button, control passes to ZAppLink and your plugin is unloaded. Therefore the rest of your code is ignored.

HTH,

Very helpful. Thank you. That all makes sense.

Since I can’t tap into the ZAppLink plugin, how do I create a button that functions the same way as the Front, Back, Left, Right, etc buttons? I’d like to have a button that stores transform info and recalls it later when the button is clicked. So, 1st click stores transform data … any click after that recalls the stored info.

I assume I need to use TransformGet and store the info in Memory. Then use TransformSet to recall the transform info. I just don’t understand how to put it all together.

Seems simple. But it wouldn’t surprise me if this is more complex than I realize.

Thanks.

The simplest way of doing what you want would be to use the TimeLine. Your script could load and show a pre-made TimeLine with different positions laid out. The user would Ctrl+Shift+click on a dot if they wanted to adjust a position. Your script could then run through the frames (by pressing the TimeLine>Go Next or Go previous buttons) exporting the renders.

Alternatively, if you wanted to have buttons like ZAppLink this is not too difficult. One way is to use a list variable for the transform values. For example:


[VarDef,myList(10),0]//declares a list with ten elements

//when the button is pressed:
[If, myList(0) == 0, //the first element is used to check if we have stored the values or not
   [VarSet,myList(0),1]// we are storing values so our 'check' is set to one
   //now get the current transform values into the list
   [TransformGet,myList(1),myList(2),myList(3),myList(4),myList(5),myList(6),myList(7),myList(8),myList(9)]
,//else we have stored values so we need to set the new position
   [TransformSet,myList(1),myList(2),myList(3),myList(4),myList(5),myList(6),myList(7),myList(8),myList(9)]
]

All that is necessary to replace the values is to set myList(0) to zero, then next time the button is pressed new values will be stored.

You can store more values for other buttons simply by having a longer list. And the list can be saved to or loaded from disk by using the [VarSave] and [VarLoad] commands. There’s an example of that here:
http://www.pixologic.com/docs/index.php/ZScript_Example:_Tutorial_Window_interface

Thanks so much! I modified it slightly to suit my needs and it’s working great.

Hopefully, just one more quesiton …

I’m trying to recreate a button that behaves like ZAppLink’s Clear To button. I figured out how to create a Clear All button. Struggling with the Clear To button. I’ve tried several things but I’ve hit a wall. I feel like I’m chasing my tail.

Basically, after clicking the Clear To button, clear the data from the “View” button I click. How do I do this?

Any ideas would be helpful. Thanks!

The ‘Clear To’ switch is just an indicator of the user’s intention, it doesn’t need any code of its own. Then each button checks to see if the ‘Clear To’ switch is ON or OFF before running the appropriate code. All that’s needed is another [If] statement wrapped around the previous code:


[VarDef,myList(20),0]//declares a list with twenty elements


[ISubPalette,"ZPlugin:My Plugin"]


[IButton,"ZPlugin:My Plugin:Front","Use front transform",
	[If,[IGet,"ZPlugin:My Plugin:Clear To"]==1,//if 'Clear To' switch is ON
		[VarSet,myList(0),0]
		[IUnPress,"ZPlugin:My Plugin:Clear To"]//turn off the switch
	,//else the 'Clear To' switch is OFF
		[If, myList(0) == 0, //the first element is used to check if we have stored the values or not
   	[VarSet,myList(0),1]// we are storing values so our 'check' is set to one
   	//now get the current transform values into the list
   	[TransformGet,myList(1),myList(2),myList(3),myList(4),myList(5),myList(6),myList(7),myList(8),myList(9)]
		,//else we have stored values so we need to set the new position
   	[TransformSet,myList(1),myList(2),myList(3),myList(4),myList(5),myList(6),myList(7),myList(8),myList(9)]
		]
	]	
,,.25]// button is quarter palette width


[IButton,"ZPlugin:My Plugin:Back","Use front transform",
	[If,[IGet,"ZPlugin:My Plugin:Clear To"]==1,//if 'Clear To' switch is ON
		[VarSet,myList(10),0]
		[IUnPress,"ZPlugin:My Plugin:Clear To"]//turn off the switch
	,//else the 'Clear To' switch is OFF
		[If, myList(10) == 0, //the first element is used to check if we have stored the values or not
   	[VarSet,myList(10),1]// we are storing values so our 'check' is set to one
   	//now get the current transform values into the list
   	[TransformGet,myList(11),myList(12),myList(13),myList(14),myList(15),myList(16),myList(17),myList(18),myList(19)]
		,//else we have stored values so we need to set the new position
   	[TransformSet,myList(11),myList(12),myList(13),myList(14),myList(15),myList(16),myList(17),myList(18),myList(19)]
		]
	]	
,,.25]// button is quarter palette width



[ISwitch,"ZPlugin:My Plugin:Clear To",0,"Press then click button above to clear its transform"
,,,,0.5]//switch is half palette width and turned off by default


//switches need to be enabled in plugins
[IEnable,"ZPlugin:My Plugin:Clear To"]

I had an additional question concerning the discussion above but I decided it should go in it’s own post. I moved it to the link below.
http://www.zbrushcentral.com/showthread.php?171426-Question-4k-render-problem-can-t-render-close-up-Why