quick tip #1

It’s been a while since I’ve done anything in MEL. I try to avoid MEL when I can; after two years of doing the majority of my Maya tools and scripts in Python (with the last year being pure Python), switching gears to work in MEL and losing the object-oriented nature of Python (along with its wonderful string and array manipulation tools) makes me feel like I’ve got a hand tied behind my back.

Still, MEL’s importance will continue for some time and there will be times when it’s necessary to hack out a bit MEL code. I wanted to make a quick tip note about something I’m embarrassed to say I didn’t know until a few days ago that might help you with your MEL scripts.

I use the whatIs command often to track down the source of built-in scripted functionality. Calling it on a function that exists in default MEL scripts will tell you in which script that function lives and where to find it; afterwards, you can break it apart and use the pertinent parts in your own script.

However, what I did not know is that whatIs can also tell you about in-memory variables. Here’s an example:

string $value = "Bunnies";
int $intArray[] = { 1,2,3,4,5 };

whatIs "$value"; // Result: string variable //
whatIs "$intArray"; // Result: int[] variable //

If you run the code you’ll see that it returns a string with the type of the variable you checked. Quite handy, since you can use it to check types of default global variables. But even handier is what happens when you use it on a variable that has not yet been created:

whatIs "$someWonderfulVariable";

This will return the string “Unknown”. If you, not unlike my recent self, are trying to determine in your or someone else’s code whether a required variable has been created, this is the way to check.

In other news, my new job begins on Tuesday. I’m extremely excited and I’ll post more about it once I’ve gotten situated there.

Also, if you’re Canadian, elections are happening on Monday! An interesting notion is the thought of voting for a non-Reform party candidate in your riding whose projections are highest instead of voting for the party or a leader you’re usually inclined to do, with an eye towards unseating the current Reform government and getting Harper out of there. Two websites on this very thing:

http://www.whipharper.ca/
http://www.projectdemocracy.ca/

Don’t worry– I won’t be mixing political messages with code tips in the future.

Tags: , ,

spring in puerto rico

… is apparently going to be 25 degrees Celsius and none too rainy.

I’m about to take off for a few weeks to visit my mother. It’s the first time I’ve ever been to Puerto Rico when it’s not Christmas; I’ve been apprehensive about how hot it’s going to be, and about how few pairs of shorts I have in my possession.

I have a few things I wanted to mention before I leave. The first is Female Body Parts. Now, I know that sounds morbid, but it’s a photo book of close-up images of various parts of the female anatomy. There’s lots of great reference of eyes, mouths, tongues, noses, and things that are not the face. I bought it while I was in Brooklyn earlier this month visiting Luckbat. It came with a CD, which I figured would have 1K-ish resolution images on it. Imagine my surprise when I found every image on the disc to be over 4Kx3K! At the $30 price tag it currently has on Amazon, that book is a steal.

The other thing I wanted to mention is Messiah 5. If you’re like me, you weren’t able to get it loaded and running after the install. I finally figured it out today and I wanted to post about it. Here’re the steps to getting it working. Keep in mind I’d already gotten one USB stick licensed before I ran through these steps.

1) Run the remove demo script.
2) Run the uninstaller script.
3) Unplug all USB devices.
4) Re-copy Messiah from the original download.
5) Run it. Allow it to get to the licensing screen.
6) QUIT out of the licensing screen by hitting the red X on the window, and allow the program to fully exit.

Now if you plug in your USB stick and run Messiah, it loads fine.

It seems that if you’ve got a license file in there on the initial install, for some odd reason the Crossover Chromium folder doesn’t get created in your ~/Library/Application Support/ folder, which (I believe) is what’s screwing things up.

Either way, it’s loaded for me. I don’t know anything about the program yet but at least I can experiment now.

Wish me luck on the flight. And wish my mother luck!

coming up for air

