Rendering Volumes in Maya, the Easy Way (TM)
(for no good reason at all)


Not too long ago I was looking for volume data of the human brain. I couldn't find much that was easy to work with, and one of the best data sets I could find at the time consisted of a demonstration, which you had to pay to get full access to, and a lower quality movie which ran through every slice, 'visible human' style.

Well, not considering MPEG's quality loss, I decided it would be easy enough to convert each frame in the movie into a slice in 3D space, and I also decided it would be really easy to hack together in Maya using MEL and a stack of textured planes. I whipped out a handy copy of linux's mplayer to extract each frame into a separate image, and then wrote a MEL script to apply each sequential image to its own shader and polygon plane.

I won't even get into how slow it was, but it did work:





This is the MEL script I wrote to generate the volume slices:


{

	string $file2d;
	string $lambert;
	string $intToStr;
	string $fileName;
	string $plane[];
	string $fullPlanePath[];

	string $prefix = "/home/shea/mdquad/";
	string $base = "00000000";
	string $format = ".jpg";
	
	int $slices = 32;		// number of slices to import ( starting with ($base) + 1 )
		
	float $spacing = 100;		// increase spacing to decrease gap.
	float $ambVal = 0.035;		// ambient brightness for volume
	float $alphaOffset = 0.36;	// transparency offset per slice
	
	for ($i=1; $i<$slices; $i++)
	{
		$file2d = createNode("file");
		$lambert = createNode("lambert");

		connectAttr( ($file2d+".outColor"), ($lambert+".transparency") );

		setAttr( ($file2d+".invert"), 1 );
		setAttr( ($file2d+".filterType"), 3 );

		setAttr( ($file2d+".colorOffsetR"), $alphaOffset );
		setAttr( ($file2d+".colorOffsetG"), $alphaOffset );
		setAttr( ($file2d+".colorOffsetB"), $alphaOffset );
		
		setAttr( ($lambert+".colorR"), 1 );
		setAttr( ($lambert+".colorG"), 1 );
		setAttr( ($lambert+".colorB"), 1 );

		setAttr( ($lambert+".ambientColorR"), $ambVal );
		setAttr( ($lambert+".ambientColorG"), $ambVal );
		setAttr( ($lambert+".ambientColorB"), $ambVal );


		$intToStr = string($i);
		$fileName = ( $prefix + (substring($base, 1, 8-size($intToStr)) + $intToStr + $format) );

		setAttr( "-type", "string", ($file2d+".fileTextureName"), $fileName );
				
		
		$plane = polyPlane("-sx", 1, "-sy", 1, "-ch", 0, "-n", $fileName);
		xform("-ws", "-a", "-t", 0, float($i)/$spacing, 0, $plane[0]);
		$fullPlanePath = listRelatives("-f", $plane[0]);

		inform($fileName);
		
		defaultNavigation("-source", $lambert, "-destination"
			, ($fullPlanePath[0]+".instObjGroups[0]"), "-connectToExisting");
		connectNodeToAttrOverride($lambert, ($plane[0]+".instObjGroups[0]") );		
	}


}