Tuesday, November 29, 2011

We're in Business!

Added a new business building type. Still have to refine the structure. Also added user control over what types of building to generate on a face (video will be up after beta review). My beta review got delayed, so I'm hoping to stick in a few more building types by then.

Sunday, November 27, 2011

Roofs


Added ~5 roof variations. Need to fix footprint generation when the given lots aren't rectangular, which is a maximal rectangle problem. Here's to hoping Maya has some kind of function for that.

Saturday, November 26, 2011

Mini-City!


Some updates for the week:

  • Implemented functionality to generate buildings given either a selected face, multiple selected faces, a one-faced polygon, or a multiple-faced polygon. This will offer a lot of flexibility for the user when they are selecting regions to generate buildings
  • Fixed window extrusions
  • Altered a big chunk of my original framework for floor-generation. Before, my code would generate one floor, and return the top-most face. The subsequent function would take that face, duplicate it as a transform node, and extrude from that. The problem I ran into with this method was that, in cases where I subdivided the side faces for making windows, the resulting face that I returned would have all the excess vertices on its sides (imagine a square with a vertex for each corner, and then ten more vertices spaced evenly on each side). This was undesirable, since my code assumes that the footprints passed in are "clean" (as in, without necessary subdivisions). I fixed this by making each function duplicate the resulting face as a polygon/transform node (using a helper function I wrote). This way I can create a duplicate footprint before adding windows to the original one.
  • Figured out how to import Maya ASCII files into a scene in python. I'm planning on letting users import their own assets eventually
  • Improved the building-generation flow in the code. The code stores all the faces in a list (if there are multiple faces to work on). For each face, the ground floor is generated first, and the rest of the floors are generated in a for-loop. Each level is split into two additional functions-- createLedge and createFloor.
Some things I'm hoping to finish before the beta review are:
  • Port over the GUI code (right now all the values in Python are hardcoded; the GUI is still in MEL)
  • Create functions for roof-generation
  • Create generation functions for different building types
  • Start functionality for reading in an image file and mapping it to cells on an input map
  • Add more variation

Monday, November 21, 2011

Making Windows

Spent the weekend fixing the the conflict between column generation and building base extrusion. I ended up keeping the initial footprint as a polygon with no subdivisions and creating the columns and base as such:

  1. inwardExtrude to create the actual footprint the building will be generated from (this is to give "sidewalk space")
  2. Add subdivisions to the newly created footprint. Right now it's set to 10x10, but in the future this value can be pulled from the GUI
  3. Select the outer ring of faces for column generation.
  4. ShrinkPolygonSelection (this command took a while to find) to select the inner cluster of faces. I wrote a helper function called deleteSubdivisions to remove the subdivisions for the building base extrusion. The reason for removing subdivisions is keep each wall face clean, so there are no conflicts when I do need to subdivide each face according to how many windows there should be.
  5. Finally we can extrude the building body to the height of the columns to get something like this:

Moving on to the floor generation, the hardest part was to figure out how to select the faces I needed, and how to subdivide each face properly. I actually started this portion earlier this week, except the lack of documentation for polySubdivideFacet led me to believe that it wasn't possible to subdivide in only one direction (ie vertically). Coupled with the fact that maya commands in the actual interface are named differently than the ones in the documentation, I was running around in circles for a few days before figuring out that you actually can subdivide a face in one direction (I ended up trying the Add Divisions tool in maya and realizing it was indeed calling polySubdivideFacet).

That being done, the next step was to scale/extrude each cell to form the frame of a window. From looking through a bunch of other people's code, I learned that polySelectConstraint was the best way to isolate the faces I wanted (ie. all faces on the east side of the building). That being said, I ran into a bug stemming from the fact that I was running transformations on faces that were passed in. I hadn't anticipated the fact that when you iterate through each side face of a floor and subdivide it, you end up with more faces than you started with and trying to keep track of everything by explicitly naming faces becomes much more difficult. So somehow I ended up with this:

