Sunday, September 27, 2009

Lost Gems in MAXScript - Forcing Global Scope Access

A thread on CGTalk just made me realize that there is a hidden gem in the MAXScript syntax barely anyone knows about, let alone uses. Since it is in part my fault that people don't suspect it is there and because the next update of the MAXScript documentation is quite a few months away, I feel it is a good idea to mention it here.

If you search for "Global" in the help, the corresponding topic will only have rank 22, and the page that links to it is rank 8, but I don't expect anyone to actually read it. I promise I will reorganize these topics next time around, at least the ones related to Scope of Variables, because this is the biggest source of errors and misunderstandings in the programming practice.

Some background info first:

MAXScript has a couple of peculiarities which make coding more "relaxed" (in that the rules are more relaxed for non-programmers), but as a side effect cause a lot of problems in certain situations:

*First of all, variables do not need to be declared before being used. You can use a variable name even if it was never declared or defined, and it will have the value of 'undefined'.

*Second, variables do not require an explicit scope declaration. If a variable is used in the top level context (Listener, or a script without any parentheses), it will be automatically assumed global. If a variable is used in a context below the global (inside parentheses), it is assumed local. This is unless the developer explicitly declared it as either type. For many years, I skipped the explicit scope specification because I knew what I was doing. In the last two years or so, I started forcing myself to declare each variable as explicitly global or local to make it clearer to others - if you read the source of the Krakatoa GUI, you will notice.

Now the trouble from these behaviors is this: If you have a script calling a function or using a variable which was supposed to be defined in the global scope by some other script file, if that other script happened not to be evaluated yet, your call would cause the function to create an undefined local variable instead at evaluation time. Even if the script defining the actual function would get evaluated later, the function call would still be looking at the local variable and seeing undefined, causing an error at run time like "Call needs function or class, got undefined".

Everybody with a little MAXScript knowledge knows that the solution is to pre-declare the global variables in both scripts. This way, when the script calling the function is evaluated, the call will not create a new local variable if the function does not exist yet, but will check the local and global scopes for that name, find it in the global scope and set the pointer at that memory address. When the actual function definition is evaluated, it will also find the existing global variable and will replace the undefined value with the actual function, making the first script operational and avoiding the error.

So here is the little hidden gem most people don't know about - the double-colon :: syntax.

In the topic "Specifying Global Variables As Global Using ::" linked from "MAXScript Language Improvements in 3ds Max 8", it is demonstrated that you can prefix any variable with :: and this will force it to look ONLY in the Global Scope, completely ignoring any local scopes!

In other words, whenever you intend to call a global function or access a global variable but you are not sure whether it is already defined at the moment of script evaluation, instead of pre-declaring the variable as global in the script to ensure it is "visible" to the caller, you can simply prefix it with ::!

You can see some examples I posted in this CGTalk thread: 

You might say: But Bobo, Global Variables are EVIL! Why would you use them?
The answer is that they have their positive role when defining libraries of functions, for example a single struct definition with many functions to be accessible by many other scripts. Such libraries are normally stored in an .MS file saved in the Stdplugs\Stdscripts folder or subfolders thereof. Since that folder is the first location to be auto-loaded by MAXScript at startup, these structs and functions would be visible to any other scripts launched later.

Unfortunately, if two scripts are placed in the same folder and the one defines global "library" functions the other script should access, ensuring the loading order of these scripts become tricky and usually involves fileIn() or include() calls from another script, making things quite complicated (this is a whole other topic to write about). Thus, using :: makes the problem go away and lets you call a function or access a struct you know exists or WILL exist in global scope regardless of the script files loading order!

I believe the "Specifying Global Variables As Global Using ::" topic should be merged with the "Scope of Variables" topic or at least extensively linked from all relevant topics. I apologize that this is not the case yet and hope you will find this little known feature useful!

Happy coding!

Tuesday, September 15, 2009

A Quarter Century Of Geekdom

I've got news for you - I am a geek. Chances are if you are reading this, you are in the same boat. And I just realized I am an OLD geek. That's right, it is September 2009, which means that pretty much exactly 25 years ago (+11 days) I touched a computer keyboard for the first time in my life!

The fact I still remember the exact date (September 4th 1984) is just one of the many evidences of geekiness, but since it marks the beginning of my life behind the screens, it could be presented as evidence "A". Of course, there were some other things in my early life that prepared the soil - the fact that I was very into reading (with the occasional attempts at writing) Science Fiction where computers used to live in the 70s (until the birth of the first Apple later that decade) and that I was crazy about Star Wars. I was so into it I actually wrote a rather long poem depicting everything happening in The Empire Strikes Back when I was 15 - since I know at least one Bulgarian is reading this blog, here is the link ).

In those early days behind the Iron Curtain, nobody expected a political change in our lifetime. In fact we were brainwashed to assume the status quo could never change - the Soviet Union had existed for almost 70 years and the Bulgarian anthem contained a line about how "Moscow is with us in peace and war". A nuclear holocaust appeared more probable than a political revolution. Thus the mere idea of working in the area of Hollywood visual effects at any time in the future was quite out there, and of course it never came to my mind. But the desire to do something creative including computers and futuristic space ships was quite natural and I was really very surprised when despite my best attempts to do something else with my life, I ended up doing just that... In a way, I believe that I am living the dream that I never had.

