|
|||||||||
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.
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.
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. SummaryPlug-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) |
|||||||||
|
|||||||||