MODULE Proj3D; (* A module that computes perspective projections in 3-space. *) IMPORT R2, R3; (* This procedure provides a single function, "Project", for mapping points in 3-space to points in 2-space according to a simple perspective projection. The "Project" function is parameterized by the point in 3-space to project, the location of the camera, and a point in 2-space to which the 3-space origin should be mapped. In this model, the camera's viewing direction is the one that causes it to point at the 3-space origin, and the view plane is taken to be a fixed distance from the camera orthogonal to the viewing direction. The "up" direction of the camera is the direction of the z-axis; hence, this mapping is undefined when the camera is located on the z-axis. *) PRIVATE CONST PlaneDist = 100, Scale = 10; PRIVATE FUNC Q = ProjectToPlane(P, camDir, camLoc, viewP0) IS (E lineDir = R3.Minus(P, camLoc), denom = R3.Dot(camDir, lineDir), Num = R3.Dot(camDir, R3.Minus(camLoc, viewP0)), t = -(Num / denom) :: Q = R3.Plus(camLoc, R3.Times(t, lineDir))) END; FUNC q = Project(Q, org, camLoc) IS (E camDist = R3.Length(camLoc), camDir = R3.Times(1 / camDist, camLoc), viewP0 = R3.Times(camDist - PlaneDist, camDir), zPt = ProjectToPlane([0, 0, 1], camDir, camLoc, viewP0), upVec = R3.Normalize(R3.Minus(zPt, viewP0)), xVec = R3.Normalize(R3.Cross(upVec, camDir)), qx, qy, Q1 = ProjectToPlane(Q, camDir, camLoc, viewP0), vec = R3.Minus(Q1, viewP0) :: q = R2.Plus(org, (qx, qy)) AND qx = Scale * R3.Dot(xVec, vec) AND qy = Scale * R3.Dot(upVec, vec)) END; (* "q" is the perspective projection of the point "Q" in 3-space. "org" is the point in 2-space to which the point "[0,0,0]" is mapped. "camLoc" is the location of the camera in 3-space. *)