rotationgeometrypovray

How to rotate an object around a vector in POV-Ray?


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}
}

enter image description here


Solution

  • 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)
    }