|
|
(5 intermediate revisions by 2 users not shown) |
Line 1: |
Line 1: |
| <blockquote> <pre>
| | [http://wiki.secondlife.com/w/index.php?action=raw&ctype=text/javascript&dontcountme=s&title=LlSculpt_mel/sculpt.mel View source to llSculpt.mel] |
|
| |
|
| // * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
| | Added a button to flip the map horizontally. It is check by default, but it should keep people from having to use photoshop to flip it if it gets inverted. --Delerium Hannibal |
| // * $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)
| |
|
| |
| {
| |
| // 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);
| |
| }
| |
| }
| |
|
| |
| 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 $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);
| |
| }
| |
| | |
|
| |
| 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 1;
| |
| | |
| 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 "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;
| |
| | |
| | |
| </pre></blockquote>
| |