Hi all,
I am trying to write a script that will take selected mesh objects (only planes) and rotate them in world y axis only to face the selected camera.
I'm having problems with the math part of it. Right now I am trying to solve it by creating a triangle of locators to calculate the angle between the camera and the selected plane.
Locator1 is point constrained in x and z axis to the camera. Locator2 is point constrained in x and z to the plane. Locator3 is point constrained in x and z to a copy of the plane that is extruded along the planes normal. This results in a 2d triangle from which I can use cos and acos to figure out a rotation angle. This almost seems to work.
The problem is it only works on planes to the left side of the camera. Planes to the right side are rotated the wrong way. So I need some way of figuring out if an object is to the left or to the right of the camera. Or perhaps a better way to calculate the rotation.
Any help and/or suggestions will be very much appreciated!
Torben
Here's the code so far. Don't know if it's helping to show the problem or just makes it more confusing ![]()
CODE
/////////////////////////////////////////////////////////////////////////////
//Purpose: Takes all selected meshes and rotates them in world Y only to face
// the selected camera.
// IMPORTANT: Use only for planes.
//
//Usage: Select any number of planes and ONE camera. Run script
//
/////////////////////////////////////////////////////////////////////////////
//init selections
$initSel = ls -sl
;
//find cam
$camToFace = ls -type "camera"
;
$meshList = ls -type "mesh"
;
$allCameraShapeNodes = ls -type "camera"
;
$allMeshShapeNodes = ls -type "mesh"
;
$allCameras = listRelatives -p $allCameraShapeNodes
;
$allMeshes = listRelatives -p $allMeshShapeNodes
;
$sel = ls -sl
;
int $countCamera = 0;
int $countMeshes = 0;
// find cameras in selection
for($each in $sel)
{
for($any in $allCameras)
{
if($each == $any)
{
$countCamera ++;
}
}
}
if ($countCamera == 0)
{
error "No camera found in selection.";
} else if ($countCamera > 1)
{
error "More than one camera found in selection.";
} else {
print ("camera: " + $allCameras[0] + "\n");
// find meshes in selection
for($each in $sel)
{
for($any in $allMeshes)
{
if($each == $any)
{
print ("mesh: " + $each + "\n");
$countMeshes ++;
aimAtCam($each, $allCameras[0]);
}
}
}
if ($countMeshes == 0)
{
error "No mesh found in selection.";
}
select -r $initSel;
}
global proc aimAtCam(string $myObj, string $myCam)
{
//create a triangle of locators to determine angle between cam and obj
//in world y rotation
//duplicate obj
select -r $myObj;
$myObjCopy = duplicate -rr
;
//move vertices along normal
int $vertexCount[] = polyEvaluate -v $myObjCopy
;
$moveCmd = "moveVertexAlongDirection ";
for ($i = 0; $i < $vertexCount[0]; $i++)
{
$moveCmd += "-n 5 ";
}
$moveCmd += ";";
select -r $myObjCopy.vtx[0:$vertexCount[0]-1];
eval($moveCmd);
//center pivot
select -r $myObjCopy;
xform -cp;
//create locators and constrain xz position
//to make a triangle on the ground plane
$myObjLoc = spaceLocator -p 0 0 0
;
select -r $myObj $myObjLoc;
pointConstraint -offset 0 0 0 -skip y -weight 1;
float $pax[] = getAttr $myObjLoc.tx
; //do not move this line. somehow it doesn't work if these floats are declared after the other locators
float $paz[] = getAttr $myObjLoc.tz
;
$myObjCopyLoc = spaceLocator -p 0 0 0
;
select -r $myObjCopy $myObjCopyLoc;
pointConstraint -offset 0 0 0 -skip y -weight 1;
float $pbx[] = getAttr $myObjCopyLoc.tx
; //do not move this line. somehow it doesn't work if these floats are declared after the other locators
float $pbz[] = getAttr $myObjCopyLoc.tz
;
$myCamLoc = spaceLocator -p 0 0 0
;
select -r $myCam $myCamLoc;
pointConstraint -offset 0 0 0 -skip y -weight 1;
float $pcx[] = getAttr $myCamLoc.tx
; //do not move this line. somehow it doesn't work if these floats are declared after the other locators
float $pcz[] = getAttr $myCamLoc.tz
;
//calculate angle
float $abx = $pax[0]-$pbx[0];
float $abz = $paz[0]-$pbz[0];
float $ab = sqrt($abx*$abx + $abz*$abz + 0.00001); //small problem here.. add small number to avoid division by zero
float $bcx = $pbx[0]-$pcx[0];
float $bcz = $pbz[0]-$pcz[0];
float $bc = sqrt($bcx*$bcx + $bcz*$bcz + 0.00001); //small problem here.. add small number to avoid division by zero
float $cax = $pcx[0]-$pax[0];
float $caz = $pcz[0]-$paz[0];
float $ca = sqrt($cax*$cax + $caz*$caz + 0.00001);
float $cosA = -($bc*$bc - $ab*$ab - $ca*$ca) / (2*$ab*$ca);
float $acosA = acos($cosA) * 180 / 3.14159;
//float $cosB=-($ca*$ca-$bc*$bc-$ab*$ab)/(2*$bc*$ab);
//float $acosB=acos($cosB)*180/3.14159;
//float $cosC=-($ab*$ab-$ca*$ca-$bc*$bc)/(2*$ca*$bc);
//float $acosC=acos($cosC)*180/3.14159;
$rotateMyObj = $acosA;
select -r $myObj;
rotate -r -ws 0 $rotateMyObj 0;
print("rotation " + $rotateMyObj + "\n");
//some cleanup
select -r $myObjLoc $myObjCopyLoc $myCamLoc $myObjCopy;
delete;
}