I upgraded my Blackberry last night to the Bold 9780. The initial shock of an OS two major number revisions after what I’d been using was huge, but the guy at the shop transferred all my contacts and email and everything was up and running again with almost no pain. That’s something Blackberry has up on the iPhone– had I gone for an iPhone 4, I’d have had to take the phone home to transfer my contacts as opposed to having a working phone 30 minutes after purchase for a night on the town.

January has been a rough month. There was a seriously crazy deadline at work that has now been pushed, so the first half of the month found me working a lot. Now, I find myself with time again, and that’s pretty exciting.

Work lately has been mostly about asset manipulation– shader updates, automatic updates, and so forth. I’ve been learning a lot about the limitations of such things and about how to determine when a scripted approach can be beneficial, provided all assets are in the same format. That’s not saying there isn’t a bunch of work to be done up front. A lot needs to be scripted or done by a very meticulous person.

I think I might do a few short tutorials here on 3Delight, because the more I use it the more I love it and the more I realize there are a number of things about it that are quite confusing. Here’s hoping my free time stays free.

501 for christmas

Modo 501 is looking fantastic. I downloaded it today, and I can’t wait to put it through it’s paces. I’m especially excited about the revamped painting and sculpting, since it means I can stay in one app as opposed to jumping back and forth between Maya and Mudbox or ZBrush. But more that that, I feel like Modo is exactly where Blender will be once the 2.5 series is put to bed and gives birth to a stable 2.6. Everything is scriptable and it’s extremely simple to make new commands, or commands that properly refire when using interface sliders. I think my favorite part is, I’ve yet to find a feature I don’t like that I couldn’t disable or otherwise change its behavior. Even the default space bar behavior (which switches between component editing modes) is changeable; mine is set to pick item mode now. Not to mention, one of the new guys at work, Rowan, is a Modo master. He’s been invaluable in finding out where things are.

It’s a pretty steep learning curve both modeling and scripting-wise, particularly for someone who’s only really done 3D scripting through the Maya and Blender APIs. Also, while every tool I use when modeling seems to exist in Modo, the names and methods for use are so different that it’s taken me all week to find the first quarter of my usual bag of tricks. But I’ve also picked up a few new ones, like Background Constraint with Vector direction. Holy crap, did I not know I wanted that feature so badly.

Blender’s always going to be there for me, but at least until the 2.5 series stabilizes (and the input manager stops getting stuck when I sculpt, making sculpting impossible), I have a new swiss-army knife for work. Oh, and Luxology: thank you for making my ordering process amazing. I’m not going to say why I’m so happy with you on this blog, but if more companies behaved like you I’d be a happier person all around.

It’s funny, though– I’m not finding with Modo that I fight the learning curve as much as I do when I move to, say, Houdini. Modo draws from all the best parts of Blender, Maya, and Lightwave, so it just works for my head. Here’s to being more efficient with modeling tasks in 2011!

By the way, the new Gorillaz album (the one recorded on an iPad) is up for streaming. I like it a lot more than Plastic Beach. In fact, it feels a lot like D-Sides, which is one of my favorite collections of their music. If you’re a fan, definitely check it out. And if anyone knows what iPad software Albarn used to master these songs, please let me know.

inspiration, part two

It’s been a whirlwind of a few weeks. At work I’m back on the DVD project, working on a few of the scripting things I’ve wanted to have done since the first DVD. It feels good to be checking those things off on my list. I also ended up writing a few pipeline tools. Today is a day for bulletproofing them.

I saw both Tangled and Harry Potter 7a recently. Both were terrific. Tangled took its time getting started, but once all the players are in place it becomes a very satisfying ride through until the end. The horse, Maximus, has become my favorite animated feature character of all time. In fact, animation-wise this is the strongest film out of Disney since, perhaps, the golden 90’s. There were some sequences where I’m sure the animators were let run wild with their ideas, and the results are uproarious.

