PDA

View Full Version : surface normal to rotation


deadalvs
02-04-2008, 08:44 PM
hi ...

i am searching a small script that gives me the y-rotation (for a direction indicator) based on the normal of any point of a nurbs surface.

let's say i have a shaped plane and i choose UV = 0.3/0.8, then i'd like to know the rotation about the y axis that shows exactly in the direction of the point's slope (in xz plane)

i know the problem's not that complex and i have scripted a version already, but there's a tiny error in the script that gives back faulty results...
(if the normal is == up or == down, that case should be explicitly pointed out, because there's no rotation making sense in that case, especially not 0 degrees.)

i can post my approach tomorrow when i get back to work... trigonometry's not complex, i only get wrong numbers with the negative tangential ratios... :banghead:

tbaypaul
02-05-2008, 12:57 AM
if I understand you right....you want the dot product of the world up and your normal. So as long as your normal is of unit length (normed) then the angle between them is just the arc cos of the y component of your normal vector.

deadalvs
02-05-2008, 08:06 AM
hey there !

thanks for that input !

i'll check that asap... :)

deadalvs
02-05-2008, 10:51 AM
ah, i see.

--> check image.

you meant the euler angle between the two vectors... that can easily be found by the angle command. (left drawing)

i meant the angle in the right drawing. as you see, the angle is only about the y-axis, showing the angle found by the x and y components of the normal.

code till now:

* * * * *

global vector $upVector;
$upVector = <<0,1,0>>;
global vector $nurbsNormal;
$nurbsNormal = <<2,2,2>>;
vector $nurbsNormal;


//vars
float $diffAngle;
float $slope;
float $Y_orientationAngle;

//calcs
$diffAngle = rad_to_deg (`angle $upVector $nurbsNormal`);
$slope = (tand ($diffAngle)) * 100;
float $Y_orientationAngle = `atand ($nurbsNormal.z / $nurbsNormal.x)`;

//print result
print ($Y_orientationAngle + "\n");

* * * * *

the problem is when the rotation turns to negative values...

plus, the exception when normal is parallel to world up is missing, i skipped it in this example.

deadalvs
02-05-2008, 02:08 PM
i guess this is the correct code now...

could someone beta-test it ? :)

* * * * *

/*
example:
create a nurbs plane and rotate it.

//settings
string $targetSurface = "nurbsPlane1";
float $UPos = 0.5;
float $VPos = 0.5;
vector $upVector = <<0,1,0>>;

//commands !
global float $result;
$result = getYRotSlopeAngle($targetSurface, $Upos, $Vpos, $upVector);
if ($result == 720){
print "holy crap, the normal is parallel to the upVector !\n";
}
if ($result != 720){
global float $result;
print "yay, the result is: !\n";
print ($result + "\n");
}
//setAttr "locator1.rotateY" $result;

*/

global proc float getYRotSlopeAngle (string $targetSurface, float $UPos, float $VPos, vector $upVector){
//find Normal
global vector $nurbsNormal;
$nurbsNormal = `pointOnSurface -u $UPos -v $VPos -normal $targetSurface`;
//vars
float $diffAngle;
float $slope;
float $Y_orientationAngle;

//division by zero issue solving
if ($nurbsNormal.x == 0){
global vector $nurbsNormal;
$nurbsNormal = <<0.0000001,$nurbsNormal.y, $nurbsNormal.z>>;
}
if ($nurbsNormal.z == 0){
global vector $nurbsNormal;
$nurbsNormal = <<$nurbsNormal.x ,$nurbsNormal.y, 0.0000001>>;
}


//special case: normal is parallel to worldUp
if ( (abs ($nurbsNormal.x) <= 0.0000001) && (abs ($nurbsNormal.z) <= 0.0000001)){
return 720;
}
//normal case
if ( (abs ($nurbsNormal.x) > 0) && (abs ($nurbsNormal.z) > 0)){

$diffAngle = rad_to_deg (`angle $upVector $nurbsNormal`);
$slope = (tand ($diffAngle)) * 100;
float $Y_orientationAngle = `atand ($nurbsNormal.z / $nurbsNormal.x)`;

return 90 - $Y_orientationAngle;
}
//end getYRotSlopeAngle
}

Robert Bateman
02-05-2008, 02:58 PM
any reason why you are not using a normalConstraint node and reading the rotation back from that?

deadalvs
02-05-2008, 03:09 PM
hehe, proper coding :)

no, seriously. i solved a familiar problem in an other script with the constraint node and it gave back proper results of course.

i just like the old-school trigonometric approach ... no absolute reason ...

deadalvs
02-05-2008, 06:38 PM
well, there is some kinda bug in the aimContraint command. when the z component of the normal becomes negative, the orient rotation acts like positive in respect to values.

i had to add ifs for correction.

--> code for the proc

* * * * *

global proc float getYRotSlopeAngle (string $targetSurface, float $UPos, float $VPos, vector $upVector){
//find Normal
global vector $nurbsNormal;
$nurbsNormal = `pointOnSurface -u $UPos -v $VPos -normal $targetSurface`;
//vars
float $Y_orientationAngle;

spaceLocator -p 0 0 0 -n "worldLocator";
move -r 0 0 0;
spaceLocator -p 0 0 0 -n "normalLocator";
move -r ($nurbsNormal.x) ($nurbsNormal.y) ($nurbsNormal.z);

select -r normalLocator ;
select -tgl worldLocator ;
aimConstraint -offset 0 0 0 -weight 1 -aimVector 0 0 1 -upVector 0 1 0 -worldUpType "vector" -worldUpVector 0 1 0 -skip x -skip z;
$Y_orientationAngle = `getAttr worldLocator.rotateY`;
undo;
select -r normalLocator ;
select -tgl worldLocator ;
delete;

if ($nurbsNormal.z <0){
return (180 - $Y_orientationAngle);
}
if ($nurbsNormal.z >= 0){
return $Y_orientationAngle;
}

//end getYRotSlopeAngle
}

CGTalk Moderation
02-05-2008, 06:38 PM
This thread has been automatically closed as it remained inactive for 12 months. If you wish to continue the discussion, please create a new thread in the appropriate forum.