How to scale one UV shell to match the exact scale of an identical shell that is a different size in Mel.

How to scale one UV shell to match the exact scale of an identical shell that is a different size in Mel.

malcolm_341
Collaborator Collaborator
803 Views
7 Replies
Message 1 of 8

How to scale one UV shell to match the exact scale of an identical shell that is a different size in Mel.

malcolm_341
Collaborator
Collaborator

Hi, I'm looking to scale one UV shell to mach another identical UV shell that is smaller or bigger by an arbitrary amount. I thought I could do this by comparing the bounding boxes and scaling by the difference, but I can't get it working. I can't seem to get shell 1 to scale exactly to shell 2. Here's my code, I'm not sure why it won't work, it's close to matching, but pretty far off.

 

//Store two selected UV shells
string $shellUVs[] = `ls -sl -fl`;
string $findShells[] = `texGetShells`;


int $numbShells = `size $findShells`;
global string $m341_udimPacker_largestShell[];
$m341_udimPacker_largestShell = {};
float $compareShell = 0;
int $shellIndex = 0;

//Select the first UV shell
select $findShells[0];
string $uvShell1[] = `ls -sl -fl`;
float $uvBBox1[] = `polyEvaluate -boundingBoxComponent2d -accurateEvaluation $uvShell1`;
float $sizeU1 = $uvBBox1[3] - $uvBBox1[0];
float $sizeV1 = $uvBBox1[4] - $uvBBox1[1];

//Select the second UV shell
select $findShells[1];
string $uvShell2[] = `ls -sl -fl`;
float $uvBBox2[] = `polyEvaluate -boundingBoxComponent2d -accurateEvaluation $uvShell2`;
float $sizeU2 = $uvBBox2[3] - $uvBBox2[0];
float $sizeV2 = $uvBBox2[4] - $uvBBox2[1];

// Calculate the scaling factors
float $scaleU = $sizeU2 / $sizeU1;
float $scaleV = $sizeV2 / $sizeV1;

// Apply scaling to the first UV shell
select $uvShell1;
polyEditUV -su $scaleU -sv $scaleU;
0 Likes
Accepted solutions (1)
804 Views
7 Replies
Replies (7)
Message 2 of 8

mcw0
Advisor
Advisor

Is this one shell out of multiple shells for a mesh?  Do you not need to align all shells?  If you are doing all, why not just transfer the uvs from one mesh to the other?

If you only want to align one specific shell, pick 2 common uvs in that shell.  For example, map[0] and map[1].  

Get the distances to figure out the scale factor.  Now do your scaling setting the pivot at either of those uv points.  That should get the scales to match perfectly.

0 Likes
Message 3 of 8

malcolm_341
Collaborator
Collaborator

@mcw0

Can't transfer, there will be a mixed mode seleciton it needs to work on a arbitrary selection of shells across multiple meshes that are identical, but not all shells will be matched. It allows for the user to define which identical shells should stack without stacking all identical shells.

 

I need to scale an arbritrary amount of shells to perfectly match the source shell. Why would moving the pivot make any difference to the scaling? I already stacked all the shells on top of themselves so shouldn't the bounding box be the difference between the shell sizes, or does the boundingbox get out of whack if the pivots are different?

0 Likes
Message 4 of 8

mcw0
Advisor
Advisor
Conceptually, calculating the scale factor should allow you to apply that scale from any pivot. It's just how I would do it. Assuming all shells are similar with scale being the only difference, then measuring one edge is sufficient. And scaling from one of the 2 points of that edge is the most direct to me.



0 Likes
Message 5 of 8

malcolm_341
Collaborator
Collaborator

@mcw0 All shells are the exact same uniform scale bigger or smaller, so I don't know why the code for bounding box isn't working. I can't think of a way to scale from the same UV on each shell either because sometimes that shell will be part of another mesh so the component id's may change. I tried Copilot and it told me to measure the bounding boxes and use the scale factor, but that didn't work either. It won't uniformly scale the shells to match the master shell correctly, is there a rounding error or something I'm not accounting for or some other trick in Maya I'm missing? I have even tried with idental quads scaled differently and the bounding box still comes up wrong when I apply the UV transform. Maybe I'm calculating the scale factor wrong?

0 Likes
Message 6 of 8

mcw0
Advisor
Advisor