HP7’s effects were out of this world. It’s expected that each Harry Potter outdo the last in terms of visual quality, but this one outpaced all my expectations, and did so with a perfectly-paced plot that followed book seven’s first half quite closely.

Between those two, and the new Avatar Collector’s Edition (yeah, I’m a sucker who just bought the same movie again), I’m to the brim with inspiration. Tangled on the big screen reminded me what I loved about Disney films when I was little, and a bit about why I wanted to become an animator. HP7 reminded me how much fun it is to be able to lose myself in a world that doesn’t exist and, even if only for a moment, believe that somewhere, somehow, those characters and their eventual triumphs are all real.

Long story short, seeing movies like those always makes me feel energized for what I do for a living.

On the musical side, I’ve bought so many CDs recently that I’m almost at a loss for what to listen to because there are too many choices! I finally picked up a copy of 2009’s Sounds of the Universe by Depeche Mode. Not quite Destroying the Angel, but still decent. Duffy’s new disc, Endlessly, is lovely start to finish; if she’s this good now I look forward to her releases a few years down the line. Her sound has changed just enough to invite new listeners without alienating fans of the first disc. She’s also one of those rare pop artists who, in my opinion, manages to keep love songs from sounding trite or contrived.

About a week left before the break. Here’s hoping I get some sleep.

calgary ahoy

I landed just fine in Calgary last night. I think the city knew I was coming because this morning there’s a healthy dusting of snow over everything.

Each time I come back the city looks a little more different. Even the downtown skyline isn’t one I recognize any more. It’s strange, turning down familiar streets and seeing unfamiliar landmarks shoulder-to-shoulder with the old. I mean, that happens everywhere– Toronto is notorious for new shops vanishing within a handful of months of opening– but it’s different to see it happening in the place I still call home.

Differences aside, the traditional Albertan friendliness hasn’t changed, and that’s something I definitely miss, living in TO.

I’m still getting over the fact that I have a whole week off. I know Banff is on our list, and I’m actually going to visit more folks than just Trez and her kin this time around, but I’m really looking forward to taking my 7D out and seeing what I can see.   

today’s collected inspiration

I have a soft spot for stories where tiny people meet and make friends with us regular humans. Arrietty the Borrower is looking good. Trailer says: “This is the story of the coming together and coming apart of a ten-centimeter tall girl and a young boy” (or something close to that effect).

Not to mention, ゲド戦記 (Tales of Earthsea) was also finally released recently, although I didn’t see it up for viewing anywhere near me. I’ll have to wait for the Blu-ray on that one.

Another animated thing I’m excited for is the new 3D Le Petit Prince. I hear it’s 26 episodes, and that in each episode he goes somewhere completely different (odd and exotic for a 3D TV show, seeing as that’s a lot of built-out). There’s a bit of art here.

fully functional?

Seems like everything is finally working!

The move over to Dreamhost was not without its bumps with regards to WordPress. I made the mistake of thinking that the “backup” tool was what I needed; turned out it spit out an unusable SQL database dump. Export was what I wanted but by the time I’d figured that out my site URL was already pointing at its new home. It took me a good chunk of yesterday and all morning today to find a workaround, which involved editing the old SQL database by hand, but now all my old WordPress posts have transferred and everything is working again.

My friend Mike has been a Dreamhost customer for years; possibly for as long as I’ve known him. He’s never had any complaints, and as particular as he can be about technology (not as particular as myself, mind) I thought that him being a satisfied customer was the highest compliment a company can be paid. As is always true when he gets me to try something new, either directly or indirectly, I am not disappointed. There were so many things I wanted to do with my old Yahoo hosting where I was told either it wasn’t possible or it wasn’t something they were interested in supporting; all those limitations are now gone with Dreamhost. Plus, hey, I get a shell account with Emacs again!

