|
|
Mastering
3D Studio MAX R3 |
Creating Geometry
You can also create geometry from scratch. This is done by defining vertices
and faces manually, through a script. The finished script will create
a parametric geometry object, with vertices and faces, just like any MAX
Object. To demonstrate, lets create a box object, with an option
to have the pivot in the center instead of the base, as seen in Figure
18.13.
FIGURE
18.13 NewBox plug-in script
Start a new script and type all the statements from Listing 18.12, or
open the file plugin_newbox.ms from the CD.
LISTING 18.12: The NewBox plug-in script (plugin_newbox.ms)
plugin simpleObject NewBox
name:”Box2”
classID:#(0x78f66693, 0x4c32d97b)
category:”Mastering 3D Studio MAX”
(
parameters main rollout:params
(
length type:#worldunits ui:b_length animatable:true
width type:#worldunits ui:b_width animatable:true
height type:#worldunits ui:b_height animatable:true
center_pivot type:#boolean ui:b_pivot animatable:false
)
rollout params “Parameters”
(
spinner b_length “Length: “ type:#worldunits range:[-10000,10000,0] \
align:#right
spinner b_width “Width: “ type:#worldunits range:[-10000,10000,0] \
align:#right
spinner b_height “Height: “ type:#worldunits range:[-10000,10000,0] \
align:#right
checkbox b_pivot “Center Pivot”
)
Now that youve defined the parameter block and the rollout, create
the geometry. This is done by assigning the position in local X, Y, and
Z coordinates, and then assigning which vertices make each face. You will
not work with mapping coordinates or smoothing groups in this example.
Continue typing:
on buildMesh do
(
if center_pivot == true then pvt = [0,0,-height/2] else pvt = 0
v = #()
v[1] = [-length/2,-width/2,0] + pvt
v[2] = [length/2,-width/2,0] + pvt
v[3] = [-length/2,width/2,0] + pvt
v[4] = [length/2,width/2,0] + pvt
for i in 5 to 8 do v[i] = v[i-4] + [0,0,height]
f = #()
f[1] = [1,3,4]
f[2] = [4,2,1]
f[3] = [5,6,8]
f[4] = [8,7,5]
f[5] = [1,2,6]
f[6] = [6,5,1]
f[7] = [2,4,8]
f[8] = [8,6,2]
f[9] = [4,3,7]
f[10] = [7,8,4]
f[11] = [3,1,5]
f[12] = [5,7,3]
setMesh mesh verts:v faces:f
)
tool create
(
on mousePoint click do
case click of
(
1: nodeTM.translation = gridPoint
3: #stop
)
on mouseMove click do
case click of
(
2: (
st = gridPoint
length = abs(gridDist.x)
width = abs(gridDist.y)
)
3: height = distance gridPoint st
)
)
)
Evaluate this script and create a box2 in any view. Then, go to the Modify
tab and adjust its values. Notice this works just like a regular object.
The script creates a mesh by using the SETMESH command. This command
will require an array of vertices and an array of faces. The vertex array
holds each vertex position in the local coordinate system. The face array
holds a list of the vertices that make that face.
You can also create more complex geometry using a plug-in script. As
an example, you will create an object that is similar to a cylinder with
a cone on top. You will notice that this script uses many loops, to calculate
the correct XYZ position of the vertex and the correct face that attaches
to that vertex.
This example is a Game object that represents an Enemy Base in a strategy
game. Start a new script and type out Listing 18.13, or open the file
plugin_enemybase.ms from the CD.
LISTING 18.13: The Enemy Base plug-in script (plugin_enemybase.ms)
plugin simpleObject Enemy_Base
name:”Enemy Base”
classID:#(0x5b4365de, 0x9244551f)
category:”Mastering 3D Studio MAX”
(
parameters main rollout:params
(
radius1 type:#worldunits ui:rad1 animatable:true
radius2 type:#worldunits ui:rad2 animatable:true
height1 type:#worldunits ui:ht1 animatable:true
height2 type:#worldunits ui:ht2 animatable:true
segments type:#integer ui:segs animatable:true default:12
)
rollout params “Parameters”
(
spinner rad1 “Radius1: “ type:#worldunits range:[-10000,10000,0] \
align:#right
spinner ht1 “Height1: “ type:#worldunits range:[-10000,10000,0] \
align:#right
spinner rad2 “Radius2: “ type:#worldunits range:[-10000,10000,0] \
align:#right
spinner ht2 “Height2: “ type:#worldunits range:[-10000,10000,0] \
align:#right
spinner segs “Segments: “ type:#integer range:[3,100,12] align:#right
)
on buildMesh do
(
v = #()
v[1] = [0,0,0]
You will now create the vertices on the base of the cylinder.y Their
X position is radius*sin(angle), where the angle will be calculated depending
on the number of segments.
for i in 1 to segments do
(
append v [radius1*cos(i*360/segments),radius1*sin(i*360/segments),0]
)
Next, create the vertices on the top of the cylinder. Theyre equal
to the vertices on the base, except that their height is different.
for i in 1 to segments do
(
append v [radius1*cos(i*360/segments),radius1*sin(i*360/segments),\
height1]
)
Create the vertices on the top of the cone. Theyre equal to the
vertices on the base, except that their radius and height are different.
for i in 1 to segments do
(
append v [radius2*cos(i*360/segments),radius2*sin(i*360/segments),\
height1+height2]
)
append v [0,0,height1+height2]
f = #()
You will now start creating the facesfirst, the ones on the base
of the cylinder. Notice the first vertex is constant, while the second
and third vertices are variable. Then, after the loop, you must also connect
the last vertex with the second one. If you didnt, the cylinder
would have a seam.
for i in 2 to segments do
(
append f [1,i+1,i]
)
append f [1,2,segments+1]
Now repeat the steps above for the sides and top of the object. Remember
that each polygon is now made of two faces.
for i in 2 to segments do
(
append f [i,i+1,i+1+segments]
append f [i,i+1+segments,i+segments]
)
append f [segments+1,2,2+segments]
append f [segments+1,2+segments,1+2*segments]
for i in (2+segments) to (2*segments) do
(
append f [i,i+1,i+1+segments]
append f [i,i+1+segments,i+segments]
)
append f [2*segments+1,2+segments,2+2*segments]
append f [2*segments+1,2+2*segments,1+3*segments]
for i in 2 to segments do
(
append f [2+3*segments,2*segments+i,2*segments+i+1]
)
append f [2+3*segments,3*segments+1,2*segments+2]
Now that every face and vertex is created, you will create the object
and assign the different smoothing groups for each part of the object.
setMesh mesh verts:v faces:f
for i in 1 to segments do setfacesmoothgroup mesh i 1
for i in (segments+1) to (3*segments) do setfacesmoothgroup mesh i 2
for i in (3*segments+1) to (5*segments) do setfacesmoothgroup mesh i 1
for i in (5*segments+1) to (6*segments) do setfacesmoothgroup mesh i 2
)
tool create
(
on mousePoint click do
case click of
(
1: nodeTM.translation = gridPoint
5: #stop
)
on mouseMove click do
case click of
(
2: radius1 = sqrt(gridDist.x^2 + gridDist.y^2)
3: height1 = sqrt(gridDist.x^2 + gridDist.y^2)
4: height2 = sqrt(gridDist.x^2 + gridDist.y^2)
5: radius2 = sqrt(gridDist.x^2 + gridDist.y^2)
)
)
)
The final result of this script is displayed in Figure 18.14. This script
is a good example of a plug-in script, in terms of parametric geometry
creation. It does not have UVW maps; if you want to know how to add UVW
coordinates to a plug-in script, look at the Online Help and at the examples
supplied with MAX.
FIGURE
18.14 Enemy Base plug-in script
A good tool you can use to create plug-in scripts is the MAXScript Export
Sample Utility (MXSExport.ms) that comes with MAX. It will
allow you to select any object in the scene and will create a plug-in
script of it.
Summary
Plug-in scripts are a complex but useful tool in MAX. They will sure
save a huge amount of time, and help you standardize your work.
Through the chapters in this Part of the book, you learned the concepts
of MAX-Script and learned ways to use it on a daily basis. However, MAXScript
is much more than just what we had room for here. Exploring MAX is the
best way to move ahead.
You can ask questions and get support through the Web, at the Online
Support Forum: http://support.discreet.com/~max. Theres a
conference full of tips and samples only for MAXScript. You can also find
information about this book and MAXScript development at http://www.origamy.com.br/english/tools.html.
© 2000, Frol (selection,
edition, publication)
|
|