I find it surprisingly difficult to find the rotation that moves an object from one given point to another one in POV-Ray.
Geometrically it's simple enough to find: I calculate the distance Dist
from the origin to the target point PointT
(green), and create Point0
at <Dist, 0, 0>
(blue). Then I calculate from Point0
and PointT
the angle between them and the perpendicular to them. The rotation by AngleD
around Perp
moves Point0
to Point1
= PointT
.
In POV-Ray I can use vaxis_rotate
to calculate Point1
. But I want to actually rotate an object (which, of course, will not be a sphere), and I don't see an obvious way to do this. I tried rotate -AngleD*Perp
, but that gives a slightly different result (red).
How can I do to an object, what vaxis_rotate
does to a point?
#declare PointT = <2, 2, 2>;
#declare Dist = VDist(<0, 0, 0>, PointT);
#declare Point0 = <Dist, 0, 0>;
#declare AngleD = VAngleD(PointT, Point0);
#declare Perp = VPerp_To_Plane(PointT, Point0);
#declare Point1 = vaxis_rotate(Point0, Perp, -AngleD);
sphere{Point0, R pigment{color Blue} }
sphere{Point1, R pigment{color Green} }
sphere{
Point0, R
rotate -AngleD*Perp
pigment{color Red}
}
The rotation matrix in the link provided by meowgoesthedog gives the expected result.
#macro RotMatFromVectorAndAngle(Vector, Angle)
// takes normalized vector and angle in radians
#local U = Vector.x;
#local V = Vector.y;
#local W = Vector.z;
#local Sin = sin(Angle);
#local Cos = cos(Angle);
#local M11 = U*U + (1-U*U)*Cos;
#local M12 = U*V*(1-Cos) - W*Sin;
#local M13 = U*W*(1-Cos) + V*Sin;
#local M21 = U*V*(1-Cos) + W*Sin;
#local M22 = V*V + (1-V*V)*Cos;
#local M23 = V*W*(1-Cos) - U*Sin;
#local M31 = U*W*(1-Cos) - V*Sin;
#local M32 = V*W*(1-Cos) + U*Sin;
#local M33 = W*W + (1-W*W)*Cos;
matrix <M11, M12, M13,
M21, M22, M23,
M31, M32, M33,
0 , 0 , 0 >
#end
Applied to the sphere from the example above:
#declare Angle = VAngle(PointT, Point0);
#declare Perp = VPerp_To_Plane(PointT, Point0);
sphere{
Point0, R
RotMatFromVectorAndAngle(Perp, Angle)
}