Dec 2011
1 / 20
Dec 2011
Dec 2011

I haven't had too much time with MEL yet so I'm still strugling with the language. I am not asking anybody to do my project for me but to help me find the right way to approach this project so I can finish it.

I'm currently doing a project for one of my 3D scripting classes in which I have to create a Random City generator. I made 5 simple buildings and now I have to design a GUI that makes them appear in a city. The only clue my instructor gave me is to use a recursive function, but I am seriously lost as to how to approach this project.

P.S. I added a screenshot of the buildings that I made (4building, 1 parking lot with cars)

how do you intend to call the buildings into the scene? if they're as simple as they are in the pic you could have their entire creation in the script, if they're fairly complicated geo, you could look at having a library which contains the geo and simple gets imported in the scene.
Te following is just what i would do, i've only a year or two in self-taught experience, so some of my practices are not the most efficient methods etc, but this would be similar to my thinking.
Dont be too ambitious just yet, start simple, try to spend time understanding why things are working/not working, then develop.
The best piece of advice i think i could give is plan. Plan your backside off, as it'll become your best friend. i would take a pen a paper and create a flow chart, organising what i want to do and how i want to go about it, this way you can keep things planned.
Then start off simple, create a sphere, at a position you specify with a locator or something.
Then do multiple objects in different locations, and take it from there.
Recursive would mean a loop, either "for" or "while", have a look at maya's documentation and example scripts that contain notes.

When you develop a script, your not doing anything fancy. 98% of the time even hardcore codes don't do fancy things. Whet you do falls somewhere between making a shopping list and a recipe.

In your case make one whatever you want, look in script editor copy it and put it inside a for loop. Once you understand taht then do more.

@Idunham: They are fairly simple geo that I created in the scene (example: the tower building is just 3 cylinders stacked on top of each other), but here's when i come to a halt and dont know how to do this. Now that i have the building should I create a procedure that creates each one and then put those inside another main procudure that is recursive? But then every time the function would call itself wouldn't the buildings be created in the same place?

That is how i would approach it yes.

You can give proceedures arguments also, ie

global proc createMe(float $pos[])
{
string $obj[]=polyCube ;
move $pos[0] $pos[1] $pos[2] $obj[0] ;
}
createMe({0,1,0}) ;

and so on. but of course there are many, many ways to do this, even another proc which moves the object into place once given the name of the object (stored in the variable which the object is created in - this way, if the object is renamed upon creation, to avoid duplicate names, its name is stored in the variable) 

Well you would actually have 2 separate parts of logic one for recursing and ne for actually makeing sure you recursing starts sanely if you can not describe it all in recursion. So at that lowest level yoru code needs tobe bastract like some very easy code.

However every piece of code that can be recursed can be written out flat, so unless your mind gives you some specific results from recursing then dont recurse. That is to say if you cant figure out a way to do something in way X but do in way Y use Y. If however you dont know how to do X or Y then you need to start working with some procedural development methodlogies to investigate the solution.

One way to solve this is to take a look at other peoples city generation scripts.

just curious Joojaa, for your first point you mean something simular to;