This site’s going to be changing. I’ve spent most of this year figuring out what I want to do and how I want to accomplish those goals; I hope that the coming months see me with more time to do just that. I’m going to start by talking more about gaming in general. In particular, I want to start writing game reviews again. I think the last time I did so was three or four blogs / hosting services back. Reviewing games is good for understanding how games work, or moreover, how and why they fail. I might start with Mirror’s Edge soon as I can find the time to finish it.

moving house

This is just a parker post for the moment. I’ve just upgraded from Yahoo to Dreamhost.  I’ve disabled the link on the main page.  It turns out that the SQL backups WordPress sends aren’t as easy to restore from. ^_^;

first steps in openCL

I’m going to post something about my trip to Italy in a bit, after I get my pics uploaded properly to Flickr. But I wanted to put this up so I don’t forget about it later.

A conversation at work got me interested enough in GPGPU calculations to start doing a bit of research into the topic. Seems that at a base level both the ATI and NVidia APIs behave similarly, and that OpenCL is a nice, understandable alternative if you don’t want to be locked in to a single vendor. (Not that I use ATI cards.) I tried getting CUDA working on my Mac, but between weirdness caused by the drivers and the fact that it doesn’t support 64-bit on OSX, I’ve decided to go with OpenCL instead for my tests. Functionally everything will be the same, and after a nice tutorial on ATI’s site detailing some introductory points I have code that compiles and does what I want it to do, which is more than I can say for CUDA.

Anyway, here’s my first test. I wanted something simple for getting device information off my laptop.

#include <iostream>
using namespace std;

#include <stdio.h>
#include <stdlib.h>

#include <OpenGL/gl.h>
#include <OpenGL/CGLDevice.h>
#include <OpenCL/cl.h>
#include <OpenCL/cl_gl.h>
#include <OpenCL/cl_gl_ext.h>
#include <OpenCL/cl_ext.h>
 
#define MSG_SIZE 4096
#define MAX_DEVICE_IDS 16

#define RT_STRING       0
#define RT_UINT         1
#define RT_BOOL         2
#define RT_PLATFORMID   3
#define RT_SIZET        5
#define RT_SIZET_ARR    6

void printDeviceInfo(cl_device_id deviceID) {
   
    cl_device_info param_list[] = {
        CL_DEVICE_NAME, CL_DEVICE_VENDOR, CL_DRIVER_VERSION, CL_DEVICE_VERSION,
        CL_DEVICE_PROFILE,
        CL_DEVICE_PLATFORM, CL_DEVICE_VENDOR_ID,
        CL_DEVICE_MAX_COMPUTE_UNITS, CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS,
        CL_DEVICE_MAX_WORK_ITEM_SIZES, CL_DEVICE_MAX_WORK_GROUP_SIZE,
       
        NULL
    };
   
    int param_return_types[] = {
        RT_STRING, RT_STRING, RT_STRING, RT_STRING,
        RT_STRING, RT_PLATFORMID, RT_UINT,
        RT_UINT, RT_UINT, RT_SIZET_ARR, RT_SIZET,
       
        NULL
    };
   
    char *param_strings[] = {
        "Device Name", "Vendor", "Driver Version", "Device Version",
        "Device Profile", "Device Platform", "Device Vendor ID",
        "Max Compute Units", "Max Work Item Dimensions",
        "Max Work Item Sizes", "Max Work Group Size",
   
        NULL
    };
   
    int i = 0;
    int maxWorkItemDimensions = 3;
   
    while(param_strings[i] != NULL) {
        char    msg[MSG_SIZE];
        size_t  param_sizeT;
        size_t  param_sizeT_array[MSG_SIZE];
        cl_uint param_uint;
        cl_bool param_bool;
        size_t  param_value_ret;
        cl_platform_id param_platformID;
       
        cl_int error;
       
        switch (param_return_types[i]) {
            case RT_STRING:
                error = clGetDeviceInfo(deviceID,
                                        param_list[i],
                                        MSG_SIZE,
                                        msg,
                                        &param_value_ret
                                        );

                cout << param_strings[i] << ": " << msg << "\n";
                break;

            case RT_UINT:
                error = clGetDeviceInfo(deviceID,
                                        param_list[i],
                                        sizeof(cl_uint),
                                        &param_uint,
                                        NULL
                                        );

                cout << param_strings[i] << ": " << param_uint << "\n";
                break;
               
               
            case RT_BOOL:
                error = clGetDeviceInfo(deviceID,
                                        param_list[i],
                                        sizeof(cl_bool),
                                        &param_bool,
                                        NULL
                                        );

                cout << param_strings[i] << ": " << (param_bool ? "True" : "False") << "\n";
                break;
               
            case RT_PLATFORMID:
                error = clGetDeviceInfo(deviceID,
                                        param_list[i],
                                        sizeof(cl_platform_id),
                                        param_platformID,
                                        NULL
                                        );

                cout << param_strings[i] << ": " << param_platformID << "\n";
                break;
           
            case RT_SIZET:
                error = clGetDeviceInfo(deviceID,
                                        param_list[i],
                                        sizeof(size_t),
                                        &param_sizeT,
                                        NULL
                                        );

                cout << param_strings[i] << ": " << param_sizeT << "\n";
                break;
               
            case RT_SIZET_ARR:
                error = clGetDeviceInfo(deviceID,
                                        param_list[i],
                                        sizeof(size_t) * maxWorkItemDimensions,
                                        param_sizeT_array,
                                        &param_value_ret
                                        );

                cout << param_strings[i] << ": " << param_sizeT_array[0] << ", "
                    << param_sizeT_array[1] << ", "
                    << param_sizeT_array[2] << "\n";
                break;
               
               
               
            default:
                break;
        }
       
        i++;
    }
}