I've never thought of using the bounding box of a shell.  I just went for the edge length.  Are the shells also oriented identically?  Is there a possible rotational offset that's throwing off the bounding box calculation?

 

You mentioned the shell might be part of a larger mesh.  Might separating the mesh be an option?  Make a duplicate of the mesh, separate to isolate the shell in question.  Do your calculations and delete the duplicate.  then apply your calculated values to the original mesh.

0 Likes
Message 7 of 8

malcolm_341
Collaborator
Collaborator

@mcw0 Seperation is not an option unfortunately. The shells are oriented the same, I was originally solving the issue by copy and pasting the texel density between the master shell and all the other shells, but then I realized if the world space of the identical shells differs from the master shell, pasting the texel density gives the wrong result and shells don't line up because texel density works on world size of mesh. So I need to find some way to accurately scale all the target shells to be the exact same size as the master shell.

0 Likes
Message 8 of 8

malcolm_341
Collaborator
Collaborator
Accepted solution

@mcw0 Some more info here, so it serves me right for trying to use Copilot to help me write the code. It got an array wrong, yes an array, it put [0] [2] [3] [4] into a bounding box array and I didn't notice the error for a whole day, so that code never worked. Then it took me a on a goose chase pretending it knew how to scale one UV bounding box to match another. After that I asked my wife for help with the math and she was able to get the script almost working, and today I asked my friend Ryan who's an accomplished pipeline and rendering engineer and he showed me I needed to square root the UV bounding boxes to get them to scale correctly and now the script works. I have no math basis, so I always need help with these types of problems. Here's the code without all my custom stuff required for the tool to work, in this example you select the shells manually and have to run the script in two parts, if you know a little Mel this should make sense to anyone wanting to do this with there own script.

 

 

//Select the source shell manually
//Get the bounding box of source shell
string $targetUVShell[] = `ls -sl -fl`;
float $targetBBox[] = `polyEvaluate -accurateEvaluation -boundingBoxComponent2d`;
float $bBoxDistanceU = $targetBBox[1] - $targetBBox[0];
float $bBoxDistanceV = $targetBBox[3] - $targetBBox[2];
float $bBoxUVArea_master = $bBoxDistanceU * $bBoxDistanceV;

//Get pivot of the source shell
string $shapeNode1[] = `ls -sl -objectsOnly`;
float $uvPivotVal_Master1[] = `getAttr ($shapeNode1[0] + ".uvPivot")`;



//Select the target shells manually
//Stack all the target shells so pivots are shared
texStackShells({});
					
//Get list of shells to loop through
string $findShells[] = texGetShells();
int $numbShells = `size $findShells`;
int $shellIndex = 0;
string $shellToken[] = {};

//Get pivot of the target shells
string $shapeNode2[] = `ls -sl -objectsOnly`;
float $uvPivotVal_Master1All[] = `getAttr ($shapeNode2[0] + ".uvPivot")`;
				
//Calculate distance to move shells
float $moveAmountU = $uvPivotVal_Master1[0] - $uvPivotVal_Master1All[0];
float $moveAmountV = $uvPivotVal_Master1[1] - $uvPivotVal_Master1All[1];
				
//Move target shells to the source shell
polyEditUV -u $moveAmountU -v $moveAmountV;
performResetPivot;


//Loop through shells and scale each shell to match source using bounding box
for ($shell = 0; $shell < $numbShells; ++$shell)
{
	tokenize($findShells[$shellIndex], $shellToken);
	select $shellToken;
						
	//Store bounding box of target shell 
	float $sourceBBox[] = `polyEvaluate -accurateEvaluation -boundingBoxComponent2d`;
	float $bBoxDistanceU_target = $sourceBBox[1] - $sourceBBox[0];
	float $bBoxDistanceV_target = $sourceBBox[3] - $sourceBBox[2];
	float $bBoxUVArea_target = $bBoxDistanceU_target * $bBoxDistanceV_target;

	//Calculate the scaling factors				
	float $scaleFactor = sqrt ($bBoxUVArea_master / $bBoxUVArea_target);
	
	//Select target shell and apply scaling to the source UV shell
	polyEditUV -pu $uvPivotVal_Master1[0] -pv $uvPivotVal_Master1[1] -su $scaleFactor -sv $scaleFactor;
							
	$shellIndex = $shellIndex + 1;
}

 

0 Likes