global proc city_create(string $obj)
{
  //creation of object...

global proc city_move(string $obj, float $pos[])
{
  //positioning of object...

string $itemsToCreate[]={"house","skyscraper"} ;
for($item in $itemsToCreate)
{
  city_create($item) ;
  city_move($item,{10,0,10}) ;

Well something like it i would just call the body of yoru code city_create and bundle your cyty_move, and cerate into a make_building.

Thanks for the help everyone! I'll take your suggestions into consideration and see what I can come out with. Also I wanted to ask your opinions of the following code, a classmate of mine told me this following code is basically what i need to have in order to complete the project yet it doesn't work if you try to run it. I have this code just in case I can't make it work on my own. But I'm not giving up yet I think that what you guys suggested might be the solution.

proc Bld1(float $myX, float $myZ){ //proc for building 1

polyCylinder ;

move -a $myX,0,$myZ;

}

proc Bld2(float $myX, float $myZ){ //proc for buiilding 2

polyCube;

move -a $myX,0,$myZ;

}

proc Bld3(float $myX, float $myZ){ //proc for building 3

polyCone;

//move -a $myX,0,$myZ;

}

proc Bld4(float $myX, float $myZ){ //proc for building 4

polySphere;

move -a $myX,0,$myZ;

}

proc Bld5(float $myX, float $myZ){ //proc for building 5

polyPlane;

move -a $myX,0,$myZ;

}

float blockLocX[5],blockLocZ[5]

for (int i=0; i<5; i++){

int $chanceRes = rand(0,100);

if($chanceRes <= 60){

pickABld(blockLocX[i],blockLocZ[i]);

}

}

proc pickABld(float $thisX, float $thisZ){ //in this proc were going to set parameters for each of the buildings

int $wBld = rand(0,100); //set random variable to determine which building will appear

if($wBld <= 20){ //each building will have a 20% chance of appearing in scene

Bld1($thisX, $thisZ);

}

else if ($wBld <= 40){

Bld2 ($thisX, $thisZ);

}

else if ($wBld <= 60){

Bld3 ($thisX, $thisZ);

}

else if (wBld <= 80){

Bld4 ($thisX, $thisZ);

}

else if (wBld <= 100){

Bld5 ($thisX, $thisZ);

}

}

theres quite a few syntax errors in this, starting with the objectCreation procs, your seperating the x y and z values with a comma in the "move" command which you shouldnt do (check the docs for working examples of mel commands)

theres quite a few missing "$" to declare variables.
you dont need to declare $i in the for loop as in "int", it knows it is with the parameters you set for the for loop.
you also missed a semi-colon ";"  when declaring the floats $blockLocX[5], $blockLocZ[5] ;

I'm abit confused why your creating a specific empty floats $blockLocX[5], $blockLocZ[5]? if those are the parameters to move the objects you'll have meant 
float $blockLocX[]={1,2,3,4,5} ;
float $blockLocZ[]=$blockLocX ;

however that also means when you run the working script it'll place objects  (X and Z) at 1, 1 or 2, 2 or 3, 3 etc, not in the random order you'll want.

You'll want to use a random positions generator.

Theres also a few things you can do to your code to simplify and improve, but after these cleans it does work, so just keep taking it further, looking at other city generators as Joojaa pointed out, and keep learning.

Here's an update on my current progress. Right now as I said in my previous post I created another code besides the one I posted here. The following image is how it looks currently when it runs and also I created a simply GUI to change the height of the buildings.

I also went back and made all the corrections of the code that I posted here before. Yet it still has 4 errors:

// Warning: New procedure definition for "Bld1" has a different argument list and/or return type. //

// Error: pickABld(blockLocX[i],blockLocZ[i]);

//

// Error: Line 59.29: Invalid use of Maya object "i". //

// Error: pickABld(blockLocX[i],blockLocZ[i]);

//

// Error: Line 59.42: Invalid use of Maya object "i". //

And here is how the code currently looks like

proc Bld1(float $myX, float $myZ){ //proc for building 1
polyCylinder ;

move -a $myX 0 $myZ;

}

proc Bld2(float $myX, float $myZ){ //proc for buiilding 2

polyCube;

move -a $myX 0 $myZ;

}

proc Bld3(float $myX, float $myZ){ //proc for building 3

polyCone;

move -a $myX 0 $myZ;

}

proc Bld4(float $myX, float $myZ){ //proc for building 4

polySphere;

move -a $myX 0 $myZ;

}

proc Bld5(float $myX, float $myZ){ //proc for building 5

polyPlane;

move -a $myX 0 $myZ;

}

float $blockLocX[]={1,2,3,4,5};

float $blockLocZ[]=$blockLocX;

for ($i=0; $i<5; $i++){

int $chanceRes = rand(0,100);

if($chanceRes <= 60){

pickABld(blockLocX[i],blockLocZ[i]);

}

}

proc pickABld(float $thisX, float $thisZ){ //in this proc were going to set parameters for each of the buildings

int $wBld = rand(0,100); //set random variable to determine which building will appear

if($wBld <= 20){ //each building will have a 20% chance of appearing in scene

Bld1($thisX, $thisZ);

}

else if ($wBld <= 40){

Bld2 ($thisX, $thisZ);

}

else if ($wBld <= 60){

Bld3 ($thisX, $thisZ);

}

else if ($wBld <= 80){

Bld4 ($thisX, $thisZ);

}

else if ($wBld <= 100){

Bld5 ($thisX, $thisZ);

}

}

you still missed some of the "$".

 pickABld(blockLocX[i],blockLocZ[i]);

when you need

pickABld($blockLocX[$i],$blockLocZ[$i]);

also theres no need to worry about the inital warning-

// Warning: New procedure definition for "Bld1" has a different argument list and/or return type. // 

Oops you're right, I forgot to add that $ in there.

It seems that everything is at least from at syntax perspective right but I am down to one last problem.

Now i only have one problem besides the warnings.

this is the line that apparently has issues but I don't understand what it means by saying its an invalid use of the object, since to me the line makes sense.

pickABld(blockLocX[$i],blockLocZ[$i]);

// Error: Line 59.31: Invalid use of Maya object "blockLocX[". //

lol you didnt put in all the $ that i pointed out.
blockLocX and blockLocX are variables, therefore;

pickABld($blockLocX[$i],$blockLocZ[$i]); 

/facepalm i feel like an idiot. Thanks for being patient with me lol

i think i might have to make a change though

this is making the objects appear in a diagonal line since basically its giving them coordinates like 1,1 and 2,2 etc since $blockLocX[] = $blockLocZ[]

float $blockLocX[]={1,2,3,4,5};

float $blockLocZ[]=$blockLocX;

Which is one of the things you warned me about now that i think about it.

Is it posible to set it to random? like for example  float $blockLocX[]={rand(-100,100)}?

yeah thats fine, but then it doesnt need to be an array, as your receiving only one return from random.

then that means theres no need to use a for loop to  loop through $blockLocX's arrays so you might as well forget storing the random number into an array as it'll just place everything in the same values (because your not telling it to generate a new random number for each object)

so i'd would have suggested instead of
pickABld($blockLocX[$i],$blockLocZ[$i]);

to use
pickABld(rand(-100,100),rand(-100,100)); 

HOWEVER, this also means the same thing, as your only running this command once for all the buildings that will spawn on that instance of the command running.

SO, you could instead for each building

Bld1 (rand(-100,100),rand(-100,100));

Ive also just realised that your proc will possibily spwan more than one building per execution as your including the max value and not a min one.

ie say int $wBld = rand(0,100); returns a number less than 20?
currently every Bld object would spawn, but only once each, just curious as to whether that was your intention?

ill make that change thanks for just suggestion, i guess the for loop does become redundant.

about your last question, when i run the code as it is now every Bld object doesnt spawn when it runs.

About my current progress: Currently I literally have 2 codes that work, the one that i posted here and another one that i made from scratch that has GUI elements on it.
If you want me to post it I could, just ask. :slight_smile:

np.

about your last question, when i run the code as it is now every Bld object doesnt spawn when it runs. 

nope you right it shouldnt, i didnt account for the "else" in the statements.

If you want me to post it I could, just ask

thats completely up to you really if you needed anymore help/advice. Good luck!

It sounds like the project might be more about designing a flexible UI vs. actually placing the objects

I do these things alot at work :stuck_out_tongue:

if this is the case...

I would have a folder called "buildings" and every building you made would be saved into that folder as a new file

then when you create your UI, you just need to look inside that folder for all the mb files, and do a for loop in the menu to add all your buildings into the menu as their own button (pseudo code follows)

start ui here

folder = list all your items in the folder;

for(file in folder)

{

add menu item to your ui

or button with a command

add button command importPlaceBuilding(file)    // see proc for what this means

}

you would have this proc to import and place them in your scene

proc importPlaceBuilding(string $fileToImport)

{

import code would go here

but you also need to decide how to place your object

}

this way the more files you add to your folder, each time your UI opens, it will code itself for you!

now if its how to place things, I would do it viral style!

place 1 building, know its dimensions, randomly pick how many sides will continue to grow out, and spread! adding more buildings around the previously placed buildings

if you say... run the loop X times, it would grow outwards X times from the center

This is all the advice I will share for now, as it sounds like the biggest part of this homework is to discover the code you need to use, I have left but pseudo code only :stuck_out_tongue:

Most of the time the logic behind a tool is the hardest part, I use this really advanced technology at the office... pencil and paper.. or if im feeling frisky... looks around to make sure no one is watching whiteboard!! to design the logic of how to aproach the problem

Michael is on to something :slight_smile:

See the thing is people often forget that the easiest ever way to do all theese automation tasks is to save things in files. Thats right EVERY application that has a load and save option has a templating mechanism.

In whuich case its a retarded exercise. If the objective is to have a flexible ui then:

  1. The end result should be a node, allmost certainly period. Theres not much point in having über cool gui for something that for all intents and puproses is random and needs to be reiterated. Unless its a node, in which case the attributes of the nodes creates the ui.

1a. This means it could be a particle instancer based thing, if you want fast interaction with the iteration on screen (theese can then be unisntanced if theres greater need after he fact.)

  1. Or if not a node it should be a artisan sculpt script, that is allmost as good if not better.

Actually the logic behind the GUI or user interface is just as hard to come up as the whats done in first place. They are linked, if your original script does not do something, then the gui can not do this. And the what you do is both a reflection of your GUI and your excutors implementation. Theese 2 things are or atleast should be the same thing.

 This is why software engineers dont jump into the plan directly, but rather they try to map the need. Because in the end doing the right thing saves you a lot of work. 85% of ALL development projects fail before any real implementation is done, at the preliminary design stage where the requirements are gathered.

Suggested Topics

Want to read more? Browse other topics in Maya or view latest topics.