LlSculpt mel/sculpt.mel

// * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
// * $License$
global proc string llFirst(string $list[])
{
	return $list[0];
}
global proc llSculptExport(string $object, string $file_name, string $file_format,
						 int $resolution_x, int $resolution_y,
						 int $maximize_scale, int $fix_orientation, int $flip_horizontal)
						 
{
	// copy it, because we're going to mutilate it. MUHAHAHAAAaa...
	string $object_copy = llFirst(duplicate($object));
	// disentangle from groups
	string $parents[] = listRelatives("-parent", $object_copy);
	if (size($parents) != 0)
		$object_copy = llFirst(parent("-world", $object_copy));
	// scale it to unit cube
	float $bounding_min[3];
	float $bounding_max[3];
	$bounding_min = getAttr($object_copy + ".boundingBoxMin");
	$bounding_max = getAttr($object_copy + ".boundingBoxMax");
	float $scale[3];
	int $i;
	for ($i = 0; $i < 3; $i++)
		$scale[$i] = $bounding_max[$i] - $bounding_min[$i];
	float $scale_max = 0;
	for ($i = 0; $i < 3; $i++)
		if ($scale[$i] > $scale_max)
			$scale_max = $scale[$i];
	if ($maximize_scale)
	{
		print($object + " scale normalized - scale by " +
			 $scale[0] + " " + $scale[1] + " " + $scale[2] + " inside SL to get original shape\n");
	}
	else
	{
		for ($i = 0; $i < 3; $i++)
			$scale[$i] = $scale_max;
	}
	
	scale("-relative", 1/$scale[0], 1/$scale[1], 1/$scale[2], $object_copy);
	// position it in unit cube
	$bounding_min = getAttr($object_copy + ".boundingBoxMin");
	$bounding_max = getAttr($object_copy + ".boundingBoxMax");
	
	float $center[3];
	for ($i = 0; $i < 3; $i++)
		$center[$i] = ($bounding_min[$i] + $bounding_max[$i]) / 2.0;
	move("-relative", 0.5 - $center[0], 0.5 - $center[1], 0.5 - $center[2], $object_copy);
	//
	// nurbs surfaces can be adjusted to ensure correct orientation
	//
	if ($fix_orientation)
	{
		string $shape = llFirst(listRelatives("-shapes", $object_copy));
		if ((nodeType($object_copy) == "nurbsSurface") ||
			(($shape != "") && (nodeType($shape) == "nurbsSurface")))
		{
			// try to determine the "north pole";
			float $pole[] = pointOnSurface("-turnOnPercentage", 1,
										 "-parameterU", 0.5,
										 "-parameterV", 0,
										 $object_copy);
			float $total_distance = 0;
			float $v;
			for ($v = 0; $v <= 1; $v += 0.1)
			{
				float $point[] = pointOnSurface("-turnOnPercentage", 1,
												"-parameterU", $v,
												"-parameterV", 0,
												$object_copy);
				float $distance = 0;
				int $i;
				for ($i = 0; $i < 3; $i++)
					$distance += pow($pole[$i] - $point[$i], 2);
				$distance = sqrt($distance);
				$total_distance += $distance;
			}
			if ($total_distance > 0.1) // the points don't converge on the pole - swap
			{
				print("swapping UVs to orient poles for " + $object + "\n");
				reverseSurface("-direction", 3, $object_copy);
			}
			// now try to ensure the normal points "out"
			// note: this could easily fail - but there's no better way (i think.)
			float $total_orientation = 0;
			float $u;
			for ($u = 0; $u <= 1; $u += 0.1)
				for ($v = 0; $v <= 1; $v += 0.1)
				{
					float $point[] = pointOnSurface("-turnOnPercentage", 1,
													"-parameterU", $u,
													"-parameterV", $v,
													$object_copy);
			
					float $normal[] = pointOnSurface("-normal",
													 "-turnOnPercentage", 1,
													 "-parameterU", $u,
													 "-parameterV", $v,
													 $object_copy);
					// check the orientation of the normal w/r/t the direction from center
					float $center_dir[];
					for ($i = 0; $i < 3; $i++)
						$center_dir[$i] = $point[$i] - 0.5;
					float $orientation = 0; // dot product
					for ($i = 0; $i < 3; $i++)
						$orientation += $center_dir[$i] * $normal[$i];
					$total_orientation += $orientation;
				}
			if ($total_orientation > 0) // need to invert
			{
				print("reversing V for " + $object + "\n");
				reverseSurface("-direction", 1, $object_copy);
			}
			if ($flip_horizontal)
			{
			// reverse U, for compatibility with surface textures
			print("reversing U for " + $object + "\n");
			reverseSurface("-direction", 0, $object_copy);
			}
		}
		
		else
		{
			warning("cannot fix orientation on non-nurbs object: " + $object);
		}
	}
	
	// create temporary shading network
	string $sampler_info = createNode("samplerInfo");
	print("exporting sculpt map for " + $object + " into file " + $file_name + "\n");
	
	// bake sculpt texture
	string $fileNodes[] = convertSolidTx("-fileImageName", $file_name,
										 "-fileFormat", $file_format,
										 "-force", 1,
										 "-resolutionX", $resolution_x,
										 "-resolutionY", $resolution_y,
										 $sampler_info + ".pointWorld",
										 $object_copy);
	delete($fileNodes); // we don't want 'em. why do you make 'em?
	delete($sampler_info);
	delete($object_copy);
}
global proc int llSculptEditorCallback()
{
	string $objects[] = ls("-sl");
	if (size($objects) == 0)
	{
		warning("please select objects to export");
		return 0;
	}
	
	string $filename = textFieldButtonGrp("-query", "-fileName", "llSculptEditorFilename");
	int $resolution_x = intSliderGrp("-query", "-value", "llSculptEditorResolutionX");
	int $resolution_y = intSliderGrp("-query", "-value", "llSculptEditorResolutionY");
	int $fix_orientation = checkBoxGrp("-query", "-value1", "llSculptEditorFixOrientation");
	int $flip_horizontal = checkBoxGrp("-query", "-value1", "llSculptEditorFlipHorizontal");
	int $maximize_scale = checkBoxGrp("-query", "-value1", "llSculptEditorMaximizeScale");
	// get filetype
	string $file_type;
	string $file_base;
	string $file_extension;
	
	string $tokens[];
	tokenize($filename, ".", $tokens);
	if (size($tokens) == 1) // no extension, default to bmp
	{
		$file_base = $filename;
		$file_type = "bmp";
		$file_extension = "bmp";
	}
	else
	{
		$file_extension = $tokens[size($tokens) - 1];
		int $i;
		for ($i = 0; $i < size($tokens) - 1; $i++)
		{
			$file_base += $tokens[$i];
			if ($i != size($tokens) - 2)
				$file_base += ".";
		}
		if ($file_extension == "bmp")
			$file_type = "bmp";
		else if (($file_extension == "jpg") || ($file_extension == "jpeg"))
			$file_type = "jpg";
		else if (($file_extension == "tif") || ($file_extension == "tiff"))
			$file_type = "tif";
		else if ($file_extension == "tga")
			$file_type = "tga";
		else
		{
			warning("unknown image type (" + $file_extension + "). switching to bmp");
			$file_type = "bmp";
			$file_extension = "bmp";
		}
	}
	string $object;
	for ($object in $objects)
	{
		string $this_filename = $file_base;
		if (size($objects) > 1)
			$this_filename += "-" + $object;
		$this_filename += "." + $file_extension;
		llSculptExport($object, $this_filename, $file_type, $resolution_x, $resolution_y,
					 $maximize_scale, $fix_orientation, $flip_horizontal);
	}
	
	select($objects);
	
	return 1;
}
global proc llSculptEditorSetFilenameCallback(string $filename, string $filetype)
{
	textFieldButtonGrp("-edit", "-fileName", $filename, "llSculptEditorFilename");
}
global proc llSculptEditorBrowseCallback()
{
	fileBrowser("llSculptEditorSetFilenameCallback", "Export", "image", 1);
}
global proc llSculptEditor()
{
	string $commandName = "llSculptExport";
	string $layout = getOptionBox();
	setParent $layout;
	setOptionBoxCommandName($commandName);
	setUITemplate -pushTemplate DefaultTemplate;
	scrollLayout;
	tabLayout -tabsVisible 0 -scrollable 0;
	string $parent = `columnLayout -adjustableColumn 1`;
	separator -height 10 -style "none";
	textFieldButtonGrp
		-label "Filename"
		-fileName "sculpt.bmp"
		-buttonLabel "Browse"
		-buttonCommand "llSculptEditorBrowseCallback"
		llSculptEditorFilename;
	intSliderGrp
		-field on
		-label "X Resolution"
		-minValue 1
		-maxValue 512
		-fieldMinValue 1
		-fieldMaxValue 4096
		-value 64
		llSculptEditorResolutionX;
	intSliderGrp
		-field on
		-label "Y Resolution"
		-minValue 1
		-maxValue 512
		-fieldMinValue 1
		-fieldMaxValue 4096
		-value 64
		llSculptEditorResolutionY;
	checkBoxGrp
		-label ""
		-label1 "Maximize scale"
		-numberOfCheckBoxes 1
		-value1 off
		llSculptEditorMaximizeScale;
	checkBoxGrp
		-label ""
		-label1 "Flip Horizontal"
		-numberOfCheckBoxes 1
		-value1 on
		llSculptEditorFlipHorizontal;
	checkBoxGrp
		-label ""
		-label1 "Correct orientation"
		-numberOfCheckBoxes 1
		-value1 on
		llSculptEditorFixOrientation;
	setUITemplate -popTemplate;
	string $applyBtn = getOptionBoxApplyBtn();
	button -edit
		-label "Export"
		-command "llSculptEditorCallback"
		$applyBtn;
	string $applyAndCloseBtn = getOptionBoxApplyAndCloseBtn();
	button -edit
		-label "Export and Close"
		-command "llSculptEditorCallback"
	$applyAndCloseBtn;
	setOptionBoxTitle("Export Sculpt Texture");
	setOptionBoxHelpTag( "ConvertFileText" );
	showOptionBox();
}
//
llSculptEditor;