View Full Version : surface normal to rotation
deadalvs 02 February 2008, 08:44 PM hi ...
i am searching a small script that gives me the yrotation (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 February 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 February 2008, 08:06 AM
hey there !
thanks for that input !
i'll check that asap... :)
deadalvs
02 February 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 yaxis, 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 February 2008, 02:08 PM
i guess this is the correct code now...
could someone betatest 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 February 2008, 02:58 PM
any reason why you are not using a normalConstraint node and reading the rotation back from that?
deadalvs
02 February 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 oldschool trigonometric approach ... no absolute reason ...
deadalvs
02 February 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 February 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.