Lots and lots of windows
I'm pretty sure I know what needs to be fixed, so this should be good to go by tomorrow. The windows were the last step to the floor creation function, so once that's done I should be able to create a building by calling createFloor numFloor-many times.

Some takeaways:

I feel that the majority of my time up until now has been spent on overcoming the rather steep learning-curve of knowing which maya commands to use to do what you want. I've also become more aware the the flexibility we can get by switching between vertex, edge, and face perspectives (a lot of the helper methods I wrote this weekend utilized this). Previously I was a bit hesitant to post pictures, since I felt what I had was rather lacking given the time that had passed. However I've realized the ramp-up time I took was worth it, since I feel a lot more comfortable coding for maya now, and my productivity has gone up quite a bit.

Just for my own reference (in case all 300 of my tabs crash), here are the Maya commands I find myself using the most:

polyEval
polyExtrudeFacet
polyCreateFacet
polySubdivideFacet
xform
polyListComponentConversion (or just cmds.ConvertSelectionToFaces())
polySelectConstraint
polyChipOff
polySeparate

Friday, November 18, 2011

Adding Details

Most of this week was spent on looking through sample scripts to see what command patterns other people use to generate building details. One thing I've realized is that although I'm fairly comfortable with MEL and python commands in Maya at this point, I still lack a lot of the experience that comes from long-term use of the languages. The most difficult part for me is knowing what commands I should use for a particular task. For example, the code I had before the alpha review had attempted to move the pivot of a model by using the move command in MEL. Now I know the the proper way to go about it is to use the xform command instead, since there is a scalePivot flag specifically for this operation. The python function I wrote for this looks like :

def movePivotToBottom(obj):
    piv = cmds.xform(obj, q=1, ws=1, scalePivot=1)
    newY = cmds.getAttr(obj + '.boundingBoxMinY')
    piv[1] = newY
    cmds.xform(obj, ws=1, scalePivot = piv)

I've written a few helper functions like this one that have been helping me understand the maya commands better. Something else that confused me for a while is the difference between, say cmds.scale(...) and cmds.setAttr(... +  '.scale'). I've tried running both of them, and from what I can tell they both do the same thing. I just haven't figured out circumstances under which each command is advantageous.

Another thing I've realized is that there are MEL commands that aren't found in the online documentation at all. After a frustrating few hours, I found out from a forum that these are either run time commands, or procs that come with maya. To check, you can run whatIs , and Maya would either tell you it's a run time command, or give you the path to the file containing the proc. At first I was worried that I wouldn't able to use certain commands/procs in python, but the maya.mel.eval command saved the day.

I'm almost done writing the function that adds columns to the base of the building. One problem I'm trying to fix right now is that the column-generation code relies on the subdivision of the footprint mesh, and my building-body mesh runs on the assumption that the footprint doesn't have any subdivisions. I'm planning on just making a copy of the subdivision-less footprint, adding subdivisions, and deleting it after the columns are generated. The only remaining problem is to make sure the columns are never intersecting with the building body, which I hope to solve by tomorrow. As I become more familiar with what I like to call "design patterns" for creating building assets, I hope to speed up my process and have images ready by the next update. Until then, stay tuned!

Monday, November 14, 2011

Some Change in Direction + Updates

One of the comments that really stuck with me from the alpha review was why bother creating a building generation script so similar to City Engine, when City Engine already exists. I spent the weekend re-evaluating my project, and came up with some changes that I feel would set my project apart from most of the existing building generators.

