Welcome to the Second Life Forums Archive

These forums are CLOSED. Please visit the new forums HERE

A solution to maya export glitches for sculpties

Mark Busch
DarkLife Developer
Join date: 8 Apr 2003
Posts: 442
09-27-2007 08:56
When exporting models from Maya using the scripts from here (http://www.qarl.com/qLab/?p=49) we noticed some glitches where the textures were not correct, and we also got some problems with the model being incorrect.
(We're talking about a full import of a model with lots of prims here)

Here are some solutions that we used.

Here's a list of what you should do first:

-ungroup your model, it should NOT be in a group
-select everything, then do delete history, freeze transformations and finally reset transformation
-When entering a filename for export, DO NOT use a space anywhere, this will mess up the commands in the SL scripts. Just use like 'mymodel.bmp' or something like that.
-The 'generate primscript' might not be visible on windows machines, use the script at the bottom to fix that too (it also fixes the textures, if you perform the steps below)

Now there is only one thing that can be wrong with your model (besides the textures): it can be too big. This will cause the SL script to try to resize the prim above 10x10x10 which is impossible and makes your model incorrect. One way to find out if it's too big (a good way) is to look at the generated primscript. Look at all lines that look like this:

"transform -setScale 1.662504852 1.744021187 1.548922199 -gotoRelativePos 0.9232675418 6.276043322 0.2445074933 -deleteScript "

The first 3 numbers tell the scale of each prim. They should never be greater then 10!
If this is the case, make your model smaller, AND DON'T FORGET to do freeze+reset transformations.

Now this should fix all model problems.

Now the texture problem:

The problem is that sometimes the texture is not rotated correctly. This is because the 'fix orientation' (which you should check) sometimes rotates and flips the surface image (scultp texture), but it does not rotate or flip the texture that belongs to it.

I wasn't able to fix this problem in the maya script itself so I made a work around.

-Install ImageMagick (for windows http://www.imagemagick.org/script/binary-releases.php#windows)
-create the directory c:\output (sorry it's a hack, so now it ALWAYS outputs to c:\output, change it if you know a little MEL)
-Restart maya (or else it will use the incorrect 'convert.exe' possibly)
-Use the altered script at the bottom of this post as your maya export script.
-when you enter the 'filename' in the maya-script-windows, DON'T use a complete path, just enter like 'mymodel.bmp'

This script will call imagemagic to rotate the textures when needed. All textures and the primscript will now be exported to c:\output (so don't forget to create that directory)

So far this has worked for all our models. Sometimes there are one two prims that did not get proper orientation (it's inside out, or something else is wrong). If so rotate the texture + sculpt texture 90 degrees to the right (or something like that) and manually set it again for those prims.

Hope this helps you!

P.S. to check if the script is rotating+flipping correct, look at the output from the script. When it rotates or flips it should say stuff like "Swapping texture" without any errors.
P.P.S. The great guy who wrote the export script told me he'd probably release a new version sometimes to fix all these problems in a better way.
P.P.S. for big models, you pay 20 L$ per prim (so a model with 50 prims will cost 200 L$). It is very much advised that you first try it on the beta grid to see if everything is OK, and only upload to the main grid when you have no further problems... but you probably figured this out already ;)

From: someone
// * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
// * $License$

global string $llPrimScript;

global proc string llFirst(string $list[])
{
return $list[0];
}


global proc string llGetShadingGroup(string $object)
{
string $allNodes[] = (`listHistory -f true $object` );
string $node = "";
for ($node in $allNodes)
{
if(`nodeType $node` == "shadingEngine";)
{
return $node;
}
}

return "";
}



global proc llSculptExport(string $object,
string $file_name, string $file_extension, string $file_format,
int $resolution_x, int $resolution_y,
int $maximize_scale, int $fix_orientation,
int $surface_bake, int $surface_resolution_x, int $surface_resolution_y, int $surface_shadows,
int $generate_primscript)

{

chdir("c:\\output";);
// 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];
if ($scale[$i] < 0.00001)
$scale[$i] = 1;
}

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
//
int $flipped=false;
int $swapped=false;
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);
$swapped=true;
}

// 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";);
$flipped=true;
reverseSurface("-direction", 1, $object_copy);
}

}

else
{
warning("cannot fix orientation on non-nurbs object: " + $object);
}


}

// create temporary shading network
string $sampler_info = createNode("samplerInfo";);

string $full_file_name = $file_name + "." + $file_extension;

print("exporting sculpt map for " + $object + " into file " + $full_file_name + "\n";);

// bake sculpt texture
string $fileNodes[] = convertSolidTx("-fileImageName", "c:\\output\\"+$full_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);

//
// bake texture also?
//

if ($surface_bake)
{
string $texture_file_name = $file_name + "-surface." + $file_extension;

string $shading_group = llGetShadingGroup($object);

print("baking texture for " + $object + " into file " + $texture_file_name + "\n";);

// bake sculpt texture
string $fileNodes[] = convertSolidTx("-fileImageName", "c:\\output\\"+$texture_file_name,
"-fileFormat", $file_format,
"-force", 1,
"-resolutionX", $surface_resolution_x,
"-resolutionY", $surface_resolution_y,
"-shadows", $surface_shadows,
$shading_group,
$object);


if ($swapped)
{
print "Swapping texture\n";
print (system("convert -flip "+ $texture_file_name +" "+ $texture_file_name));
print (system("convert -rotate 270 "+ $texture_file_name +" "+ $texture_file_name));
}
if ($flipped)
{
print "Flipping texture\n";
print (system("convert -flip "+ $texture_file_name +" "+ $texture_file_name));
}

delete($fileNodes); // still don't want 'em.
}