int main(int argc, char **argv) {
    cl_device_id deviceID;
    cl_uint numDevices;

    cl_uint err = clGetDeviceIDs(
                NULL,                  
                CL_DEVICE_TYPE_CPU,    
                MAX_DEVICE_IDS,        
                &deviceID,             
                &numDevices
                );
   
    cout << "Number of CPU devices: " << numDevices << "\n";
   
    for (int i = 0; i < numDevices; i++) {
        printDeviceInfo(deviceID);
    }

    cout << "\n\n";

   
   

    err = clGetDeviceIDs(
                NULL,
                CL_DEVICE_TYPE_GPU,
                MAX_DEVICE_IDS,
                &deviceID,
                &numDevices
                );
   
    cout << "Number of GPU devices: " << numDevices << "\n";
   
    for (int i = 0; i < numDevices; i++) {
        printDeviceInfo(deviceID);
    }
   
    cout << "\n\n";
   
}
 

(Hope that copy-and-pasted correctly.) To compile it on your Mac:

g++ test2.cpp -o test2 -framework OpenCL

Here are the results on my laptop, a 2010 Core i7 MacBook Pro 15″:

Number of CPU devices: 1
Device Name: Intel(R) Core(TM) i7 CPU       M 620  @ 2.67GHz
Vendor: Intel
Driver Version: 1.0
Device Version: OpenCL 1.0
Device Profile: FULL_PROFILE
Device Platform: 0
Device Vendor ID: 16909312
Max Compute Units: 4
Max Work Item Dimensions: 3
Max Work Item Sizes: 1, 1, 1
Max Work Group Size: 1

Number of GPU devices: 1 Device Name: GeForce GT 330M Vendor: NVIDIA Driver Version: CLH 1.0 Device Version: OpenCL 1.0 Device Profile: FULL_PROFILE Device Platform: 0 Device Vendor ID: 16918016 Max Compute Units: 6 Max Work Item Dimensions: 3 Max Work Item Sizes: 512, 512, 64 Max Work Group Size: 512

Next step: getting the GPU to do some calculations.

Tags: ,