The majority of building/city scripts focus a lot on generating sufficient randomness, so the city doesn't look repetitive. Because of this, the user usually doesn't have a lot of say on what types of architecture should be generated at a particular location in the city (in CityEngine this is doable, but requires scripting on the user's end).

I felt this would an interesting issue to address, so I decided to alter my project a bit, such that it focuses on generating a city with different building types, located according to user specifications. I started out identifying three basic types of architecture that exist in a typical city: business buildings, residential structures, and recreational areas, and listed some of their properties below.

 
During one of my review sessions, Norm had suggested the use of a heat-map to specify the placement of different architectural styles. Using that as my start-off point, I plan on having my project take in an image from the user, with each component of the RGB value corresponding to a building type. For example, R = business, G = residential, B = recreational. For colors that have multiple values, I can determine the building type by the dominating RGB value, or by a probability function. This will allow my project to be extensible; additional building types can be added anytime as long as an RGB pattern is specified.

Since Python has an excellent image processing library, I decided to continue my project in python from now on. Currently I'm in the middle of porting my code from MEL to python and thinking about setting up an inheritance structure (if any) for the different building files.

Some links that were really helpful in getting me up to speed with python/maya was Chad Vernon's tutorial site and Autodesk's list of python commands in Maya. Check back in a couple days for more updates.

Sunday, November 6, 2011

Wrangling the Maya Plug-in Wizard

This week I started exploring the Maya plug-in for Visual Studio. Since the whole process took a while to figure out, I thought I'd document the steps I took in case someone else needs it later. The basic set of instructions can be found on the autodesk site here, but additional steps are needed to make everything work (which I will mention below)

  1. The MayaPluginWizard.zip file is found in the devkit/plugin folder under wherever you installed Maya (for me it was C:\Program Files\Autodesk\Maya2012\devkit\pluginwizard). From there, open the MayaWizardReadme.txt, which will give you step by step instructions on adding the plugin wizard to VS (take note there are different instruction sets for 32 and 64 bits.
  2. Unzip the MayaPluginWizard.zip file (I had to copy this onto the desktop first due to permissions). After navigating into the extracted directory, open the MayaPluginWizard.vsz file in a text editor like Notepad++, and make sure Wizard=VsWizard.VsWizardEngine.9.0 refers to the correct version of Visual Studio (VS2008 is 9.0 so I didn't have to change anything).
  3. Copy the following files to the "C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\vcprojects" directory:
        MayaPluginWizard.vsdir
        MayaPluginWizard.vsz
        MayaPluginWizard.ico
  4. Copy the *outer* "MayaPluginWizard" directory to "C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\VCWizards".  NOTE: there should be a MayaPluginWizard directory within a MayaPluginWizard directory after this step.
  5. Now, since my version of Maya2012 is 64-bit, and VS is 32-bit, I needed to configure my VS for 64-bit applications. I followed the directions listed here (basically you need to install the missing x64 compiler and tools). This requires you to have the VS installer on hand, which was a pain. 
  6. Close VS if you have it open. Right click on the icon and select "Run as administrator". If you don't do this, you'll get an extremely vague popup saying "project upgrade failed". Figuring out this part was extremely frustrating.
  7. Now you should be able to create a project using the Maya Plugin Wizard. (Start Microsoft Visual Studio 9.0 and invoke File -> New -> Project -> Visual C++ Projects and select MayaPluginWizard.)
  8. The project will be created and then the solution can updated and built.

Friday, November 4, 2011

Alpha Review Thoughts

After going through the comments on the Alpha Review, I've noted a few areas I could improve on, such as going into more detail on my project context as well as overall progress. The comments were helpful in giving me advice for resources as well as directions to consider for the project. Next I'll address some of the major points in the comments.

Will the final project be procedural generation of a city or just buildings?
This is something I've been thinking about since a few weeks ago. There are two parts to procedurally generating a city: the generation of the building itself, and then the creation of a city by populating city blocks with buildings. While I originally intended to focus on generating the building model, it's something that has been explored many times already, and I think it'd be more interesting to explore different ways the user can interface with Maya to generate a city.  Norm suggested I could have my script import a color-map from the user to determine which types of buildings should be generated in each region of a city. I feel this is a good point to start off on once I finish implementing the functionality to generate a basic building.

How is this different from CityEngine and how does the user benefit from using a plug-in in Maya?
At the moment, most of CityEngine's building generation is done through user-created files. I think it'd be neat if my script can offer a more visual approach like the one I mentioned earlier. Right now I have a couple ideas I'm planning on trying out next week. Until then, thanks for looking!