On that fateful September day of 1984, a schoolmate of mine told me about a computer club. Like everything in those days membership was completely free. All I had to do was show up at 8 in the morning and register. My friend also gave me a 4 pages introduction to computers and BASIC programming and after swallowing the whole info before going to bed, I couldn't get any sleep because my brain was trying to combine the few graphics-related commands it knew into something resembling a Zaxxon-like diagonal scrolling game. When the course started in the morning, our teacher told us about an expo with free access to computers that was going on in a big concert hall in Sofia (the expo was called TNTM, short for "Technical and Scientific Creativity of the Youth" in Bulgarian). I went to that hall and spent some of the most exciting days of my life there - I felt something big was happening in my life, but I had no idea how big.

Here is something else interesting to consider. In those days Bulgaria had a population of about 8 million, so the chances of being born Bulgarian were pretty small statistically speaking. Every country in the communist block had an industrial specialty in order to avoid duplicated efforts in multiple countries. For example the USSR was producing most of the cars and planes, while Bulgaria specialized in building forklifts and... computers. In the early 80s, a clone of the Apple 2 was "created" in Bulgaria, a couple of years later the building of PC clones started and most of them were exported. But it also meant that hardware and software were available and the education of specialists in these areas was part of the state policy. (When the Perestroika happened, around 1988 almost half of the computer viruses in the world were Bulgarian, a sad result of having too many specialists with nothing to do). What I am trying to say is that no matter what I did or where I went, computers were around me and appeared to be stalking me... Was I meant to be doing what I am doing? I think so.

So that's how it all started for me. A quarter of a century later, I still get the same excitement when I sit behind a computer, with the small difference I have a slightly better idea what I am doing.

Food for thought: Apple II used a CPU running somewhere between 1 and 2 MHz. My next computer, the Sinclair ZX Spectrum, used a 3.5 MHz CPU. 25 years later I am working on 8 cores with 2.66 GHz each. That is a really nice curve, Mr. Moore.

Monday, September 14, 2009

Remember The Good Old Days?

At least once a week we (the Krakatoa developers) google the web to see if anything new has been posted related to our favorite piece of software. On good days, we find a new creation by Matthias Müller. (If you have been living under a rock, go check out his particle work on YouTube - )
Some times I find comments related to such videos that are quite amusing. For one, people still consider one million particles a big deal. On a modern machine (I just bought one yesterday, but about that later), one million particles require about 0.6 seconds for lighting with one light and about as long to render, textured with a couple of procedural maps. Including the PFlow processing and getting the particles into memory, it still takes less than 2 seconds. The new Voxel mode is a bit slower, in the same benchmark it took slightly more than 3 seconds. Around the time Krakatoa was first released, we considered 1MP (MegaPoints!) a typical amount for quick testing. With the new Intel i7 CPUs, we are seeing ourselves forced to move to 10MP just to get rid of statistical errors.
But people still assume particle rendering requires renderfarms working on frames for days. If I may quote one comment, "It's amazing what you can do with brute force computation these days". The fact is hard disk and memory bandwidth still don't allow us to saturate 8 cores at 100% - one can get about 75% in Voxel Mode, and in Particle Mode Krakatoa is still single-threaded, drawing at nearly 2MP/second. Still, we have no plans to make it realtime, CUDA or not. The problem has never been the drawing performance, but the time it takes to get all the gigabytes of data into memory, and graphics memory is today where RAM was a couple of years ago - my card has "just" 1 GB...

So I got a new top of the line gaming machine the other day. 4 cores i7 920, shows up as 8 cores in Task Manager. My office workstation has Dual QuadCore Xeons and costs a fortune (I assume), but this new gaming box for under $2K totally kicks its behind! I had to start writing a public benchmark that could be used to compare the performance of all systems out there running Krakatoa to find out how the two compare. Before buying it, I studied all the hardware site reports about how Tri-channel memory does not bring any advantage in typical applications. Well, it is quite possible that it brings some to particle rendering - if you have not heard yet, Krakatoa is quite memory intensive! While people were telling stories about how 64 bit would not bring performance improvements or would actually cause slowdowns, Krakatoa was twice as fast in 64 bit since day one. I would love to compare my results to a similar system with dual-channel memory to see whether the CPUs have anything to do with the performance differences. Hopefully once the benchmark script is released, we will be able to provide the answer.

Apropos scripting... While reading through the Krakatoa-related talkbacks on one of the video sites, I found a comment that made me thinking. It said "Remember when Bobo was writing Maxscripts back in the day?"
I kind of remember those days. Yesterday was one of them. The big difference is now I write them as a job. MAXScript actually manages to put bread (and chocolate, and ketchup) on my table. VR Boboland really has one or two new scripts a year (although DIMaster, NextPlease and LightTouch are quite cool ones and a lot more polished than most of my earlier works). And I still try to go to CGTalk and The Area and help people out, but the days of me writing eveybody's tools for free are probably over. Still, I had not thought about this until reading that post.

Those days were good, but writing the Krakatoa GUI is quite an adventure, too...

Saturday, September 12, 2009

Here we go...with a slight delay

After 14 years online using various newsgroups, forums and VR Boboland to communicate in cyberspace, I felt it was time to finally start a blog. I have been contemplating this step for years now, but strangely enough the final push came from the movie "Julie&Julia", a quite funny comedy nobody should be allowed to see before dinner. The movie not only featured a quote from The Hitch Hiker's Guide To The Galaxy and showed that anyone (not only rats) can cook, but demonstrated how easy it is to start a blog and get hooked on it.

Some weeks ago, just before Siggraph, I tried Twitter but quickly discovered that a character limit is not something I enjoy - I quite like writing long posts. As a matter of fact, I have been using cell phones for over 10 years now but have managed to send less than 10 text messages during this period. But just give me a large keyboard and unlimited space and watch me going!

So here we go - I intend to share my thoughts on some of my favorite subjects including MAXScript, 3ds Max in Visual Effects production, Krakatoa development as well as Life, The Universe, And Everything.