Special
thanks to Fred Moreau for for his great script: Max Freehand Tools. Grass
and Stone ink was a plugin brush to MFHT. When 3ds max 5 comes out with
the Painter interface, I started to hack the codes to make it compatible
with Painter Interface.
A.
Introduction
Advanced
Painter is a modular object distribution tool with brush based interface.
The script comes with 5 inks (in alphabetical order, not usefulness):
Grass:
to create simple grasses.
Hair: used to create simple hair/fur (or
as guide hair for Shag:Hair).
Randomizer, a variation of Scatterer used to randomly
distribute a selection of objects.
Stone: to create simple stones and peebles.
Spaghetti: spaghetties, noodles, wires and other long
things maker.
Scatterer: a generic but powerful object scattering
tool.
Toothpaste:
the fun but not-so-useful toothpaste generator.
3rd
Party scripters can take advantage of this system as Advanced Painter's
modularity allows scripters to focus on the main UI and core functions,
rather than basic things like creating paint button, storing parameters,
etc. Refer to the history section for Advanced Painter's commands reference.
The mzp package also installs an example ink and a template ink which
helps you to write a new Ink Defintion. They can be found in [maxroot]\scripts\AdvPainter\
folder.
Advnaced
Painter 1.5 replaces Nature Painter 1.2. Check the history section for
more details on the recent changes.
B.
Installation
1)
Extract advPainter_1.6.0.mzp
2) Start
Max. MaxScript>Run Script ... and choose the extraced file. A dialog
box will inform you that installation is successful.
3) Install
Advanced Painter action item (found under 'Painter' category) to your
toolbar, main menu bar, or quadmenu. Please refer your 3ds max documentation
for more information on action item installation.
NOTE:
Advanced Painter 1.6.0 requires 3ds max 9 - 2009.
Uninstalling
Advanced Painter: During setup, the the following files are copied.
If you wish to uninstall Advanced Painter just delete them yourself.
[maxroot]\stdplugs\stdscripts\Functions_AdvPainter.ms
[maxroot]\UI\macroscripts\Macro_AdvPainter.mcr
[maxroot]\scripts\AdvPainter\Ink_Grass.ms
[maxroot]\scripts\AdvPainter\Ink_Hair.ms
[maxroot]\scripts\AdvPainter\Ink_Randomizer.ms
[maxroot]\scripts\AdvPainter\Ink_Scatterer.ms
[maxroot]\scripts\AdvPainter\Ink_Spaghetti.ms
[maxroot]\scripts\AdvPainter\Ink_Stone.ms
[maxroot]\scripts\AdvPainter\Ink_Toothpaste.ms
[maxroot]\scripts\AdvPainter\Ink_Example.txt
[maxroot]\scripts\AdvPainter\Ink_Template.txt
[maxroot]\scripts\AdvPainter\scatterer_i.bmp
[maxroot]\scripts\AdvPainter\scatterer_a.bmp
C.
Reference
0)
Main UI
Inks
Drop Down List
Lists all available inks
Paint
Starts/ends the paint session.
Menu
Button
Pops Advanced Painter's Menu
Advanced
Painter Menu
Brush Settings: Opens Painter Interface's Options
dialog
Only Paint on Selection: When active, Advanced uses
the current selection as canvas. When inactive Advanced Painter uses
its own nodelist as canvas. You add objects to Advanced Painter's
nodelist by using Make Selection Paintable command.
Make
Selection Paintable: Sets the current selection as paintable
by adding them to Advanced Painter's nodelist
Reset
Nodelist: Resets Advanced Painter's nodelist array.
Help:
Opens this manual.
1)
Grass Ink
Number
of Strands
specifies the number of stands on each plant.
Base
Radius
the radius of each strand.
Base
Segments
number of sides of each strand.
Min/Max
Height
during strand creation the script produces a random number to specify
strand's height. The random number is between the Minimum and Maximum
Height values.
Height
Segments
number of segments along each strand's height. Generally you will need
higher value if you specify high bending angle.
Orientation
Start/End
Similar to the Maximum/Minimum Height spinner, Orientation Start and
End specifies the range of random orientation.
Min/Max
Bend
Similar to the Maximum/Minimum Height spinner, Minimum/Maximum Bend
specifies the range of each strand's bending.
Custom
Material (default: off)
When this checkbox is on the material specified on the material button
is assigned to every grass strands.
Reverse
Direction (default: off)
When this checkbox is on each grass strands are placed in reversed direction
Strand
Direction (default: Normal)
Specifies the up direction of each grass strands. Normal places each
strands in the same direction as the surface normal, while the rest
places each strands along in the same direction as the specified axis
2)
Scatterer
- object scattering tool
Source
Object List [new]
This list contains objects that has been added to source list. Unchecking
the checkboxes will skips the specified object from being cloned. This
is a useful when you have several objects to scatter. Instead of picking
new object when you need to change the source object, you can simply
add all objects to the source list, and unchecking objects that you
dont want to be cloned.
TIP:
It is very importat to set up every source object's pivot position and
orientation before painting. Scatterer always orient clone's local z
axis parallel to the current surface normal (or world x or y or z axis,
depends on your setting). Another important issue is sometimes you need
to scatter several objects with specific position relative to each other
(ie.: you have a butterfly which consists of the body, the left wing
and the right wing). Scatterer will ignore their configuration as it
only regards source object's pivot position. You will have to align
each pivot to a common position and direction.
Pick button
[new]
Pick object from the scene to be added to the source list
Add Sel button
[new]
Add selected object to the source list
Remove button
[new]
Remove selected object in the list.
Clear button
[new]
Clears the source list.
Up/Down button
[new]
Moves selected object in the list up or down to change its index. This
is used when you are using the new npScatterSrcIdx variable
in your PostClone script as the index become important.
Align Up-Direction
Specifies the up direction of each clones. When Reverse is
active the direction is reversed.
Align
to Stroke
Specifies whether each clone is aligned to stroke direction. When Reverse
is active the direction is reversed.
Minimum Distance
Specifies how distant each sequentially generated clones. Value of 10.0
means every clone is at least 10.0 units away.
Min/Max Offset (X,
Y, and Z ) [new]
Specifies the range for the random offsets on each axis.
Min/Max Orientation (X,
Y, and Z)
During cloning process this ink calculates 3 random numbers to specify
cloned object's orientation on X, Y and Z axis. The random number is
in the range of the Minimum and Maximum Orientation values.
PostClone Script
This checkbutton toggles the PostClone feature. Check the tutorial in
the following section for more information on PostClone feature.
3)
Spaghetti
Radius
Specifies the radius of the spaghetti
Color
specifies the color of the spaghetti
4)
Stone Ink
- instant
stones
Min/Max
Size
during stone creation the script produces a random number to specify
stone's radius. The random number is in the range of the Minimum and
Maximum Size values.
Segments
specifies number of segments for each stones.
Noise
Strength Low/High
Similar to the Maximum/Minimum Size spinner, Noise Strength Low/High
specifies therange of random turbulence for each stone.
Separation
ratio
Specifies
how distant each sequentially generated stones. Value of 1.2 means each
stones are 1.2 stones away. Higher value produces rare distribution.
Material
(default: off)
When this checkbox is on, the material specified on the material button
is assigned to every stones.
5)
Toothpaste
- toothpaste like geometry
Radius
Specifies the radius of the paste
Minimal Distance
Specifies how distant each cross section are apart. Smaller result yields
a more detailed shape.
NOTE: For best result, it is recomended to turn on 'Remove Interior
Patches' in the Surface modifier's settings, and switch interpolation
setting in Cross Section modifier to smooth. These options are not exposed
to maxscript, so I cannot make it automatic.
6)
Hair
- simple hair/fur generator.
This
is simply a script to try ideas and I wont be a replacement to real
hair/fur plug in (unless you have access to PRMan or maybe mental ray
or other renderer with curve primitive then you can write a script to
convert the splines to curve primitive). However this script is quite
handy to create guide hairs for shag hair. If you used my script called
HairStylist's Tools, you will find this ink far more advanced as it
adds wavyness, bending and droopyness parameters.
Segments
The number of segments of each hair. Try to set this value to optimum
value as high value often produces the exact same result as smaller
value, but consumes more memory. Generally you will want to set this
value to around 3-5 if you hair is not wavy. For wavy hairs it depends
largely to its frequency and amplitude.
Thickness
Hair Thickness
Length
Min/Max
Specifies the range of each hair's length
Align
to X/Y
Tells the ink to align each hair's to either X or Y axis.
Bias
Specifies the how hair's thickness will vay along its length. Smaller
bias value makes you hair looks thinner while higher bias makes you
hair looks more solid and thicker.
Base/Tip
Color
Bass and Tip color
Edit
Opens the material editor and puts the current hair material in slot
1.
Create
New
Create a new hair material. This is used when you want to change hair
shading for future hairs but you dont want previously created hairs
to be affected.
Amplitude
Specifies the amplitude of the wavy effect
Frequency
Specifies how wavy each hair is. Higher value makes your hair looks
more wavy.
Bending
Min/Max
Specifes the range of bending angle of each hair.
Droopyness
Min/Max
Specifies how heavy each hair is. Value of 0 means your hair is very
light and not affected by gravity . Value of 1 means you hair is very
heavy.
7)
Randomizer
- this is the variant of Scatterer ink.
Randomizer
has identical ui as Scatterer.
D.
Tutorial
Scatterer
Basics
In this part we will cover the basic operation of Nature Painter's Scatterer
Ink.
1)
Open the tutorial file: Nature Painter_ScatterTut01.max.
The Scene contains a teapot and a plane with a fern material assigned.
If you examine the plane, you can see the pivot has been moved and rotated
so the local z axis is parallel to plane's length. When using the Scatterer
Ink it is very important to orient object's local z axis to proper direction
beforehand. Also, a Bend modifer has been added to the Plane01.
2)
Start Advanced Painter, and from the Inks drop down list, switch to
Scatterer ink.
3)
Press the Pick button and pick Plane01 or alternatively select
Teapot01 and press Add Sel. Leave the rest to default.
4)
Select Teapot01 and press the Paint button. Start stroking your cursor
on the Teapot. You can see that instances of the plane object placed
along your brush stroke.
Now
we are going to make the object distribution denser.
5)
Set the Minimum Distance spinner to around 1.0 and start stroking
again. Plane01 instances are tightly placed along your brush stroke.
::Minimum
Distance specifies how distant each sequentially generated clones.
To
add some randomness, we are going to play with Min/Max Orientation values.
6) Delete Plane01 clones
or just press Undo. Set Minimal Orientation Z to -100 and Maximum
Orientation Z to 100. Start stroking again. Now, Plane01 clones
are scattered on the teapot with random orientation.
::
Min/Max Orientation specifies the range of random rotation
that will be applied during stroking.
While
the Min/Max Orientation is designed to create randomness, it is also
useful to orient clone to specific direction during stroking.
7) Set Min/Max Orientation
to -80 and -100 and start stroking on the teapot. As a result, the clones
are now scattered with different orientation.
Scatterer and PostClone Script
The PostClone Script feature lets you perform any maxscript operation
after cloning. This gives you unlimited freedom and makes the Scatterer
Ink a very powerful tool.
1)
Open the tutorial file: Nature Painter_ScatterTut01.max.
The Scene contains a teapot and a plane with a fern material assigned.
If you examine the plane, you can see the pivot has been moved and rotated
so the local z axis is parallel to plane's length. When using the Scatterer
Ink it is very important to orient object's local x axis to proper direction
beforehand. Also, a Bend modifier has been added to the Plane01.
2)
Start NaturePainter, and from the Inks drop down list, switch to Scatterer
ink.
3)
Press the Pick button and pick Plane01 or alternatively select
Teapot01 and press Add Sel. Set Minimal Orientation Z
to -90 and Maximum Orientation Zn to 90. Leave the rest to
default.
4)
Activate the PostClone feature by checking its checkbox.
5)
Type in the following command:
npScatterObj.bend.angle = random 40 120
Switch
Cloning Method to 'Copy' and start Stroking on the
teapot. Plane01 clones are scattered along the stroke and assigned with
random Bend angle.
During
each cloning process, the clone are referenced to a global variable
called npScatterObj. Using this variable you can do
anything via simple scripting. The above script generates a random number
between 40 and 120 and then assigns it to the angle parameter of the
Bend modifier.
Remember
that when using PostClone Script, it would be useless if you dont set
Cloning Method to Copy.
6)
Hide the Teapot, create a moderately sized Plane and Set Min/Max
Orientation to 0.0. Replace the PostClone Script with the following
commands:
ang
= abs((sin(npScatterObjIdx*10))*2)+0.3; scale npScatterObj
[1, 1, ang]
7)
Select the new plane and start stroking. You can see that now the clones
are distributed evenly with sinual scaling along the z axis. This script
utilizes the npScatterObjIdx variable which is actually
the index of the current clone.
::
The PostClone field is not multiline. If your script getting too long
you can put them in a separate function and put the function's command
into the PostClone field.
:: If there is any error on your script the paint mode will be stopped.
8)
Try this script: _npos= 10*sin(npScatterObjIdx*20);
move npScatterObj [0, _npos, 0]
:: npScatterObj : current clone
:: npScatterObjIdx : current clone's index
:: npScatterSrcIdx [new] : specifies
the source object in the source list which is being cloned. This is
useful if you have more than one object in the source list and you want
a uniqe script for each source.
Scattering
Multiple Objects
In
this part we will cover the new feature in Scatterer 1.5.1 which allows
you to scatter several objects at the same time.
1) Open NaturePainter_ScatterTut02.max.
Examine the scane, we have a plane, a blue butterfly and a purple butterfly.
Each butterfly consists of the body and the wings.
2) Open
Advanced Painter and switch to Scatterer ink. Marquee select the blue
butterfly and press Add Sel button. The source listbox should
list blue butterfly's components: the body and wings.
3) Select the plane, press
Paint and start painting on the plane. The butterfly is scattered
along the stroke but not properly placed. This is because each object's
pivot is not positioned and oriented properly. If you select the blue
butterfly and check its components' pivot (you can do this via the Hierarchy
Panel) you can see that both wings' pivot are centered to itself and
their z axis are facing to different directions. It is very important
to place to place and orient object pivot before painting.
4) Select the purple butterfly
and examine its component's pivot. Notice how each wings has its pivot
aligned to the body and the z axis points upwards. This butterfly has
been set up to work properly with Scatterer.
5) We are going to replace
the blue butterfly with purple butterfly from the source list. Marquee
select the purple butterfly and press Add Sel. The purple butterfly
components should be listed in the source list (as well as the blue
butterfly's components). Since we dont want the blue butterfly to be
scattered, uncheck blue butterfly's components off the list. Now press
Paint and start painting on the Plane. The butterfly should be properly
placed and oriented, but we need to align them to stroke direction.
Set Align to Stroke to Y and Min Distance to 20.0.
Start painting again to see the result.
6) Butterflies doesnt
walk on the ground, we have to make them float in the air and add a
bit of randomness. To do this set Min Offset Z to 40; Max
Offset Z to 80; Min Orientation Z to -30 and Max Orientation
Z to 30. Start painting on the Plane.
You
should have the butterflies flying on the air and faces to a slightly
random direction.
7)
We are going to use PostClone Script to vary each butterfly's wings
orientaion. Make sure the purple butterfly's body is the fourth object
in the list. If it is not use the up and down button to set the index.
Then, enable PostClone script and use the following command:
if (npScatterSrcIdx
== 5) or (npScatterSrcIdx == 6) then in coordsys local rotate npScatterObj
(eulerangles 0 (random -20 20) 0)
The
script basically adds a random orientation to each wings. Since we have
multiple objects we used npScatterSrcIdx variable
to check wheter the currenttly scattered object is a wing. npScatterSrcIdx
reflects the index shown in the source list.
E.
History
Advanced
Painter 1.5.1
- The
Scatterer Ink now supports multiple sources. This new feature also introduces
several new things: npScatterSrcIdx
variable for PostClone Script: this new global variable holds
the index of the currently cloned object; source object listview;
pick button; add selection button,
remove button; clear button; and move
up/down buttons.
- New
offset values in the scatterer ink. Originally you can do this via PostClone
script, but due to the introduction multiple source feature, PostClone
Script become impractical for this basic effect.
- Added
the Hair ink. This is a very simple hair maker and probably not very
useful for production when used directly. However you can use this to
generate guide hair for Shag Hair.
- Added
the Randomizer Ink as requested by Yiannis Koumoutzelis. This ink is
a quick hack of the Scatterer ink which instead scatters every object
in the list, it randomly picks an object in the list. The rest is identical
to Scatterer.
- Few
bug fixes.
Advanced
Painter 1.5
- Converted
Nature Painter 1.5 into a modular system where each ink is simply a
plugin (called inkDef) to the system. This allows simpler ink creation
and management. 3rd party scripter can take advantage of this new system
as they can concentrate more on the core code than the UI. Please note
that all ink defintion should be locaed in [maxroot]\scripts\AdvPainter
folder.
- Added
several functions to AdvPainter functions library (there are more functions,
but I only listed functions that are useful for 3rd party scripter)
:
<void>advPainter.open() -- opens the
Advanced Painter Panel
<void>advPainter.register <inkDef>thisInk
-- registers thisInk to AdvPainter_inks array
<void>advPainter.unregister <inkDef>thisInk
-- unregister thisInk from AdvPainter_inks array
<void>advPainter.switch <inkDef>thisInk
-- switch to thisInk and update the panel.
<void>advPainter.startPaint() -- starts
the paint session and perform the neccessary setup beforehand.
<void>advPainter.error [<string>msg]
-- stops the paint mode, restore the undo buffer, then pops a generic
message in Advanced Painter Panel's status area. If msg is
specified the content of msg will be used instead.
<void>advPainter.popmsg <string>msg
-- pops the specified msg to Advanced Painter status area.
<void>advPainter.evaluateInks -- evaluates
all ink definition in [maxroot]\scripts\AdvPainter folder. Normally
this should only done once during startup.
Also, there are several useful global variables:
advPainter_inks : array containing registered inks
advPainter_currentInk : current inkDef as listed in
the Advanced Painter panel.
advPainter_current : the
index of current ink
advPainter_rlt : Advanced Painter's panel rollout definition.
You can access the 'Paint' button by using this syntax advPainter_rlt.apPaint
and the status area by using this syntax: advPainter_rlt.apStatus.
- Added
the inkDef structure:
inkDef string>name <array>fns
<array>params <rollout>rlt
<int>version
name specifies the name of the ink which will be listed
on the Inks drop down list. Each names must be unique.
fns is a 5 elements array contains functions for startStroke,
paintStroke, endStroke, cancelStroke, and systemEnd which will be directed
to thePainterInterface.scriptFunctions when Paint button is
pressed.
params is an array to hold the parameters of the Ink
rlt specifies the UI for the Ink.
version is a 4 digit integer to store ink's version.
When inkDef is registered using advpainter regsiter()
function, the system check wheter the ink with the specified
name has already exist in AdvPainter_Inks array. If it is, the system
checks again whether the new inkDef version is higher than the one registered
in AdvPainter_inks array. If the new inkDef is higher, theysystem will
replace the old inkDef with the new one.
- Changed
Scatterer ink's paintStroke function to use 3x4 transform matrix instead
of setting each transform values individually. This should improve performance
to certain level. This changes also introduces align to stroke feature
which orient clone's x or y axis to stroke direction.
- Added
align to
stroke feature which orient clone's x or y axis to stroke direction.
By default this mode is off. When Reverse option is active,
the orientation will be reversed.
- Added
X, Y, and Z Max/Min Orientation parameter which lets user to produce
random rotation on all 3 axis. Previously Scatterer ink only do this
on local z axis.
- Added
the Paste ink. This ink produces toothpaste like shape out of lofted
circles.
- Added
the PostClone Script feature to Scatterer ink. This addition introduces
2 new global variable which is useful when using the PostClone Script
feature. They are:
-
npScatterObj <node> :
current clone
- npScatterObjIdx <integer> : current
clone's index
- New
status area on Advanced Painter rollout. This area tells user if ther
is something wrong with the current ink or PostClone script as well
as other simpler error.
- Replaces
the Options button with Advanced Painter's menu.
- Now
you can paint on non-selected object, by making objects paintable and
turning off 'Only Paint on Selection'.
- Added
more error handling.
Nature
Painter 1.1
- New
Scatterer ink which lets you to scatter objects using brush based interface.
- New
'Strand Direction' and 'Invert Direction' options in Grass Painter as
requested by Keith Chamberlain. When 'Z' is active every grass strands
are forced to face the positive Z axis direction regardles the direction
of surface normals. Its useful when you are painting on bumpy surface.
- Grass
and Stone (and Scatterers) ink now supports undo. The undo system utilizes
the new theHold interface which was introduced in 3ds max 5.1.
- Fixed
a few minor bugs.
Nature
Painter 1.0
- First
public release.
- Converted
my MaxFreeHandTools (by Fred Moreau's) brush definition to Painterinterface's
ink definition.
F.
Bugs
If you
find this tool useful, please contribute to Advanced Painter development
by submitting any bugs you have encountered to my email. Please include
detailed steps to reproduce the error as well as sample scene (if necessary,
and please zip it) to this email: herman-saksono@telkom.net. If you encounter
Assertion Failure, please record the Assertion Error Information, and
include it to the email. Don’t save your scene if Assertion Failure
has occured. |