Question

I made a 3D tree in Maya and need MEL code to run in a for loop and generate as many trees as I want. Is there any way to convert a model made in Maya into MEL code that would rebuild the tree?

I can't just duplicate it because the script needs to generate the tree from scratch. Unfortunately, I cleared my history because it was messy, so I am looking for a way to generate the MEL code given just the geometry.

Was it helpful?

Solution

It is slightly unfortunate that you deleted the history. If you had not then you could have just built a script out if the history tree. But all is not lost, still i will explain how you can do this in case you do remake the history at some point.

The complexity of your history is never really a issue, at least when modeling. I would advice to not delete any history until your sure its of no use. Having a 1000 node history is not in any way slowing you down since most of it is inactive. Its only a problem once you enter animation even then its not necessarily a problem at all. Since the history deletion is a bit destructive its a good idea to save the scene when you are deleting big areas of history. So rule of thumb do not delete history and use the freeze transformation operation unless its really necessary (and it may be you never actually do this).

Another side remark: Copying stuff is still valid, unless like in this case there is a artificial limitation. The only time when this limitation is valid is if this is homework (in which case you may want to demonstrate that your willing to follow instruction). Doing a copy does not detract in any way the end result. Copying is mel (and all maya ascii files are mel of sorts).

Method 1: (when history is cleared)

You can reduce the problem to a normal rigging operation. What you do is you rig the tree that you built with bones, clusters and possibly blend shapes. Then just randomize the channels of your rig on each copy operation. The neat thing here is that the script can be easily extended with different base trees, or just about anything, just by making new separate rigs.

The bonus here is that you could now also easily animate the tree being blown by the wind etc.

This might feel like something outside the scope of the assignment. However a good MEL programmer does not really separate tasks. Using a node to do something is just as valid, if not more valid, as writing everything in code. Something like this demonstrates really thorough understanding of maya use and maya programming. On the other hand not all users are as enlightened (most are not).

Everything in Maya is or at least should be a rig. (the auxiliary to this is that your mel should strive to build a rig or you should use API to make nodes)

Method 2: (when history is cleared)

Chunk your result into pieces. Then randomize the chunk positions with L-system like rule based generator. It may seem counter intuitive to use a L-system with hand modeled pieces when the entire thing could be generated with a L-system. But clunking allows for a very simple l-system to be built. The end result also retains the artistic integrity of the original in some ways that might be much more pleasing.

A slightly different version of this and method 3 is to make 2-3 overlapping set of branches in the model and then randomly delete branches for variation.

Method 3: (when history is cleared)

Cheat, well i would actually argue that in CG there's no such thing as cheating. Just copy the same tree about, alter its rotation ans scale. And randomize new shaders to your model (swap different leaf textures different color etc). When combined with even slight amount of rigginng approach can totally hide the fact that there is just one tree. Copies dont have to be all that exact they might be shaped with a lattice or something. This is actually pretty efficient, most people wouldn't notice.

Method 4: (when history is not cleared)

When you model something manually maya records this quite efficiently. The history can be turned into a script with little or no effort. The best kept secret. If you save this kind of scene as maya ascii then the maya ascii file is (almost) just mel and you can repeat this by adding variables to the stream to instrument it to mel. Beware tough that not all tools build meaningful history so point tweaks should be done on clusters instead on manual point tweaking that ends up in the shapes tweak array.

It is also possible to build the mel automatically with a mel script that checks for connections and values in nodes to reproduce the thing in code. The good thing is that you can readily introduce the instrumentation. Here's a really old version of code as giveaway (you need to handle the shaders and inputComponents for example):

/* jooConvertNodeNetworkToMelLadder.mel  0.0

  Authors:     Janne 'Joojaa' Ojala
  Testing:     Has known bugs, code deprecated, no bug reporting
  Licence:     Creative Commons Attribution-ShareAlike 3.0 Unported
  About:

  A deprecated early version of code generation it has some bugs and
  is nowhere near perfect but you can have this code for the heck of
  it. Main thing missing is that it does not check for selection 
  sets for nodes so you need to make those manually.

  Install Instructions:

  copy jooConvertNodeNetworkToMelLadder.mel to your maya script 
  directory

  Usage:

  Select node and run jooConvertNodeNetworkToMelLadder from mel 
  commandline.

  Deprecated at 31.12.2006
*/

proc string generateAttrib(string $node, string $createNode,
                           string $attrib,string $varName){
  string $return="";
  if (getAttr($node + "." + $attrib) != 
      getAttr($createNode + "." + $attrib))
    $return = ("  setAttr (" +
                $varName + "+\"." + $attrib+"\") "+
                getAttr($node + "." + $attrib) + ";\n");
  return $return;
}

proc string doOneNode(string $nodeOrig,string $connections[]){
  string $hist[]=`listConnections    -c 1 -p 1 $nodeOrig`;
  string $return="";
  $type=`nodeType $nodeOrig`;
  $varName=("$"+$nodeOrig);
  $createNode=`createNode $type`;
  $return=("  "+$varName+"=`createNode -n "+$nodeOrig+" "+$type+"`;\n");
  if ($type != "mesh") {
      for ($attrib in `listAttr -settable -multi -w -scalar $createNode`){
          $return += generateAttrib($nodeOrig, $createNode,
                                    $attrib, $varName);
      }
  }
  delete $createNode;

  for ($i=0;$i< size($hist);$i=$i+2){
    if (size(`connectionInfo -dfs $hist[$i]`)){
      string $node,$port,$type,$nodeOrig,$portOrig;
      $node=`match "[^.]*" $hist[$i+1]`;
      $port=`match "[.].*$" $hist[$i+1]`;
      $nodeOrig=`match "[^.]*" $hist[$i]`;
      $portOrig=`match "[.].*$" $hist[$i]`;
      $connections[size($connections)]= 
      ("  connectAttr -f ($" + 
        $nodeOrig + "+\"" + $portOrig + "\") ($" +
        $node+"+\""+$port+"\");");
    }
  }

  return $return;
}

global proc jooConvertNodeNetworkToMelLadder()
{
  print "\n// jooConvertNodeNetworkToMelLadder result:\n{\n";
    string $a[]={};
    for ($node in `listHistory`)
    print(`doOneNode $node $a`);
    print $a;

  print "}\n";
}

But this is all I have time for, hope this helps.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top