<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>duber&#039;s blog</title>
	<atom:link href="http://blog.duber.cz/feed" rel="self" type="application/rss+xml" />
	<link>http://blog.duber.cz</link>
	<description>the blog of duber studio™</description>
	<lastBuildDate>Sun, 05 May 2013 19:45:54 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>dotNet iterables in MAXScript, a pain in the ass</title>
		<link>http://blog.duber.cz/3ds-max/maxscript/dotnet-iterables-in-maxscript-a-pain-in-the-ass</link>
		<comments>http://blog.duber.cz/3ds-max/maxscript/dotnet-iterables-in-maxscript-a-pain-in-the-ass#comments</comments>
		<pubDate>Sun, 05 May 2013 15:50:44 +0000</pubDate>
		<dc:creator>loocas</dc:creator>
				<category><![CDATA[dotNET]]></category>
		<category><![CDATA[maxscript]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[technical]]></category>

		<guid isPermaLink="false">http://blog.duber.cz/?p=1158</guid>
		<description><![CDATA[Yes, that is true. Stuff that should be inherently and implicitly iterable, is not, when accessed from MAXScript. I had to find out the hard way, so here I am sharing my findings and solutions so that you don&#8217;t have to waste time on this nonsense issue. The problem I bumped into some time ago [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://blog.duber.cz/wp-content/uploads/autodesk_facepalm.png" alt="Autodesk facepalm" title="Autodesk facepalm" width="560" height="50" class="alignnone size-full wp-image-1170" /></p>
<p>Yes, that is true. Stuff that should be inherently and implicitly iterable, is not, when accessed from MAXScript.</p>
<p>I had to find out the hard way, so here I am sharing my findings and solutions so that you don&#8217;t have to waste time on this nonsense issue.</p>
<p>The problem I bumped into some time ago was when I tried to access Management Object Searchers in my code (for finding various HW IDs and serial numbers). When you call a dotNET iterable (or a collection) in MAXScript, you automatically assume you can iterate over its contents, just like with an array, for example.</p>
<p><strong>WRONG!</strong></p>
<p>Somebody at Autodesk decided that this isn&#8217;t the behavior you&#8217;d like and instead made you having to jump through hoops and obstacles to get to the object contents.</p>
<p>Anyways, lets look at this problem on a rather simple example of using Hashtables in MAXScript:</p>
<p><span id="more-1158"></span></p>
<pre>hsh = dotNetObject "System.Collections.Hashtable"</pre>
<p></br>This will create a dotNET object, Hashtable, in MAXScript, so you can start adding Key:Value pairs to it. Which is the closest thing to Python&#8217;s Dictionary objects I&#8217;ve found. Very helpful.</p>
<p>Let&#8217;s add some data to the Hashtable for our demonstration purposes:</p>
<pre>hsh.Add 1 "test"
hsh.Add "foo" "bar"</pre>
<p></br>Now this data type is rather simple, it stores Key:Value pairs, so you can later call them similarly to calling array items: hsh.Item[KEY] and it will return the VALUE associated with the KEY.</p>
<pre>hsh.Item[1]
"test"</pre>
<p></br></p>
<pre>hsh.Item["foo"]
"bar"</pre>
<p></br>Brilliant!</p>
<p>But, what if you don&#8217;t know all the Keys, or you want to dump all the Values and the Keys into an array, or do something else with the data. Naturally, the first thing I wrote was:</p>
<pre>for o in hsh do print o.Key</pre>
<p></br>Well, the friendly message you receive is as follows:</p>
<pre>-- No "map" function for dotNetObject:System.Collections.Hashtable</pre>
<p></br>Which is essentially saying FUCK YOU! You cannot iterate over a collection!</p>
<p>But why? Why couldn&#8217;t I iterate over an obvious collection/iterable? I have no fucking idea!</p>
<p>So then the real question was, how the hell do I get the data out of the object if I don&#8217;t know the KEYs? How do I even get all the KEYs of the Hashtable?</p>
<p>The, not so obvious, answer was Enumeration. Simply put, you need to get an Enumerator object of the Collection and iterate on that in order to retreive the data in MAXScript. It&#8217;s cumbersome, nonintuitive and unnecessary, but that&#8217;s the only way I&#8217;ve found that works reliably.</p>
<p>In order to do just that, call the .GetEnumerator() method on the iterable object and store it in a variable. Then use that variable to &#8220;walk&#8221; through the Enumerator and get its data, like this:</p>
<pre>hshEnum = hsh.GetEnumerator()
while hshEnum.MoveNext() do print hshEnum.Key</pre>
<p></br>After running this code, you&#8217;ll get:</p>
<pre>1
"foo"</pre>
<p></br>Which you can then use later in your code to retreive the Value associated with these Keys.</p>
<p>Dumb, isn&#8217;t it? I spent hours looking on forums, searching Google and asking around to figure this out. It took me this long since in IronPython I can, naturally, iterate over collections and iterables without jumping through Enumeration hoops. Here&#8217;s the same program, except written in in IronPython:</p>
<pre>from System.Collections import Hashtable as hsh
hsh = hsh()
hsh.Add(1, "test")
hsh.Add("foo", "bar")
for o in hsh: print o.Key</pre>
<p></br>DONE! How smooth, simple, easy and intuitive is that?!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.duber.cz/3ds-max/maxscript/dotnet-iterables-in-maxscript-a-pain-in-the-ass/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Autodesk cannot write good software</title>
		<link>http://blog.duber.cz/3ds-max/autodesk-cannot-write-good-software</link>
		<comments>http://blog.duber.cz/3ds-max/autodesk-cannot-write-good-software#comments</comments>
		<pubDate>Sun, 31 Mar 2013 14:13:48 +0000</pubDate>
		<dc:creator>loocas</dc:creator>
				<category><![CDATA[3ds Max]]></category>
		<category><![CDATA[opinions]]></category>

		<guid isPermaLink="false">http://blog.duber.cz/?p=1154</guid>
		<description><![CDATA[I just realized that after seeing what Autodesk has been doing to the (at the very least) DCC software packages for a long time now. They just can&#8217;t write good software. Nothing breath taking, let alone revolutionary. Just look at it. All they sell is software they bought from really smart and bold developers in [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://blog.duber.cz/wp-content/uploads/stupid_autodesk.png" alt="stupid autodesk" title="stupid autodesk" width="560" height="60" class="alignnone size-full wp-image-1155" /></p>
<p>I just realized that after seeing what Autodesk has been doing to the (at the very least) DCC software packages for a long time now.</p>
<p>They just can&#8217;t write good software. Nothing breath taking, let alone revolutionary. Just look at it. All they sell is software they bought from really smart and bold developers in the past. Then they pretty much kept it the same way it had been, including all the bugs, quirks and issues, but slapping on fancier and fancier GUIs they also bought or licensed from someone else (Qt anyone?). They don&#8217;t have the balls, even though they pretty much have a monopoly on the DCC field. Pussies.</p>
<p>Seriously, when was the last time you were excited a new version of anything from Autodesk is coming out soon? I haven&#8217;t. Hell, I haven&#8217;t been even excited about their betas in a long while. Autodesk doesn&#8217;t listen to the users, they don&#8217;t care much about the old time power users either. They just don&#8217;t give a shit, in my opinion.</p>
<p>So, with all seriousness, I&#8217;m truly considering cancelling my subscription and just don&#8217;t give a shit back.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.duber.cz/3ds-max/autodesk-cannot-write-good-software/feed</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Repathing 3ds Max assets externally, command line utility</title>
		<link>http://blog.duber.cz/3ds-max/repathing-3ds-max-assets-externally-command-line-utility</link>
		<comments>http://blog.duber.cz/3ds-max/repathing-3ds-max-assets-externally-command-line-utility#comments</comments>
		<pubDate>Sun, 03 Mar 2013 21:30:49 +0000</pubDate>
		<dc:creator>loocas</dc:creator>
				<category><![CDATA[3ds Max]]></category>
		<category><![CDATA[software]]></category>
		<category><![CDATA[technical]]></category>

		<guid isPermaLink="false">http://blog.duber.cz/?p=1149</guid>
		<description><![CDATA[Do you remember my post about repathing 3ds Max assets in the .max and .mat files without actually running 3ds Max? Well, I cooked up a little utility that can be run from the command line without any IronPython installed. You can use this simple exe file to repath or simply just list all your [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://blog.duber.cz/wp-content/uploads/repathMaxAssets_cmd.png" alt="Repath Max Assets cmd" title="repathMaxAssets_cmd" width="560" height="302" class="alignnone size-full wp-image-1150" /></p>
<p>Do you remember <a href="http://blog.duber.cz/3ds-max/repathing-your-assets-in-max-files-without-3ds-max">my post about repathing 3ds Max assets</a> in the .max and .mat files without actually running 3ds Max? Well, I cooked up a little utility that can be run from the command line without any IronPython installed. You can use this simple exe file to repath or simply just list all your external asset paths inside your .max and .mat files, should you need to. And since it&#8217;s a command line utility you can run it from within your programs and catch the outputs or batch feed it data for processing etc&#8230;</p>
<p>Anyways, the syntax is pretty simple:</p>
<p>You need to call the program and then pass it a .max or .mat scene file. If you provide only that, it&#8217;ll list the file&#8217;s asset paths. But if you provide a <strong>-p</strong> parameter followed by a new path, it&#8217;ll re-path all the file&#8217;s external assets to the new location you provided. Unfortunately, there is no way for me (afaik) to distinguish what is an actual render output or RE output and what are texture or cache data inputs, so everything will be linked to the new directory at once.</p>
<p>Should you need any help, just call the program without any parameters, or with the parameter <strong>-h</strong> for help.</p>
<p><a href="http://blog.duber.cz/wp-content/downloads/repathMaxAssets_v02.zip">Download the program from here</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.duber.cz/3ds-max/repathing-3ds-max-assets-externally-command-line-utility/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Render Max scenes shortcut</title>
		<link>http://blog.duber.cz/3ds-max/render-max-scenes-shortcut</link>
		<comments>http://blog.duber.cz/3ds-max/render-max-scenes-shortcut#comments</comments>
		<pubDate>Wed, 27 Feb 2013 18:32:18 +0000</pubDate>
		<dc:creator>loocas</dc:creator>
				<category><![CDATA[3ds Max]]></category>
		<category><![CDATA[technical]]></category>

		<guid isPermaLink="false">http://blog.duber.cz/?p=1143</guid>
		<description><![CDATA[Another one of those little things that can save up a ton of time in day to day productions. I&#8217;ve added a simple &#8220;render with 3ds Max&#8221; shortcut to my right-click menu, so that I don&#8217;t have to open up Max if I need to render a scene. This actually came in handy on the [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.duber.cz/wp-content/uploads/render_with_max_shortcut.png" rel="lightbox[1143]"><img src="http://blog.duber.cz/wp-content/uploads/render_with_max_shortcut.png" alt="Render with Max Shortcut" title="render_with_max_shortcut" width="560" height="200" class="alignnone size-full wp-image-1146" /></a></p>
<p>Another one of those little things that can save up a ton of time in day to day productions.</p>
<p>I&#8217;ve added a simple &#8220;render with 3ds Max&#8221; shortcut to my right-click menu, so that I don&#8217;t have to open up Max if I need to render a scene. This actually came in handy on the current project where I was modifying a few scenes and re-saving them. Then I went through a few of them manually and needed to render them out quickly for reference. No need to actually run Max, open the scene, hit F9&#8230; it was all setup, I just needed to render them out.</p>
<p>If you want to modify your right-click menu this same way, just modify this registry key (3ds Max 2013 in this case):
<pre>Windows Registry Editor Version 5.00

[HKEY_CLASSES_ROOT\3dsmax\Shell\Render]
@="Render with 3ds Max 2013"

[HKEY_CLASSES_ROOT\3dsmax\Shell\Render\Command]
@="\"C:\\Program Files\\Autodesk\\3ds Max 2013\\3dsmaxcmd.exe\" \"%1\""</pre>
<p>Done. <img src='http://blog.duber.cz/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://blog.duber.cz/3ds-max/render-max-scenes-shortcut/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>VFX solidarity</title>
		<link>http://blog.duber.cz/misc/vfx-solidarity</link>
		<comments>http://blog.duber.cz/misc/vfx-solidarity#comments</comments>
		<pubDate>Mon, 25 Feb 2013 21:35:16 +0000</pubDate>
		<dc:creator>loocas</dc:creator>
				<category><![CDATA[miscellaneous]]></category>
		<category><![CDATA[opinions]]></category>

		<guid isPermaLink="false">http://blog.duber.cz/?p=1139</guid>
		<description><![CDATA[There would be no fun without VFX!]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.duber.cz/wp-content/uploads/green_blue_screens.png" rel="lightbox[1139]"><img src="http://blog.duber.cz/wp-content/uploads/green_blue_screens.png" alt="Green and Blue Screens" title="green_blue_screens" width="560" height="300" class="alignnone size-full wp-image-1140" /></a></p>
<p>There would be no fun without VFX!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.duber.cz/misc/vfx-solidarity/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Shotgun is $49 bucks per month!</title>
		<link>http://blog.duber.cz/misc/shotgun-is-49-bucks-per-month</link>
		<comments>http://blog.duber.cz/misc/shotgun-is-49-bucks-per-month#comments</comments>
		<pubDate>Thu, 21 Feb 2013 11:20:07 +0000</pubDate>
		<dc:creator>loocas</dc:creator>
				<category><![CDATA[miscellaneous]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[software]]></category>

		<guid isPermaLink="false">http://blog.duber.cz/?p=1131</guid>
		<description><![CDATA[I was shocked and very pleased to hear that Shotgun Software decided to unify their pricing and bring it down to $49 USD per month per user with the API! How awesome is that?! That brings me to a thought of actually releasing our duberPython plugin for a ridiculously low price so that EVERYONE can [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.duber.cz/wp-content/uploads/shotgun_new_price_banner.png" rel="lightbox[1131]"><img src="http://blog.duber.cz/wp-content/uploads/shotgun_new_price_banner.png" alt="Shotgun new price banner" title="Shotgun banner" width="560" height="210" class="alignnone size-full wp-image-1133" /></a></p>
<p>I was shocked and very pleased to hear that Shotgun Software decided to unify their pricing and bring it down to $49 USD per month per user with the API! How awesome is that?!</p>
<p>That brings me to a thought of actually releasing our duberPython plugin for a ridiculously low price so that EVERYONE can use Shotgun and our Python module in their pipeline!</p>
<p>Let me know what you think, guys and I&#8217;ll prep the installations in the meantime.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.duber.cz/misc/shotgun-is-49-bucks-per-month/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Relighting workflow in Nuke 7 for 3ds Max users</title>
		<link>http://blog.duber.cz/3ds-max/relighting-workflow-in-nuke-7-for-3ds-max-users</link>
		<comments>http://blog.duber.cz/3ds-max/relighting-workflow-in-nuke-7-for-3ds-max-users#comments</comments>
		<pubDate>Mon, 10 Dec 2012 15:49:16 +0000</pubDate>
		<dc:creator>loocas</dc:creator>
				<category><![CDATA[3ds Max]]></category>
		<category><![CDATA[Nuke]]></category>
		<category><![CDATA[technical]]></category>

		<guid isPermaLink="false">http://blog.duber.cz/?p=1119</guid>
		<description><![CDATA[As you may know, Nuke 7 is out and one of its very exciting features are the new re-lighting tools. However, I&#8217;ve bumped into a bit of a problem. Since I&#8217;m primarily a 3ds Max user, all my world render passes are Z-up oriented. This is a bit of an issue, since Nuke is, more [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.duber.cz/wp-content/uploads/nuke_7_matrix.jpg" rel="lightbox[1119]"><img src="http://blog.duber.cz/wp-content/uploads/nuke_7_matrix.thumbnail.png" alt="Nuke 7 Relighting Workflow" title="Nuke 7 Relighting Workflow" width="560" height="264" class="alignnone size-thumbnail wp-image-1122" /></a></p>
<p>As you may know, Nuke 7 is out and one of its very exciting features are the new re-lighting tools.</p>
<p>However, I&#8217;ve bumped into a bit of a problem. Since I&#8217;m primarily a 3ds Max user, all my world render passes are Z-up oriented. This is a bit of an issue, since Nuke is, more commonly, Y-up oriented.</p>
<p>Fret not! There is a rather simple solution. The ColorMatrix node, nobody seems to care about. <img src='http://blog.duber.cz/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> All you need to know, if you&#8217;re not much into math and shit, is that in order to properly convert the RGB values representing the XYZ space coordinates in Max into Nuke&#8217;s world space, just type in these values:</p>
<ul>
<li>In the first row, type in: 1,0,0</li>
<li>In the second row, type in: 0,0,1</li>
<li>In the third row, type in: 0,-1,0</li>
</ul>
<p>Or just look at the picture above. <img src='http://blog.duber.cz/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>Done! This is all you need in order to start re-lighting your renders in Nuke using 3ds Max&#8217;s World Point passes.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.duber.cz/3ds-max/relighting-workflow-in-nuke-7-for-3ds-max-users/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Lack of updates</title>
		<link>http://blog.duber.cz/misc/lack-of-updates-2</link>
		<comments>http://blog.duber.cz/misc/lack-of-updates-2#comments</comments>
		<pubDate>Tue, 27 Nov 2012 22:15:18 +0000</pubDate>
		<dc:creator>loocas</dc:creator>
				<category><![CDATA[miscellaneous]]></category>

		<guid isPermaLink="false">http://blog.duber.cz/?p=1113</guid>
		<description><![CDATA[I&#8217;ve been extremely busy recently, thus the updates on this blog have been, well, nonexistent. I promise I&#8217;ll write about some really fucking exciting shit (oh yeah: Max, Mari, Nuke&#8230;) pretty soon, but I&#8217;ll have to deliver two more TVCs this and early next month. So, possibly right after that. Stay tuned, you won&#8217;t be [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been extremely busy recently, thus the updates on this blog have been, well, nonexistent. <img src='http://blog.duber.cz/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>I promise I&#8217;ll write about some really fucking exciting shit (oh yeah: Max, Mari, Nuke&#8230;) pretty soon, but I&#8217;ll have to deliver two more TVCs this and early next month. So, possibly right after that.</p>
<p>Stay tuned, you won&#8217;t be dissappointed, I promise. <img src='http://blog.duber.cz/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> Cheers&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.duber.cz/misc/lack-of-updates-2/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>RV Explorer integration script updated</title>
		<link>http://blog.duber.cz/misc/rv-explorer-integration-script-updated</link>
		<comments>http://blog.duber.cz/misc/rv-explorer-integration-script-updated#comments</comments>
		<pubDate>Tue, 27 Nov 2012 22:10:54 +0000</pubDate>
		<dc:creator>loocas</dc:creator>
				<category><![CDATA[miscellaneous]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[RV]]></category>
		<category><![CDATA[software]]></category>
		<category><![CDATA[technical]]></category>

		<guid isPermaLink="false">http://blog.duber.cz/?p=1109</guid>
		<description><![CDATA[Just a shout out to those who downloaded my RV Explorer integration Python script. I&#8217;ve updated it so that RV now accepts file sequences with various leading zero lengths as I bumped into this issue myself recently. Hope I haven&#8217;t caused you too much trouble. Here&#8217;s the updated script: v0.3]]></description>
			<content:encoded><![CDATA[<p><img src="" /></p>
<p>Just a shout out to those who downloaded my RV Explorer integration Python script.</p>
<p>I&#8217;ve updated it so that RV now accepts file sequences with various leading zero lengths as I bumped into this issue myself recently.</p>
<p>Hope I haven&#8217;t caused you too much trouble. <img src='http://blog.duber.cz/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p><a href="http://blog.duber.cz/wp-content/downloads/loadFileSequenceInRV.py">Here&#8217;s the updated script: v0.3</a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.duber.cz/misc/rv-explorer-integration-script-updated/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
<enclosure url="http://blog.duber.cz/wp-content/gallery/vids/load_in_rv_final.mp4" length="79881031" type="video/mp4" />
		</item>
		<item>
		<title>Repathing your assets in .max files without 3ds Max</title>
		<link>http://blog.duber.cz/3ds-max/repathing-your-assets-in-max-files-without-3ds-max</link>
		<comments>http://blog.duber.cz/3ds-max/repathing-your-assets-in-max-files-without-3ds-max#comments</comments>
		<pubDate>Fri, 03 Aug 2012 16:17:28 +0000</pubDate>
		<dc:creator>loocas</dc:creator>
				<category><![CDATA[3ds Max]]></category>
		<category><![CDATA[dotNET]]></category>
		<category><![CDATA[maxscript]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[technical]]></category>

		<guid isPermaLink="false">http://blog.duber.cz/?p=1078</guid>
		<description><![CDATA[Ever since I read this blog post on the Area, I was intrigued to get this working in an IronPython environment (that&#8217;s pretty much all I know, in the &#8220;serious programming&#8221; area). Unfortunately for me, the article mentions C++, OLE and COM. Which are my least favourite technical subjects. So, now when I finally really [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://blog.duber.cz/wp-content/uploads/asset_tracking.png" alt="Asset Tracking" title="Asset Tracking" width="560" height="360" class="alignnone size-full wp-image-1094" /></p>
<p>Ever since I read <a href="http://area.autodesk.com/blogs/chris/reading_and_modifying_asset_file_paths_in_the_3ds_max_file">this blog post on the Area</a>, I was intrigued to get this working in an IronPython environment (that&#8217;s pretty much all I know, in the &#8220;serious programming&#8221; area). Unfortunately for me, the article mentions C++, OLE and COM. Which are my least favourite technical subjects.</p>
<p>So, now when I finally really needed this solution (more on that some time later), I had to ask on the Autodesk forums.</p>
<p>Luckily I got an answer. But first off, huge thank you goes to <strong>Larry Minton</strong>, an Autodesk Engineer, without whom I wouldn&#8217;t have been able to get this thing going.</p>
<p>Now, about the problem. If your facility has a render farm and you happen to work off of your local storage, you have to point your assets to a UNC path where they&#8217;re stored so that all the machines on the network can find and load them when rendering. There are many ways of doing this and usually your pipeline TDs had figured this one out prior you even starting any work on the project. <img src='http://blog.duber.cz/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> Unfortunately for me, I&#8217;m the only pipeline TD here. <img src='http://blog.duber.cz/wp-includes/images/smilies/icon_biggrin.gif' alt=':D' class='wp-smiley' /> So I had to figure out a way of re-pathing my assets in 3ds Max scene files prior to rendering.<br />
<span id="more-1078"></span><br />
Up until now I&#8217;ve been dealing with this via MAXScript and Deadline. I wrote a handy dandy PostLoad script that gets executed right after a Max scene file gets loaded up, then the renderer fires off and renders correctly. This has worked flawlessly for me and probably will work forever. However, you always have to supply this script along every submitted file. So, this gets a little more problematic with more complex PostLoad scripts that you also need to run occassionally for specific jobs/shots.</p>
<p>Then, not very long ago, I bumped into these two commands in MAXScript:
<pre>getMAXFileAssetMetadata &lt;filename&gt;</pre>
<p>and</br>
<pre>setMAXFileAssetMetadata &lt;filename&gt; &lt;array of AssetMetadata_StructDef instances&gt;</pre>
<p></br>These commands will allow you to source a special stream of data off of a given .max file and will allow you to overwrite it with whatever you supply the methods with. This is a perfect solution for a situation where you have to batch modify a ton of .max files in order to prepare them for the network rendering. Unfortunately, though, you have to have 3ds Max running in order to perform MAXScript operations. This is a bit prohibiting on a server side, where you usually don&#8217;t have a 3ds Max license available or you don&#8217;t want to use up a single seat of floating licenses.</p>
<p>Then there is the OLE stream. It has been possible, since 3ds Max 2010, to get such data out of the .max files without running 3ds Max and thus without needing a single license of Max to perform such pipeline tasks. It isn&#8217;t as trivial as the MAXScript approach, though, but definitely doable.</p>
<p>The problem with .NET languages, though, is that this was designed more for C++, than C# or even IronPython, or Python for that matter. But, luckily, there is a library, <a href="http://sourceforge.net/projects/openmcdf/">OpenMCDF</a>, that allows you to manipulate OLE data streams in files. It is very simple to use the OpenMCDF objects and methods and works perfectly fine under IronPython (which is my case of using it). And so, the last piece of puzzle was to figure out how to access the meta data asset stream and, mainly, how to modify it &#8211; effectively re-pathing the assets outside of 3ds Max.</p>
<p>First of all, download and unpack the <a href="http://sourceforge.net/projects/openmcdf/">OpenMCDF</a> assembly into the IronPython\DLLs folder. </p>
<p>Now, in IronPython, in order to get to the data stream, you have to Compound the .max file using the OpenMcdf.CompoundFile() method. If you want to modify it, supply a UpdateMode parameter and a couple of boolean variables denoting whether you want to recycle sectors and or erase free sectors.
<pre>from OpenMcdf import *
cFile = CompoundFile(r"pathToMaxFile.max")</pre>
<p></br>You then have to access the RootStorage and its streams. This gets a little tricky. I had to look this up in the C++ SDK (kindly provided by Larry). The stream name you&#8217;re looking for is called <em>FileAssetMetaData2</em>, so with this in mind:
<pre>theStream = cFile.RootStorage.GetStream("FileAssetMetaData2")
buffer = theStream.GetData()</pre>
<p></br>Now here it becomes a little cumbersome for high-level programmers like myself. Essentially, what we get is an array object full of Byte objects carrying data, like so:
<pre>Array[Byte]((&lt;System.Byte object at 0x00000000000023BF [92]&gt;,
&lt;System.Byte object at 0x00000000000023C0 [108]&gt;,
&lt;System.Byte object at 0x00000000000023C1 [59]&gt;))</pre>
<p></br>Let&#8217;s take a look at the MAXScript output, to put things into perspective. If you run this command:
<pre>getMAXFileAssetMetadata @"pathToMaxFile.max"</pre>
<p> you get something like this:
<pre>#((AssetMetadata_StructDef assetId:"{923B6C5C-1ACC-48D7-A879-FF472DC61589}"
filename:"D:\_SOME_PATH_\TEST\BEAUTY.exr" type:#bitmap))</pre>
<p></br>It&#8217;s an array of AssetMetadata_StructDef objects. More importantly, the data it contains is: asset ID, what type of an asset it is and the file path, which is what we&#8217;re interested in modifying. The ID and type is not to be played with! You can get pretty nasty Max crashes if you do something wrong with these. Believe me. <img src='http://blog.duber.cz/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>Now that we know what data we&#8217;re looking for, we need to make some order out of the Byte array we received from the stream. To make things even more complicated, the Byte array contains not only the data we want, but also some descriptors (not really the best name, but at least that&#8217;s what I think of them). The descriptors tell you how long the next Byte stream is in order to retreive correct data. Here&#8217;s how the data is structured in the stream in order to make something out of it (again, huge thanks go to Larry for this):</p>
<ul>
<li>16 Bytes &#8211; the AssetID (don&#8217;t modify this!)</li>
<li>4 Bytes &#8211; the length of the next Byte stream that contains the Asset Type name</li>
<li>(len+1)*2 Bytes &#8211; the amount of Bytes you need to read in order to retreive the Asset Type name (UTF-16)</li>
<li>4 Bytes &#8211; the length of the next Byte stream that contains the Asset file path string</li>
<li>(len+1)*2 Bytes &#8211; the amount of Bytes you need to read in order to retreive the Asset file path string (UTF-16)</li>
</ul>
<p>So, that&#8217;s basically it. This recipe loops for as long as there are available Bytes in the stream. This, of course, means that if you want to change the file path string, you will have to update the preceding 4 Bytes denoting the file path string&#8217;s length, which is a pain in the ass, if you ask me.</p>
<p>I&#8217;ve figured out a pretty dirty workaround, which I&#8217;m presenting here. I&#8217;ll present a way of reading the file paths, so that you can use them in your asset management or production management software, for example.</p>
<p>The process is as follows:</p>
<ol>
<li>Get the buffer Byte Array object</li>
<li>Decode it using the UTF-16 table into a unicode string</li>
<li>Split the string by using a special <em>&#8220;\x00&#8243;</em> delimiter character</li>
<li>The resulting list object stores all the data you need in a human-readable form (well, that applies only to the file path string and the asset type string)</li>
<li>Filter out only every fourth item in the list, which is the asset file path</li>
</ol>
<p>Unfortunately, there is no way (none that I know of) to tell what is the asset file path associated with. All you know is whether it is a Bitmap, or a Cache etc&#8230; but there is no way to tell whether it is a render element save file path, or an actual texture path etc.</p>
<p>But still, for repathing purposes, it&#8217;s all you need! Here&#8217;s the IronPython code showing the above process in action:
<pre>from System.Text import Encoding
assetFilePaths = (Encoding.Unicode.GetString(buffer)).split("\x00")[3::4]</pre>
<p></br>That&#8217;s it! The resulting list contains all the Asset file path strings that are contained in the .max file you sourced. With a bit of imagination and some more programming, you can start re-pathing the file paths using these methods. Also make sure to read the OpenMCDF documentation for all the available methods and object properties.</p>
<p><img src="" /></p>
<p>I&#8217;ll post my scripts here as soon as they&#8217;re polished and thoroughly tested. However, I&#8217;m very thrilled to finally have a way of modifying asset paths in my .max files without having to run Max first, it&#8217;s such a time saver and it&#8217;s very helpful in a modern pipeline.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.duber.cz/3ds-max/repathing-your-assets-in-max-files-without-3ds-max/feed</wfw:commentRss>
		<slash:comments>14</slash:comments>
<enclosure url="http://blog.duber.cz/wp-content/gallery/vids/repathing_assets.mp4" length="5932907" type="video/mp4" />
		</item>
	</channel>
</rss>