//
// construct primScript
//
if ($generate_primscript)
{
global string $llPrimScript;

// strip dir from filename
string $tokens[];
tokenize($file_name, "/", $tokens);
string $base_name = $tokens[size($tokens)-1];

$llPrimScript += "newPrim\n";

$llPrimScript += "prim -setObjectName " + $object + " -deleteScript\n";

$llPrimScript += "shape -setSculpt " + $base_name + " 1 -deleteScript\n";

$llPrimScript += "texture";
if ($surface_bake)
$llPrimScript += " -setTexture " + $base_name + "-surface -1";
$llPrimScript += " -deleteScript\n";

$llPrimScript += "transform -setScale " +
$scale[0] + " " + $scale[1] + " " +$scale[2] +
" -gotoRelativePos " +
$center[0]*$scale[0] + " " + $center[1]*$scale[1] + " " +$center[2]*$scale[2] +
" -deleteScript \n";
}

}



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";);
int $surface_bake = checkBoxGrp("-query", "-value1", "llSculptEditorSurfaceBake";);
int $surface_resolution_x = intSliderGrp("-query", "-value", "llSculptEditorSurfaceResolutionX";);
int $surface_resolution_y = intSliderGrp("-query", "-value", "llSculptEditorSurfaceResolutionY";);
int $surface_shadows = checkBoxGrp("-query", "-value1", "llSculptEditorSurfaceShadows";);
int $generate_primscript = checkBoxGrp("-query", "-value1", "llSculptEditorGeneratePrimScript";);


// 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";
}
}


global string $llPrimScript;
$llPrimScript = "";

int $multi_file = 0;

if (size($objects) > 1)
$multi_file = 1;

if ($generate_primscript)
$multi_file = 1;

string $object;
for ($object in $objects)
{
string $this_filename = $file_base;
if ($multi_file)
$this_filename += "-" + $object;

llSculptExport($object, $this_filename, $file_extension, $file_type, $resolution_x, $resolution_y,
$maximize_scale, $fix_orientation,
$surface_bake, $surface_resolution_x, $surface_resolution_y, $surface_shadows,
$generate_primscript);
}

if ($generate_primscript)
{
int $file_id=fopen($file_base + ".primscript";);
fwrite($file_id, $llPrimScript);
fclose($file_id);
}

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 llSculptEditorSurfaceBakeCallback()
{
int $surface_bake = checkBoxGrp("-query", "-value1", "llSculptEditorSurfaceBake";);

control("-edit", "-enable", $surface_bake, "llSculptEditorSurfaceResolutionX";);
control("-edit", "-enable", $surface_bake, "llSculptEditorSurfaceResolutionY";);
control("-edit", "-enable", $surface_bake, "llSculptEditorSurfaceShadows";);
}


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 on
llSculptEditorMaximizeScale;

checkBoxGrp
-label ""
-label1 "Correct orientation"
-numberOfCheckBoxes 1
-value1 off
llSculptEditorFixOrientation;

separator;

checkBoxGrp
-label ""
-label1 "Bake surface texture"
-numberOfCheckBoxes 1
-value1 off
-changeCommand llSculptEditorSurfaceBakeCallback
llSculptEditorSurfaceBake;

intSliderGrp
-field on
-label "X Resolution"
-minValue 1
-maxValue 512
-fieldMinValue 1
-fieldMaxValue 4096
-value 128
llSculptEditorSurfaceResolutionX;

intSliderGrp
-field on
-label "Y Resolution"
-minValue 1
-maxValue 512
-fieldMinValue 1
-fieldMaxValue 4096
-value 128
llSculptEditorSurfaceResolutionY;

checkBoxGrp
-label ""
-label1 "Include shadows"
-numberOfCheckBoxes 1
-value1 on
llSculptEditorSurfaceShadows;

separator;

checkBoxGrp
-label ""
-label1 "Generate primscript"
-numberOfCheckBoxes 1
-value1 on
llSculptEditorGeneratePrimScript;



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" );

llSculptEditorSurfaceBakeCallback();

showOptionBox();
}


//

llSculptEditor;
Crash Prefect
Darklife Art Director
Join date: 4 Dec 2004
Posts: 55
09-27-2007 09:42
From: Mark Busch
Sometimes there are one two prims that did not get proper orientation (it's inside out, or something else is wrong). If so rotate the texture + sculpt texture 90 degrees to the right (or something like that) and manually set it again for those prims.



that was if we were using EP curves,..or even using nurbs planes to create a shape. the work around was to uncheck the orientation check box, re export the offending prims, and bring it to an image editing program like photoshop and flip the image horizontally. What this does is make it right side out.


On a side note, if you do this to any sculpt texture, texture it black, and resize it slightly to fit over a fixed version of itself you can create a cell shaded effect. "inside out prim creates a constant black line around your prim"
Carrie Tatsu
Registered User
Join date: 13 Nov 2006
Posts: 3
works better
11-01-2007 10:33
Just wanted to say that the suggestion works..I tested it a few times. The only thing I noticed is the original sculptie exporter for Maya did not generate a correct prim script, the one posted in this forum did. However I couldn't use this one to create the sculptie textures since I am on a Mac..but using both in conjunction seemed to do the trick..
carrie