(*^ ::[ Information = "This is a Mathematica Notebook file. It contains ASCII text, and can be transferred by email, ftp, or other text-file transfer utility. It should be read or edited using a copy of Mathematica or MathReader. If you received this as email, use your mail application or copy/paste to save everything from the line containing (*^ down to the line containing ^*) into a plain text file. On some systems you may have to give the file a name ending with ".ma" to allow Mathematica to recognize it as a Notebook. The line below identifies what version of Mathematica created this file, but it can be opened using any other version as well."; FrontEndVersion = "Macintosh Mathematica Notebook Front End Version 2.2"; MacintoshStandardFontEncoding; fontset = title, inactive, noPageBreakBelow, nohscroll, preserveAspect, groupLikeTitle, center, M7, bold, L3, e8, 24, "New York"; fontset = subtitle, inactive, noPageBreakBelow, nohscroll, preserveAspect, groupLikeTitle, center, M7, bold, L2, e6, 18, "New York"; fontset = subsubtitle, inactive, noPageBreakBelow, nohscroll, preserveAspect, groupLikeTitle, center, M7, bold, L2, e6, 14, "New York"; fontset = section, inactive, noPageBreakBelow, nohscroll, preserveAspect, groupLikeSection, grayBox, M22, bold, L2, a20, 14, "New York"; fontset = subsection, inactive, noPageBreakBelow, nohscroll, preserveAspect, groupLikeSection, blackBox, M19, bold, L2, a15, 12, "New York"; fontset = subsubsection, inactive, noPageBreakBelow, nohscroll, preserveAspect, groupLikeSection, whiteBox, M18, bold, L2, a12, 10, "New York"; fontset = text, inactive, nohscroll, noKeepOnOnePage, preserveAspect, M7, L2, 12, "New York"; fontset = smalltext, inactive, nohscroll, noKeepOnOnePage, preserveAspect, M7, L2, 10, "New York"; fontset = input, noPageBreakInGroup, nowordwrap, preserveAspect, groupLikeInput, M42, N23, bold, L2, 14, "Courier"; fontset = output, output, inactive, noPageBreakInGroup, nowordwrap, preserveAspect, groupLikeOutput, M42, N23, L2, 10, "Courier"; fontset = message, inactive, noPageBreakInGroup, nowordwrap, preserveAspect, groupLikeOutput, M42, N23, R65535, L2, 12, "Courier"; fontset = print, inactive, noPageBreakInGroup, nowordwrap, preserveAspect, groupLikeOutput, M42, N23, L2, 12, "Courier"; fontset = info, inactive, noPageBreakInGroup, nowordwrap, preserveAspect, groupLikeOutput, M42, N23, L2, 12, "Courier"; fontset = postscript, PostScript, formatAsPostScript, output, inactive, noPageBreakInGroup, nowordwrap, preserveAspect, groupLikeGraphics, M7, l34, w282, h287, L2, 12, "Courier"; fontset = name, inactive, nowordwrap, nohscroll, noKeepOnOnePage, preserveAspect, M7, italic, B65535, L2, 10, "Geneva"; fontset = header, inactive, noKeepOnOnePage, preserveAspect, M7, L2, 10, "Times"; fontset = leftheader, inactive, L2, 10, "Times"; fontset = footer, inactive, noKeepOnOnePage, preserveAspect, center, M7, L2, 12, "Times"; fontset = leftfooter, inactive, center, L2, 12, "Times"; fontset = help, inactive, nohscroll, noKeepOnOnePage, preserveAspect, M7, L2, 10, "Geneva"; fontset = clipboard, inactive, noKeepOnOnePage, preserveAspect, M7, L2, 12, "New York"; fontset = completions, inactive, nowordwrap, noKeepOnOnePage, preserveAspect, M7, L2, 12, "New York"; fontset = special1, inactive, nowordwrap, noKeepOnOnePage, preserveAspect, M7, L2, 12, "New York"; fontset = special2, inactive, nowordwrap, noKeepOnOnePage, preserveAspect, center, M7, L2, 12, "New York"; fontset = special3, inactive, nowordwrap, noKeepOnOnePage, preserveAspect, right, M7, L2, 12, "New York"; fontset = special4, inactive, nowordwrap, noKeepOnOnePage, preserveAspect, M7, L2, 12, "New York"; fontset = special5, inactive, nowordwrap, noKeepOnOnePage, preserveAspect, M7, L2, 12, "New York"; paletteColors = 256; currentKernel; ] :[font = section; inactive; dontPreserveAspect] from Exploring Parallel Graphics with Mathematicaª © Jacques J. Vidal, 1990 ;[s] 1:0,1;86,-1; 2:0,19,14,New York,1,14,0,0,0;1,14,10,New York,1,10,0,0,0; :[font = subsubtitle; inactive; preserveAspect] 3D Perspective Transformation using a Normalized View Volume :[font = section; inactive; Cclosed; preserveAspect; startGroup] Definition of Cross (from "LinearAlgebra`CrossProducts`"] :[font = input; initialization; preserveAspect; fontSize = 10; endGroup] *) Cross[v1_?VectorQ, v2_?VectorQ] := Module[{m=Minors[{v1,v2},2][[1]]}, {m[[3]], -m[[2]], m[[1]]} ] /; Length[v1]==Length[v2]==3 (* Properties of cross products. *) Cross/: Cross[a_,b_]^2 := a.a b.b - (a.b)^2; Cross[a_,a_] = 0; Cross[a_ + b_, c_] := Cross[a,c] + Cross[b,c]; Cross[a_, b_ + c_] := Cross[a,b] + Cross[a,c]; Cross[a_,0] = 0; Cross[0,a_] = 0; Cross[(n_?NumberQ) a_, b_] := n Cross[a, b]; Cross[a_, (n_?NumberQ) b_] := n Cross[a, b]; Cross[a_,Cross[b_,c_]] := (a.c) b - (a.b) c; Cross[Cross[a_,b_],c_] := (a.c) b - (b.c) a; Unprotect[Dot]; (* Properties of dot products. *) a_ . ((n_?NumberQ) b_) := n (a.b); ((n_?NumberQ) a_) . b_ := n (a.b); a_ . (b_ + c_) := a.b + a.c; (a_ + b_) . c_ := a.c + b.c; a_ . 0 = 0; 0 . a_ = 0; a_ . Cross[a_,b_] = 0; a_ . Cross[b_,a_] = 0; Cross[a_,b_] . a_ = 0; Cross[b_,a_] . b_ = 0; Cross[a_,b_] . c_ := a . Cross[b,c]; a_ . Cross[b_,c_] := b . Cross[c,a] /; !OrderedQ[{a,b}]; a_ . Cross[b_,c_] := c . Cross[a,b] /; !OrderedQ[{a,c}]; (* This rule must be given after other rules involving Cross are defined. *) Cross[a_,b_] := -Cross[b,a] /; !OrderedQ[{a,b}]; (* :[font = section; inactive; Cclosed; preserveAspect; startGroup] Definition of Transformation Matrices :[font = input; initialization; dontPreserveAspect; endGroup] *) Off[General::spell]; Off[General::spell1]; homogenize[vec:{_,_}]:=Append[vec,1] deHomogenize[vec:{_,_,_}]:=Drop[vec/(Last[vec]),-1] homogenize[vec:{_,_,_}]:=Append[vec,1] deHomogenize[vec:{_,_,_,_}]:=Drop[vec/(Last[vec]),-1] normalize[vec:_List]:= vec/Sqrt[Apply[Plus,vec^2]] (** Transformations in Two dimensions **) (******************************************************) rotationMatrix2D[theta_] := {{Cos[theta], -Sin[theta], 0}, {Sin[theta], Cos[theta], 0}, {0,0,1}} (******************************************************) scalingMatrix2D[{sx_,sy_}] := { {sx,0,0},{0,sy,0},{0,0,1} } (******************************************************) translationMatrix2D[{tx_,ty_}] := { {1,0,tx},{0,1,ty},{0,0,1} } (******************************************************) (** Three dimensions **) xRotationMatrix3D[phi_] := Transpose[ { {1, 0, 0, 0}, {0, Cos[phi], Sin[phi],0}, {0,-Sin[phi], Cos[phi],0}, {0, 0, 0, 1} }] yRotationMatrix3D[psi_] := Transpose[ { {Cos[psi], 0, -Sin[psi], 0}, {0, 1, 0, 0}, {Sin[psi], 0, Cos[psi], 0}, {0, 0, 0, 1} }] zRotationMatrix3D[theta_]:= Transpose[{ {Cos[theta], Sin[theta], 0,0}, {-Sin[theta], Cos[theta], 0, 0}, {0, 0, 1, 0}, {0, 0, 0, 1} }] rotationMatrix3D[phi_,theta_,psi_] := Transpose[ { { Cos[psi] Cos[phi] - Cos[theta] Sin[phi] Sin[psi], Cos[psi] Sin[phi] + Cos[theta] Cos[phi] Sin[psi], Sin[psi] Sin[theta],0 } , { -Sin[psi] Cos[phi] - Cos[theta] Sin[phi] Cos[psi], -Sin[psi] Sin[phi] + Cos[theta] Cos[phi] Cos[psi], Cos[psi] Sin[theta],0 } , { Sin[theta] Sin[phi], -Sin[theta] Cos[phi], Cos[theta],0 },{0,0,0,1} }] (******************************************************) scalingMatrix3D[{sx_,sy_,sz_}] := { {sx,0,0,0},{0,sy,0,0},{0,0,sz,0},{0,0,0,1} }; (******************************************************) translationMatrix3D [{tx_,ty_,tz_}] := Transpose[ { {1,0,0,0},{0,1,0,0},{0,0,1,0},{tx,ty,tz,1} }]; (* ;[s] 1:0,1;1963,-1; 2:0,16,11,Courier,1,14,0,0,0;1,14,10,Courier,1,12,0,0,0; :[font = section; inactive; preserveAspect] Create a "view of the viewing" :[font = input; dontPreserveAspect; startGroup] Clear [display,scene,vpn,vup,cop,u,v, umin,umax,vmin,vmax, windowcorners2D,windowcorners3D,pyramidedges] :[font = input; preserveAspect] range=8; :[font = input; preserveAspect; endGroup] Off[General::spell1] :[font = input; dontPreserveAspect] display[scene_List]:= Show[Graphics3D[{ PointSize[0.02], scene, RGBColor[1,0,0], Line[{{0,0,10},{0,0,0},{0,10,0},{0,0,0},{10,0,0}}]}], PlotRange->Automatic, AxesLabel->{"X","Y","Z"}] ;[s] 2:0,0;181,1;183,-1; 2:1,16,11,Courier,1,14,0,0,0;1,19,14,New York,1,14,0,0,0; :[font = text; inactive; dontPreserveAspect] Setting up a perspective viewing starts with assigning values in the World coordinate system to several scenes: 1) The vpn, a vector normal (i.e., perpendicular) to the intended viewplane. It will completely determine the orientation of the viewplane. 2) The vrp (View Reference Point), to completely deternine the plane itself. The vrp will become the origin of the local 2D viewing coordinate system (VC). 3) The View-Up Vector, or vup, to orient the VC system on the viewplane. This vector must be distinct from, but not necesarily orthogonal to, the vpn. 4) The cop, or center of projection, the viewer eye's positon, specified either in absolute World Coordinates (as in this notebook) or as a displacement in WC from the VRP. 5) The window boundaries in the form of relative displacements from the vrp in the x and y directions of the viewing system (uv). Typical packages would expect something like ;[s] 11:0,2;119,3;126,2;135,1;140,2;263,3;266,2;442,3;445,2;574,3;577,2;919,-1; 4:0,17,12,New York,0,12,0,0,0;1,14,10,New York,2,10,0,0,0;6,14,10,New York,0,10,0,0,0;4,14,10,New York,1,10,0,0,0; :[font = input; dontPreserveAspect] windowcorners2D = {{umin, vmin},{umin,vmax}, {umax,vmax},{umax,vmin}}; :[font = text; inactive; dontPreserveAspect] We can now calculate two unit vectors u and v, that define the respective x and y axes of the two dimensional VC system lying on the viewplane. We can derive them simply from the vpn and the vup: u will be the normalized cross-product vector of the vup by the vpn. ;[s] 16:0,1;38,2;39,1;44,2;45,1;180,2;183,1;192,2;195,1;197,2;198,1;250,2;253,1;261,2;264,1;266,0;267,-1; 3:1,17,12,New York,0,12,0,0,0;8,14,10,New York,0,10,0,0,0;7,14,10,New York,1,10,0,0,0; :[font = input; dontPreserveAspect] u := normalize[Cross[vup,vpn]]; :[font = text; inactive; dontPreserveAspect] Then v will be the cross-product vector of u by the vpn. ;[s] 2:0,1;56,0;57,-1; 2:1,17,12,New York,0,12,0,0,0;1,14,10,New York,0,10,0,0,0; :[font = input; dontPreserveAspect] v := normalize[Cross[vpn,u]]//N; :[font = input; preserveAspect] n:= Cross[u,v] :[font = text; inactive; dontPreserveAspect] The projection is made on a rectangular window, we can view that window as the base of a viewing pyramid whose apex is the cop. ;[s] 4:0,2;90,1;105,2;128,0;129,-1; 3:1,17,12,New York,0,12,0,0,0;1,14,10,New York,2,10,0,0,0;2,14,10,New York,0,10,0,0,0; :[font = text; inactive; dontPreserveAspect] and then calculate the four 3D world coordinates of the window corners by adding their displacements (relative coordinates) to the absolute coordinates of the vrp: ;[s] 2:0,1;164,0;165,-1; 2:1,17,12,New York,0,12,0,0,0;1,14,10,New York,0,10,0,0,0; :[font = input; dontPreserveAspect] windowcorners3D := Map[(vrp+#)&,(windowcorners2D.{u,v})]//N; :[font = text; inactive; dontPreserveAspect] The view pyramid edges are lines connecting the COP to these four window corners: ;[s] 2:0,1;81,0;82,-1; 2:1,17,12,New York,0,12,0,0,0;1,14,10,New York,0,10,0,0,0; :[font = input; dontPreserveAspect] pyramidedges := Map[Function [Append[{cop},#]],windowcorners3D ]; :[font = input; dontPreserveAspect] :[font = text; inactive; dontPreserveAspect] A parenthesis is in order. We have just made an important step. We have in fact obtained and used a parametric equation for the view plane. In vector form the plane equation is P = vrp + uu*u + vv*v where uu and vv are the parameters, i.e., the local coordinates that measure the displacement on the viewing plane in the respective (orthogonal) directions u and v. We could apply this knowledge to the projection problem by reversely finding the coordinates (uu,vv) of projected points as the intersections between the view plane and the rays that connects the COP and the points. We could do so for instance for each of the vertices of a polyhedron to obtain their local viewing coordinates. All that would then be left to do is to plot in 2D to get the projected polyhedron. This general method is the essence of what is called ray tracing and is an important and sometimes the only applicable option in advanced graphics. It is however considerably more demanding in computing resources than the transformation matrix strategy that we are pursuing at this time. ;[s] 16:0,1;194,2;204,1;206,2;211,1;213,2;216,1;374,2;375,1;380,2;381,1;558,2;562,1;853,2;864,1;1089,0;1090,-1; 3:1,17,12,New York,0,12,0,0,0;8,14,10,New York,2,10,0,0,0;7,14,10,New York,3,10,0,0,0; :[font = subsubtitle; inactive; dontPreserveAspect] Example :[font = section; inactive; preserveAspect] Choose viewing parameters and window boundaries :[font = input; dontPreserveAspect] vpn ={4,-1,3}; (* specify the normal direction*) vrp = {2,1,3}; vup = {6,2,-1}; cop = {-3,-1,-1}; umin=-4;umax=1; vmin=-4;vmax=2; ;[s] 3:0,0;15,1;49,0;131,-1; 2:2,16,11,Courier,1,14,0,0,0;1,16,11,Courier,0,14,0,0,0; :[font = text; inactive; dontPreserveAspect] Let us test our definitions with these values ;[s] 2:0,1;45,0;46,-1; 2:1,17,12,New York,0,12,0,0,0;1,14,10,New York,0,10,0,0,0; :[font = input; preserveAspect; startGroup] Chop[{u.v,v.n,n.u}]//N :[font = output; output; inactive; preserveAspect; endGroup] {4.163336342344337*10^-17, 0, 0} ;[o] -17 {4.16334 10 , 0, 0} :[font = input; preserveAspect; startGroup] Map[Apply[Plus,#^2]&,{u,v,n}] :[font = output; output; inactive; preserveAspect; endGroup] {1, 1., 1.} ;[o] {1, 1., 1.} :[font = input; dontPreserveAspect; startGroup] windowcorners2D (*viewing coordinates of the window corners*) ;[s] 3:0,0;16,1;61,0;62,-1; 2:2,16,11,Courier,1,14,0,0,0;1,16,11,Courier,0,14,0,0,0; :[font = output; output; inactive; dontPreserveAspect; endGroup] {{-4, -4}, {-4, 2}, {1, 2}, {1, -4}} ;[o] {{-4, -4}, {-4, 2}, {1, 2}, {1, -4}} :[font = input; dontPreserveAspect; startGroup] (*convert above to World Coordinate displacements*) (windowcorners2D.{u,v})//N ;[s] 2:0,1;51,0;80,-1; 2:1,16,11,Courier,1,14,0,0,0;1,16,11,Courier,0,14,0,0,0; :[font = output; output; inactive; preserveAspect; endGroup] {{-3.116815083862583, 1.216602027277482, 4.561287454242607}, {0.4285421761992277, 4.363106595582341, 0.882979296928476}, {1.370096647642614, 0.2202669212314391, -1.753373223113007}, {-2.175260612419197, -2.926237647073419, 1.924934934201123}} ;[o] {{-3.11682, 1.2166, 4.56129}, {0.428542, 4.36311, 0.882979}, {1.3701, 0.220267, -1.75337}, {-2.17526, -2.92624, 1.92493}} :[font = input; dontPreserveAspect] (*convert above to absolute World Coordinates*) windowcorners3D:= Map[Function[vrp+#],(windowcorners2D).{u,v}//N] ;[s] 2:0,1;48,0;115,-1; 2:1,16,11,Courier,1,14,0,0,0;1,16,11,Courier,0,14,0,0,0; :[font = input; preserveAspect; startGroup] windowcorners3D :[font = output; output; inactive; preserveAspect; endGroup] {{-1.116815083862583, 2.216602027277482, 7.561287454242607}, {2.428542176199228, 5.363106595582341, 3.882979296928476}, {3.370096647642614, 1.220266921231439, 1.246626776886993}, {-0.1752606124191969, -1.926237647073419, 4.924934934201124}} ;[o] {{-1.11682, 2.2166, 7.56129}, {2.42854, 5.36311, 3.88298}, {3.3701, 1.22027, 1.24663}, {-0.175261, -1.92624, 4.92493}} :[font = section; inactive; preserveAspect] Picking up a "scene" to view :[font = text; inactive; dontPreserveAspect] We pick a tetrahedron as the scene to be projected: ;[s] 1:0,1;52,-1; 2:0,17,12,New York,0,12,0,0,0;1,14,10,New York,0,10,0,0,0; :[font = input; dontPreserveAspect; startGroup] verticelist= N[ {{0, 0, 3^(1/2)}, {0, (2*2^(1/2)*3^(1/2))/3, -3^(1/2)/3}, {-2^(1/2), -(2^(1/2)*3^(1/2))/3, -3^(1/2)/3}, {2^(1/2), -(2^(1/2)*3^(1/2))/3, -3^(1/2)/3}} ]; :[font = input; dontPreserveAspect] facelist ={{1, 2, 3}, {1, 3, 4}, {1, 4, 2}, {2, 4, 3}}; verticelistH:=Map[homogenize,verticelist] :[font = input; preserveAspect; startGroup] verticelistH :[font = output; output; inactive; preserveAspect; endGroup] {{0, 0, 1.732050807568877, 1}, {0, 1.632993161855452, -0.5773502691896259, 1}, {-1.414213562373095, -0.816496580927726, -0.5773502691896259, 1}, {1.414213562373095, -0.816496580927726, -0.5773502691896259, 1}} ;[o] {{0, 0, 1.73205, 1}, {0, 1.63299, -0.57735, 1}, {-1.41421, -0.816497, -0.57735, 1}, {1.41421, -0.816497, -0.57735, 1}} :[font = text; inactive; dontPreserveAspect] We will use this volume as a primitive scene to be projected and transform it, along with the rest of the view data using homogeneous coordinate transformations. We initially scale and place the scene at the desired point ;[s] 1:0,1;223,-1; 2:0,17,12,New York,0,12,0,0,0;1,14,10,New York,0,10,0,0,0; :[font = input; dontPreserveAspect; startGroup] modelingMatrix = translationMatrix3D[{4,4,4}]. yRotationMatrix3D[Pi]. scalingMatrix3D[{1,0.7,2}] :[font = output; output; inactive; preserveAspect; endGroup] {{-1, 0., 0, 4}, {0, 0.7, 0, 4}, {0, 0., -2, 4}, {0, 0., 0, 1}} ;[o] {{-1, 0., 0, 4}, {0, 0.7, 0, 4}, {0, 0., -2, 4}, {0, 0., 0, 1}} :[font = input; dontPreserveAspect; startGroup] verticelist= Map[deHomogenize,Map[(modelingMatrix.#)&,verticelistH]] :[font = output; output; inactive; preserveAspect] {{4, 4., 0.5358983848622461}, {4., 5.143095213298817, 5.154700538379252}, {5.414213562373095, 3.428452393350592, 5.154700538379252}, {2.585786437626905, 3.428452393350592, 5.154700538379252}} ;[o] {{4, 4., 0.535898}, {4., 5.1431, 5.1547}, {5.41421, 3.42845, 5.1547}, {2.58579, 3.42845, 5.1547}} :[font = input; dontPreserveAspect; endGroup; endGroup] edgelist := Map[Function[verticelist[[#]]], facelist]; scene := Map[Polygon,edgelist]; :[font = input; preserveAspect; startGroup] Short[edgelist] :[font = output; output; inactive; preserveAspect; endGroup] Short["<<>>"] ;[o] {{{4, 4., 0.535898}, <<1>>, {5.41421, 3.42845, 5.1547}}, <<2>>, {<<3>>}} :[font = text; inactive; dontPreserveAspect] We can see how the viewing data looks. ;[s] 2:0,1;39,0;40,-1; 2:1,17,12,New York,0,12,0,0,0;1,14,10,New York,0,10,0,0,0; :[font = text; inactive; dontPreserveAspect] Now let us display the scene, the normal and view-up vectors, the VRP point the viewplane and the sides of the viewing pyramid. ;[s] 1:0,1;129,-1; 2:0,17,12,New York,0,12,0,0,0;1,14,10,New York,0,10,0,0,0; :[font = input; dontPreserveAspect; startGroup] display [{scene, PointSize[0.01],RGBColor[0,0,0],Point[cop], Line[{{0,0,0},vpn}],Point[vrp], RGBColor[0.7,0.7,0.2], Polygon[windowcorners3D], Thickness[0.004],Map[Line,pyramidedges], RGBColor[0,0,1], Line[{{0,0,0},vup}]}] ;[s] 5:0,1;17,0;61,1;80,0;200,1;223,-1; 2:2,16,11,Courier,1,14,0,0,0;3,19,14,New York,1,14,0,0,0; :[font = postscript; PostScript; formatAsPostScript; output; inactive; preserveAspect; pictureLeft = 34; pictureWidth = 273; pictureHeight = 277] %! %%Creator: Mathematica %%AspectRatio: 1.01733 MathPictureStart %% Graphics3D /Courier findfont 10 scalefont setfont % Scaling calculations -0.000611066 1.04153 0.0260382 1.04153 [ [ 0 0 0 0 ] [ 1 1.01733 0 0 ] ] MathScale % Start of Graphics 1 setlinecap 1 setlinejoin newpath [ ] 0 setdash 0 g 0 0 m 1 0 L 1 1.01733 L 0 1.01733 L closepath clip newpath p .002 w .09663 .26435 m .02604 .72972 L s .02604 .72972 m .38369 .9913 L s .38369 .9913 m .40013 .56736 L s .40013 .56736 m .09663 .26435 L s .68003 .02604 m .91371 .40111 L s .91371 .40111 m .97396 .84945 L s .97396 .84945 m .7106 .51419 L s .7106 .51419 m .68003 .02604 L s .09663 .26435 m .02604 .72972 L s .02604 .72972 m .7106 .51419 L s .7106 .51419 m .68003 .02604 L s .68003 .02604 m .09663 .26435 L s .40013 .56736 m .91371 .40111 L s .91371 .40111 m .97396 .84945 L s .97396 .84945 m .38369 .9913 L s .38369 .9913 m .40013 .56736 L s P p 0 0 0 r .01 w .14219 .30346 Mdot P p .002 w .35529 .64653 m .50555 .56999 L .48361 .4841 L p .839 .716 .728 r F P s P p .002 w .46627 .56992 m .56708 .59353 L .5448 .42726 L p .785 .557 .592 r F P s P p .002 w .52056 .43731 m .46627 .56992 L p .5448 .42726 L .785 .557 .592 r F P s P p .002 w .53983 .39025 m .56708 .59353 L .59048 .5303 L closepath p 0 0 .488 r F P s P p .002 w .59048 .5303 m .46627 .56992 L .52056 .43731 L p .514 .261 .469 r F P s P p .002 w .5448 .42726 m .53983 .39025 L .52056 .43731 L p .785 .557 .592 r F P s P p .002 w .52056 .43731 m .53983 .39025 L .54546 .4058 L p .514 .261 .469 r F P s P p .002 w .54546 .4058 m .59048 .5303 L p .52056 .43731 L .514 .261 .469 r F P s P p .002 w .27277 .68856 m .35529 .64653 L p .47634 .45567 L .839 .716 .728 r F P s P p .002 w .48361 .4841 m .47634 .45567 L p .35529 .64653 L .839 .716 .728 r F P s P p .002 w .47634 .45567 m .44911 .34909 L p .37105 .49937 L .839 .716 .728 r F P s P p .27277 .68856 m .47634 .45567 L .37105 .49937 L .839 .716 .728 r F P p .7 .7 .2 r .004 w .14219 .30346 m .3816 .47907 L s P p 1 0 0 r .004 w .28216 .32107 m .39875 .44604 L s P p 1 0 0 r .004 w .28216 .32107 m .71662 .1553 L s P p 0 0 1 r .004 w .28216 .32107 m .57897 .2499 L s P p 0 0 0 r .004 w .28216 .32107 m .41824 .34039 L s P p .002 w .56708 .59353 m .46627 .56992 L .59048 .5303 L closepath p .654 .754 .924 r F P s P p .002 w .44911 .34909 m .20294 .45685 L .27277 .68856 L p .839 .716 .728 r F P s P p 1 0 0 r .004 w .27339 .42601 m .28216 .32107 L s P p 1 0 0 r .004 w .2482 .72758 m .26518 .52434 L s P p .7 .7 .2 r .004 w .14219 .30346 m .44911 .34909 L s P p .7 .7 .2 r .004 w .14219 .30346 m .27277 .68856 L s P p .7 .7 .2 r .004 w .14219 .30346 m .20294 .45685 L s P p 0 0 0 r .01 w .38323 .42965 Mdot P p .002 w .68003 .02604 m .91371 .40111 L s .91371 .40111 m .97396 .84945 L s .97396 .84945 m .7106 .51419 L s .7106 .51419 m .68003 .02604 L s .09663 .26435 m .02604 .72972 L s .02604 .72972 m .7106 .51419 L s .7106 .51419 m .68003 .02604 L s .68003 .02604 m .09663 .26435 L s P p P % End of Graphics MathPictureEnd :[font = output; output; inactive; dontPreserveAspect] Graphics3D["<<>>"] ;[o] -Graphics3D- :[font = section; inactive; preserveAspect] Step 1 toward Canonical Projection Make COP and Axes Origin to coincide, by appropriate tranlation :[font = input; preserveAspect; startGroup] cop :[font = output; output; inactive; preserveAspect; endGroup] {-3, -1, -1} ;[o] {-3, -1, -1} :[font = input; preserveAspect; startGroup] translationMatrix3D[-cop] :[font = output; output; inactive; preserveAspect; endGroup] {{1, 0, 0, 3}, {0, 1, 0, 1}, {0, 0, 1, 1}, {0, 0, 0, 1}} ;[o] {{1, 0, 0, 3}, {0, 1, 0, 1}, {0, 0, 1, 1}, {0, 0, 0, 1}} :[font = input; dontPreserveAspect; startGroup] MatrixForm[tran=translationMatrix3D[-cop]] :[font = output; output; inactive; preserveAspect; endGroup] MatrixForm[{{1, 0, 0, 3}, {0, 1, 0, 1}, {0, 0, 1, 1}, {0, 0, 0, 1}}] ;[o] 1 0 0 3 0 1 0 1 0 0 1 1 0 0 0 1 :[font = text; inactive; preserveAspect] Check the result and transform the relevant points: cop,vpn, vrp, vup, windowcorners3D and the vertices of the scene; cop should move to the origin and stay there. :[font = input; dontPreserveAspect; startGroup] cop= deHomogenize[tran.homogenize[cop]] :[font = output; output; inactive; preserveAspect; endGroup] {0, 0, 0} ;[o] {0, 0, 0} :[font = input; dontPreserveAspect; startGroup] vrp = deHomogenize[tran.homogenize[vrp]] :[font = output; output; inactive; preserveAspect; endGroup] {5, 2, 4} ;[o] {5, 2, 4} :[font = input; dontPreserveAspect; startGroup] verticelist = Map[deHomogenize,Map[(tran.#)&,verticelistH]] :[font = output; output; inactive; preserveAspect; endGroup] {{7., 5., 1.535898384862246}, {7., 6.143095213298817, 6.154700538379252}, {8.4142135623731, 4.428452393350592, 6.154700538379252}, {5.585786437626905, 4.428452393350592, 6.154700538379252}} ;[o] {{7., 5., 1.5359}, {7., 6.1431, 6.1547}, {8.41421, 4.42845, 6.1547}, {5.58579, 4.42845, 6.1547}} :[font = input; dontPreserveAspect; startGroup] display [{scene, PointSize[0.01],RGBColor[0,0,0],Point[cop], Line[{{0,0,0},vpn}], RGBColor[0.7,0.7,0.2], Polygon[windowcorners3D],Point[vrp], Thickness[0.003],Map[Line,pyramidedges], RGBColor[0,0,1], Line[{{0,0,0},vup}]}] ;[s] 5:0,1;17,0;61,1;80,0;200,1;223,-1; 2:2,16,11,Courier,1,14,0,0,0;3,19,14,New York,1,14,0,0,0; :[font = postscript; PostScript; formatAsPostScript; output; inactive; preserveAspect; pictureLeft = 34; pictureWidth = 259; pictureHeight = 292] %! %%Creator: Mathematica %%AspectRatio: 1.12597 MathPictureStart %% Graphics3D /Courier findfont 10 scalefont setfont % Scaling calculations -0.0438533 1.14266 0.0285666 1.14266 [ [ 0 0 0 0 ] [ 1 1.12597 0 0 ] ] MathScale % Start of Graphics 1 setlinecap 1 setlinejoin newpath [ ] 0 setdash 0 g 0 0 m 1 0 L 1 1.12597 L 0 1.12597 L closepath clip newpath p .002 w .11284 .25196 m .02857 .81221 L s .02857 .81221 m .4259 1.0974 L s .4259 1.0974 m .44016 .59152 L s .44016 .59152 m .11284 .25196 L s .64414 .02857 m .90344 .43991 L s .90344 .43991 m .97143 .97243 L s .97143 .97243 m .67108 .61368 L s .67108 .61368 m .64414 .02857 L s .11284 .25196 m .02857 .81221 L s .02857 .81221 m .67108 .61368 L s .67108 .61368 m .64414 .02857 L s .64414 .02857 m .11284 .25196 L s .44016 .59152 m .90344 .43991 L s .90344 .43991 m .97143 .97243 L s .97143 .97243 m .4259 1.0974 L s .4259 1.0974 m .44016 .59152 L s P p 1 0 0 r .004 w .44249 .63032 m .15989 .34353 L s P p 1 0 0 r .004 w .15989 .34353 m .66741 .14181 L s P p 1 0 0 r .004 w .09702 .83063 m .15989 .34353 L s P p 0 0 1 r .003 w .15989 .34353 m .50984 .25919 L s P p 0 0 0 r .004 w .15989 .34353 m .30913 .36357 L s P p 0 0 0 r .01 w .15989 .34353 Mdot P p .002 w .42068 .76123 m .59935 .66565 L .57427 .56225 L p .844 .721 .728 r F P s P p .002 w .5564 .66801 m .67762 .69595 L .64668 .49307 L p .787 .557 .588 r F P s P p .002 w .61817 .50536 m .5564 .66801 L p .64668 .49307 L .787 .557 .588 r F P s P p .002 w .63985 .44827 m .67762 .69595 L .71124 .62073 L closepath p .029 .029 .521 r F P s P p .002 w .71124 .62073 m .5564 .66801 L .61817 .50536 L p .519 .268 .475 r F P s P p .002 w .64668 .49307 m .63985 .44827 L .61817 .50536 L p .787 .557 .588 r F P s P p .002 w .61817 .50536 m .63985 .44827 L .64767 .46715 L p .519 .268 .475 r F P s P p .002 w .64767 .46715 m .71124 .62073 L p .61817 .50536 L .519 .268 .475 r F P s P p .002 w .32123 .81443 m .42068 .76123 L p .56593 .52789 L .844 .721 .728 r F P s P p .002 w .57427 .56225 m .56593 .52789 L p .42068 .76123 L .844 .721 .728 r F P s P p .002 w .56593 .52789 m .53455 .3985 L p .44043 .58201 L .844 .721 .728 r F P s P p .32123 .81443 m .56593 .52789 L .44043 .58201 L .844 .721 .728 r F P p .7 .7 .2 r .003 w .15989 .34353 m .45267 .55814 L s P p .002 w .67762 .69595 m .5564 .66801 L .71124 .62073 L closepath p .649 .76 .93 r F P s P p .002 w .53455 .3985 m .23707 .53156 L .32123 .81443 L p .844 .721 .728 r F P s P p .7 .7 .2 r .003 w .15989 .34353 m .53455 .3985 L s P p .7 .7 .2 r .003 w .15989 .34353 m .32123 .81443 L s P p .7 .7 .2 r .003 w .15989 .34353 m .23707 .53156 L s P p .7 .7 .2 r .01 w .45545 .4969 Mdot P p .002 w .64414 .02857 m .90344 .43991 L s .90344 .43991 m .97143 .97243 L s .97143 .97243 m .67108 .61368 L s .67108 .61368 m .64414 .02857 L s .11284 .25196 m .02857 .81221 L s .02857 .81221 m .67108 .61368 L s .67108 .61368 m .64414 .02857 L s .64414 .02857 m .11284 .25196 L s P p P % End of Graphics MathPictureEnd :[font = output; output; inactive; dontPreserveAspect; endGroup; endGroup] Graphics3D["<<>>"] ;[o] -Graphics3D- :[font = text; inactive; dontPreserveAspect] Step 2 toward Canonical Projection Rotate so that axes {u,v,n,} and {x,y,y} coincide ;[s] 1:0,1;88,-1; 2:0,17,12,New York,0,12,0,0,0;1,19,14,New York,1,14,0,0,0; :[font = text; inactive; dontPreserveAspect] The scene has not changed, except for the new location of the axes origin. We will now compute transformation matrices to apply to all point coordinates such that the normal vector will be made to coincide with the positive z axis and that the projection of the VUP on the viewplane align with the y axis. ;[s] 1:0,1;306,-1; 2:0,17,12,New York,0,12,0,0,0;1,14,10,New York,0,10,0,0,0; :[font = text; inactive; dontPreserveAspect] This is another case of general rotation problem. It can be solved simply by using the properties of orthogonal vectors. A 3x3 composite rotation matrix has the form rot = {{r1x, r1y, r1z}, {r2x, r2y, r2z}, {r3x, r3y, r3z}} These matrices are orthogonal. Its rows and columns are mutually orthogonal unit vectors and have the following property: If the rotation matrix is applied to the row vectors they relocate respectively along the x, y and z axis. Hence if we know the components of the unit vectors that are to be rotated into the axes, as in this case, we can form the composite matrix directly: ;[s] 1:0,1;630,-1; 2:0,17,12,New York,0,12,0,0,0;1,14,10,New York,0,10,0,0,0; :[font = input; dontPreserveAspect; startGroup] {r1x,r2x,r3x} = u//N {r1y,r2y,r3y} = v//N {r1z,r2z,r3z} = n//N :[font = output; output; inactive; preserveAspect] {0.1883108942886773, -0.82856793487018, -0.5272705040082966} ;[o] {0.188311, -0.828568, -0.527271} :[font = output; output; inactive; preserveAspect] {0.5908928766769686, 0.5244174280508097, -0.6130513595523551} ;[o] {0.590893, 0.524417, -0.613051} :[font = output; output; inactive; preserveAspect] {0.7844645405527363, -0.196116135138184, 0.5883484054145522} ;[o] {0.784465, -0.196116, 0.588348} :[font = text; inactive; dontPreserveAspect] and the homogeneous composite matrix is ;[s] 2:0,1;40,0;41,-1; 2:1,17,12,New York,0,12,0,0,0;1,14,10,New York,0,10,0,0,0; :[font = input; dontPreserveAspect; endGroup] rot={{r1x,r2x,r3x,0},{r1y,r2y,r3y,0}, {r1z,r2z,r3z,0},{0,0,0,1}}; ;[s] 2:0,1;5,0;71,-1; 2:1,16,11,Courier,1,14,0,0,0;1,19,14,New York,1,14,0,0,0; :[font = input; preserveAspect; startGroup] Map[(Apply[Plus,#^2])&,rot] :[font = output; output; inactive; preserveAspect; endGroup] {1., 1., 1., 1} ;[o] {1., 1., 1., 1} :[font = input; dontPreserveAspect; startGroup] vrp = Chop[deHomogenize[rot.homogenize[vrp]]] :[font = output; output; inactive; preserveAspect; endGroup] {-2.82466341433016, 1.551093801277042, 5.883484054145522} ;[o] {-2.82466, 1.55109, 5.88348} :[font = input; dontPreserveAspect] verticelist = Map[deHomogenize,Map[(rot.#)&,verticelistH]]; :[font = input; dontPreserveAspect; startGroup] vpn = Chop[deHomogenize[rot.homogenize[vpn]]]//N :[font = output; output; inactive; preserveAspect; endGroup] {0, 0, 5.099019513592786} ;[o] {0, 0, 5.09902} :[font = input; dontPreserveAspect; startGroup] vup = Chop[deHomogenize[rot.homogenize[vup]]] :[font = output; output; inactive; preserveAspect; endGroup] {0, 5.207243475715785, 3.726206567625498} ;[o] {0, 5.20724, 3.72621} :[font = input; preserveAspect; startGroup] {u, v, n} :[font = output; output; inactive; preserveAspect; endGroup] {{1., 0, 0}, {0, 1., 0}, {0, 0, 1.}} ;[o] {{1., 0, 0}, {0, 1., 0}, {0, 0, 1.}} :[font = input; dontPreserveAspect; startGroup] display [{scene, PointSize[0.01],RGBColor[0,0,0], Point[cop], Line[{{0,0,0},vpn}], RGBColor[0.7,0.7,0.2], Polygon[windowcorners3D],Point[vrp], Thickness[0.003],Map[Line,pyramidedges], RGBColor[0,0,1], Line[{{0,0,0},vup}]}] ;[s] 5:0,1;17,0;62,1;81,0;201,1;224,-1; 2:2,16,11,Courier,1,14,0,0,0;3,19,14,New York,1,14,0,0,0; :[font = postscript; PostScript; formatAsPostScript; output; inactive; preserveAspect; pictureLeft = 122; pictureTop = 20; pictureWidth = 344; pictureHeight = 305] %! %%Creator: Mathematica %%AspectRatio: .88883 MathPictureStart %% Graphics3D /Courier findfont 10 scalefont setfont % Scaling calculations 0.0242847 0.97139 -0.00677936 0.97139 [ [ 0 0 0 0 ] [ 1 .88883 0 0 ] ] MathScale % Start of Graphics 1 setlinecap 1 setlinejoin newpath [ ] 0 setdash 0 g 0 0 m 1 0 L 1 .88883 L 0 .88883 L closepath clip newpath p .002 w .07262 .2749 m .02428 .6274 L s .02428 .6274 m .32973 .86455 L s .32973 .86455 m .34534 .53712 L s .34534 .53712 m .07262 .2749 L s .72248 .02428 m .93109 .35018 L s .93109 .35018 m .97572 .69617 L s .97572 .69617 m .74924 .39432 L s .74924 .39432 m .72248 .02428 L s .07262 .2749 m .02428 .6274 L s .02428 .6274 m .74924 .39432 L s .74924 .39432 m .72248 .02428 L s .72248 .02428 m .07262 .2749 L s .34534 .53712 m .93109 .35018 L s .93109 .35018 m .97572 .69617 L s .97572 .69617 m .32973 .86455 L s .32973 .86455 m .34534 .53712 L s P p 1 0 0 r .004 w .57007 .46516 m .38386 .25279 L s P p .002 w .12534 .5152 m .21702 .59489 L .28331 .57394 L p .653 .754 .924 r F P s P p .002 w .2073 .59333 m .20567 .66544 L .34127 .60373 L p .822 .785 .817 r F P s P p .002 w .32851 .59074 m .2073 .59333 L p .34127 .60373 L .822 .785 .817 r F P s P p .002 w .37184 .58982 m .20567 .66544 L .25776 .69735 L closepath p .592 .25 .359 r F P s P p .002 w .25776 .69735 m .2073 .59333 L .32851 .59074 L p .827 .598 .592 r F P s P p .002 w .34127 .60373 m .37184 .58982 L .32851 .59074 L p .822 .785 .817 r F P s P p .002 w .32851 .59074 m .37184 .58982 L .35888 .60204 L p .827 .598 .592 r F P s P p .002 w .35888 .60204 m .25776 .69735 L p .32851 .59074 L .827 .598 .592 r F P s P p .002 w .07477 .47124 m .12534 .5152 L p .30518 .56703 L .653 .754 .924 r F P s P p .002 w .28331 .57394 m .30518 .56703 L p .12534 .5152 L .653 .754 .924 r F P s P p .002 w .30518 .56703 m .38687 .54121 L p .24951 .51042 L .653 .754 .924 r F P s P p .07477 .47124 m .30518 .56703 L .24951 .51042 L .653 .754 .924 r F P p .7 .7 .2 r .003 w .25736 .51218 m .38386 .25279 L s P p 0 0 1 r .003 w .38386 .25279 m .48505 .48432 L s P p .002 w .20567 .66544 m .2073 .59333 L .25776 .69735 L closepath p .335 .371 .75 r F P s P p 1 0 0 r .004 w .38386 .25279 m .75588 .11587 L s P p 0 0 0 r .01 w .38386 .25279 Mdot P p .002 w .38687 .54121 m .25253 .40936 L .07477 .47124 L p .653 .754 .924 r F P s P p 0 0 0 r .004 w .37734 .41654 m .38386 .25279 L s P p .7 .7 .2 r .003 w .07477 .47124 m .38386 .25279 L s P p .7 .7 .2 r .003 w .38386 .25279 m .38687 .54121 L s P p .7 .7 .2 r .003 w .25253 .40936 m .38386 .25279 L s P p 1 0 0 r .004 w .37628 .44324 m .38386 .25279 L s P p 1 0 0 r .004 w .3704 .59071 m .37628 .44324 L s P p .7 .7 .2 r .01 w .30885 .51088 Mdot P p .002 w .72248 .02428 m .93109 .35018 L s .93109 .35018 m .97572 .69617 L s .97572 .69617 m .74924 .39432 L s .74924 .39432 m .72248 .02428 L s .07262 .2749 m .02428 .6274 L s .02428 .6274 m .74924 .39432 L s .74924 .39432 m .72248 .02428 L s .72248 .02428 m .07262 .2749 L s P p P % End of Graphics MathPictureEnd :[font = output; output; inactive; dontPreserveAspect; endGroup] Graphics3D["<<>>"] ;[o] -Graphics3D- :[font = text; inactive; dontPreserveAspect] Now the vpn is on the z axis and the pyramid base is parallel the the xy plane. The vup is in the yz plane, pointing toward the "up" direction of the view plane. ;[s] 1:0,1;165,-1; 2:0,17,12,New York,0,12,0,0,0;1,14,10,New York,0,10,0,0,0; :[font = input; preserveAspect] Step 3 toward Canonical Projection: Shear to center the viewing pyramid ;[s] 1:0,1;74,-1; 2:0,16,11,Courier,1,14,0,0,0;1,19,14,New York,1,14,0,0,0; :[font = text; inactive; dontPreserveAspect] The pyramid is still skewed however since the vrp doesnot line up with the vpn and since the window selcted was not centered on the vrp anyway. To correct this (on our way to a normalized pyramid), we need to shear the whole scene. The shear coefficients are derived from the position of the center line of the view volume which also define the center (cx,cy,cz) of the window ;[s] 4:0,2;211,1;216,2;380,0;381,-1; 3:1,17,12,New York,0,12,0,0,0;1,14,10,New York,2,10,0,0,0;2,14,10,New York,0,10,0,0,0; :[font = input; preserveAspect; startGroup] vrp :[font = output; output; inactive; preserveAspect; endGroup] {-2.82466341433016, 1.551093801277042, 5.883484054145522} ;[o] {-2.82466, 1.55109, 5.88348} :[font = input; dontPreserveAspect; startGroup] cx = vrp[[1]] + 0.5 (umin+umax) :[font = output; output; inactive; preserveAspect] -4.324663414330161 ;[o] -4.32466 :[font = input; dontPreserveAspect; startGroup] cy = vrp[[2]] + 0.5 (vmin+vmax); MatrixForm[shear = {{1,0,-cx/vrp[[3]],0}, {0,1,-cy/vrp[[3]],0}, {0,0,1,0},{0,0,0,1}}] :[font = output; output; inactive; preserveAspect; endGroup] MatrixForm[{{1, 0, 0.7350514379796761, 0}, {0, 1, -0.0936679348843887, 0}, {0, 0, 1, 0}, {0, 0, 0, 1}}] ;[o] 1 0 0.735051 0 0 1 -0.0936679 0 0 0 1 0 0 0 0 1 :[font = input; preserveAspect; startGroup] verticelist :[font = output; output; inactive; preserveAspect; endGroup; endGroup] {{-3.634497329822005, 5.816752684018763, 5.414314473790723}, {-7.016987509464511, 3.584648796077174, 7.90759994041063}, {-5.329977628454374, 3.521108938520359, 9.35326945585177}, {-5.862601269745682, 1.849811498307916, 7.134468670950855}} ;[o] {{-3.6345, 5.81675, 5.41431}, {-7.01699, 3.58465, 7.9076}, {-5.32998, 3.52111, 9.35327}, {-5.8626, 1.84981, 7.13447}} :[font = input; dontPreserveAspect; startGroup] vrp = Chop[deHomogenize[shear.homogenize[vrp]]] :[font = output; output; inactive; preserveAspect; endGroup] {1.5, 1., 5.883484054145522} ;[o] {1.5, 1., 5.88348} :[font = input; preserveAspect; startGroup] vrp :[font = output; input; inactive; preserveAspect; endGroup] {1.5, 1., 5.883484054145522} ;[o] {1.5, 1., 5.88348} :[font = input; preserveAspect; startGroup] Chop[{u, v, n}]//N :[font = output; output; inactive; preserveAspect; endGroup] {{1., 0, 0}, {0, 1., 0}, {0, 0, 1.}} ;[o] {{1., 0, 0}, {0, 1., 0}, {0, 0, 1.}} :[font = input; dontPreserveAspect] verticelist = Map[deHomogenize,Map[(shear.#)&,verticelistH]]; :[font = input; dontPreserveAspect; startGroup] display [{scene, PointSize[0.01],RGBColor[0,0,0],Point[cop], Line[{{0,0,0},vpn}], RGBColor[0.7,0.7,0.2], Polygon[windowcorners3D],Point[vrp], Thickness[0.003],Map[Line,pyramidedges], RGBColor[0,0,1], Line[{{0,0,0},vup}]}] ;[s] 5:0,1;17,0;61,1;80,0;200,1;223,-1; 2:2,16,11,Courier,1,14,0,0,0;3,19,14,New York,1,14,0,0,0; :[font = postscript; PostScript; formatAsPostScript; output; inactive; preserveAspect; pictureLeft = 89; pictureWidth = 226; pictureHeight = 267] %! %%Creator: Mathematica %%AspectRatio: 1.18233 MathPictureStart %% Graphics3D /Courier findfont 10 scalefont setfont % Scaling calculations -0.0673578 1.20436 0.030109 1.20436 [ [ 0 0 0 0 ] [ 1 1.18233 0 0 ] ] MathScale % Start of Graphics 1 setlinecap 1 setlinejoin newpath [ ] 0 setdash 0 g 0 0 m 1 0 L 1 1.18233 L 0 1.18233 L closepath clip newpath p .002 w .09806 .22336 m .03011 .76851 L s .03011 .76851 m .50471 1.15222 L s .50471 1.15222 m .50806 .659 L s .50806 .659 m .09806 .22336 L s .5697 .03011 m .91845 .52875 L s .91845 .52875 m .96989 1.03963 L s .96989 1.03963 m .57562 .59158 L s .57562 .59158 m .5697 .03011 L s .09806 .22336 m .03011 .76851 L s .03011 .76851 m .57562 .59158 L s .57562 .59158 m .5697 .03011 L s .5697 .03011 m .09806 .22336 L s .50806 .659 m .91845 .52875 L s .91845 .52875 m .96989 1.03963 L s .96989 1.03963 m .50471 1.15222 L s .50471 1.15222 m .50806 .659 L s P p 1 0 0 r .004 w .62461 .62127 m .34918 .30437 L s P p 0 0 1 r .003 w .34918 .30437 m .50069 .65028 L s P p .002 w .16286 .60259 m .30058 .73031 L .40541 .69713 L p .653 .755 .925 r F P s P p .002 w .3372 .70617 m .35893 .80974 L .49198 .74423 L p .895 .789 .736 r F P s P p .002 w .47374 .72377 m .3372 .70617 L p .49198 .74423 L .895 .789 .736 r F P s P p .002 w .52112 .72988 m .35893 .80974 L .50536 .83744 L closepath p .471 .013 .082 r F P s P p .002 w .50536 .83744 m .3372 .70617 L .47374 .72377 L p .771 .301 .126 r F P s P p .002 w .49198 .74423 m .52112 .72988 L .47374 .72377 L p .895 .789 .736 r F P s P p .002 w .47374 .72377 m .52112 .72988 L .5194 .74157 L p .771 .301 .126 r F P s P p .002 w .5194 .74157 m .50536 .83744 L p .47374 .72377 L .771 .301 .126 r F P s P p .002 w .08496 .53034 m .16286 .60259 L p .44019 .68613 L .653 .755 .925 r F P s P p .002 w .40541 .69713 m .44019 .68613 L p .16286 .60259 L .653 .755 .925 r F P s P p .002 w .44019 .68613 m .57096 .64474 L p .35877 .59479 L .653 .755 .925 r F P s P p .08496 .53034 m .44019 .68613 L .35877 .59479 L .653 .755 .925 r F P p 1 0 0 r .004 w .66887 .1826 m .34918 .30437 L s P p .7 .7 .2 r .003 w .31716 .585 m .34918 .30437 L s P p 0 0 0 r .01 w .34918 .30437 Mdot P p .002 w .35893 .80974 m .3372 .70617 L .50536 .83744 L closepath p .438 .49 .816 r F P s P p .002 w .57096 .64474 m .37343 .42638 L .08496 .53034 L p .653 .755 .925 r F P s P p 0 0 0 r .004 w .34228 .43761 m .34918 .30437 L s P p .7 .7 .2 r .003 w .08496 .53034 m .34918 .30437 L s P p .7 .7 .2 r .003 w .34918 .30437 m .57096 .64474 L s P p .7 .7 .2 r .003 w .34918 .30437 m .37343 .42638 L s P p 1 0 0 r .004 w .33335 .60995 m .33444 .58906 L s P p 1 0 0 r .004 w .32265 .81672 m .33335 .60995 L s P p .7 .7 .2 r .01 w .45223 .59555 Mdot P p .002 w .5697 .03011 m .91845 .52875 L s .91845 .52875 m .96989 1.03963 L s .96989 1.03963 m .57562 .59158 L s .57562 .59158 m .5697 .03011 L s .09806 .22336 m .03011 .76851 L s .03011 .76851 m .57562 .59158 L s .57562 .59158 m .5697 .03011 L s .5697 .03011 m .09806 .22336 L s P p P % End of Graphics MathPictureEnd :[font = output; output; inactive; dontPreserveAspect; endGroup] Graphics3D["<<>>"] ;[o] -Graphics3D- :[font = input; preserveAspect] Apply the Perspective Transformation ;[s] 1:0,1;37,-1; 2:0,16,11,Courier,1,14,0,0,0;1,19,14,New York,1,14,0,0,0; :[font = text; inactive; dontPreserveAspect] We now have a regular pyramid with its centerline on the z-axis. Notice that the vrp is off-center as should be expected with the current window boundaries. The next step is to normalize the view volume so that the sloped planes between the pyramid edges have unity slopes. This can be accomplished by scaling. Since the window is not necessarily square, sx and sy must be calculated separately. In addition one can uniformly scale the view data without altering the relative appearance of the projected picture. This can be use to simplify clipping. Assuming that a back clipping plane is located a a distance b from the vieplane, it has z-coordionate vrp[[3]] + b. Uniform scaling can be combined with the non-uniform scaling defined above, so that the back plane is now at unit distance from the origin. The combined scaling matrix is (assuming b=10): ;[s] 2:0,1;863,0;864,-1; 2:1,17,12,New York,0,12,0,0,0;1,14,10,New York,0,10,0,0,0; :[font = input; preserveAspect; startGroup] vrp :[font = output; output; inactive; preserveAspect; endGroup] {1.5, 1., 5.883484054145522} ;[o] {1.5, 1., 5.88348} :[font = input; dontPreserveAspect; startGroup] MatrixForm[ per ={{1,0,0,0}, {0,1,0,0}, {0,0,1,0}, {0,0,1/vrp[[3]],0}}] :[font = output; output; inactive; preserveAspect; endGroup] MatrixForm[{{1, 0, 0, 0}, {0, 1, 0, 0}, {0, 0, 1, 0}, {0, 0, 0.1699673171197594, 0}}] ;[o] 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.169967 0 :[font = input; dontPreserveAspect; startGroup] vrp = deHomogenize[per.homogenize[vrp]] :[font = output; output; inactive; preserveAspect; endGroup] {1.5, 1., 5.883484054145522} ;[o] {1.5, 1., 5.88348} :[font = input; dontPreserveAspect] verticelist = Map[deHomogenize,Map[(per.#)&,verticelistH]]; :[font = input; preserveAspect; startGroup] windowcorners3D :[font = output; output; inactive; preserveAspect; endGroup] {{-2.5, -3., 5.883484054145522}, {-2.5, 3., 5.883484054145522}, {2.5, 3., 5.883484054145522}, {2.5, -3., 5.883484054145522}} ;[o] {{-2.5, -3., 5.88348}, {-2.5, 3., 5.88348}, {2.5, 3., 5.88348}, {2.5, -3., 5.88348}} :[font = input; preserveAspect; startGroup] pyramidedges :[font = output; output; inactive; preserveAspect; endGroup] {{{0, 0, 0}, {-2.5, -3., 5.883484054145522}}, {{0, 0, 0}, {-2.5, 3., 5.883484054145522}}, {{0, 0, 0}, {2.5, 3., 5.883484054145522}}, {{0, 0, 0}, {2.5, -3., 5.883484054145522}}} ;[o] {{{0, 0, 0}, {-2.5, -3., 5.88348}}, {{0, 0, 0}, {-2.5, 3., 5.88348}}, {{0, 0, 0}, {2.5, 3., 5.88348}}, {{0, 0, 0}, {2.5, -3., 5.88348}}} :[font = input; dontPreserveAspect; startGroup] display [{scene, PointSize[0.01],RGBColor[0,0,0],Point[cop], Line[{{0,0,0},vpn}], RGBColor[0.7,0.7,0.2], Polygon[windowcorners3D],Point[vrp], Thickness[0.003],Map[Line,pyramidedges], RGBColor[0,0,1], Line[{{0,0,0},vup}]}] ;[s] 5:0,1;17,0;61,1;80,0;200,1;223,-1; 2:2,16,11,Courier,1,14,0,0,0;3,19,14,New York,1,14,0,0,0; :[font = postscript; PostScript; formatAsPostScript; output; inactive; preserveAspect; pictureLeft = 89; pictureWidth = 404; pictureHeight = 524] %! %%Creator: Mathematica %%AspectRatio: 1.29724 MathPictureStart %% Graphics3D /Courier findfont 10 scalefont setfont % Scaling calculations -0.117099 1.31174 0.0327934 1.31174 [ [ 0 0 0 0 ] [ 1 1.29724 0 0 ] ] MathScale % Start of Graphics 1 setlinecap 1 setlinejoin newpath [ ] 0 setdash 0 g 0 0 m 1 0 L 1 1.29724 L 0 1.29724 L closepath clip newpath p .002 w .10148 .20103 m .03279 .8216 L s .03279 .8216 m .56219 1.26445 L s .56219 1.26445 m .55957 .70272 L s .55957 .70272 m .10148 .20103 L s .51209 .03279 m .91691 .58931 L s .91691 .58931 m .96721 1.16642 L s .96721 1.16642 m .50761 .6676 L s .50761 .6676 m .51209 .03279 L s .10148 .20103 m .03279 .8216 L s .03279 .8216 m .50761 .6676 L s .50761 .6676 m .51209 .03279 L s .51209 .03279 m .10148 .20103 L s .55957 .70272 m .91691 .58931 L s .91691 .58931 m .96721 1.16642 L s .96721 1.16642 m .56219 1.26445 L s .56219 1.26445 m .55957 .70272 L s P p 1 0 0 r .004 w .69149 .66001 m .38435 .29534 L s P p .002 w .59717 .82361 m .37647 .66833 L .39457 .71919 L closepath p .653 .755 .925 r F P s P p .002 w .59717 .82361 m .49612 .66396 L .37647 .66833 L closepath p .653 .755 .925 r F P s P p .002 w .59717 .82361 m .39457 .71919 L .49612 .66396 L closepath p .653 .755 .925 r F P s P p 0 0 1 r .003 w .38435 .29534 m .55577 .69129 L s P p 1 0 0 r .004 w .62684 .20298 m .38435 .29534 L s P p 0 0 0 r .01 w .38435 .29534 Mdot P p .002 w .08826 .5515 m .32927 .78206 L .64086 .68344 L p .653 .755 .925 r F P s P p .7 .7 .2 r .003 w .34833 .61359 m .38435 .29534 L s P p .002 w .39457 .71919 m .37647 .66833 L .49612 .66396 L closepath p .653 .755 .925 r F P s P p .002 w .64086 .68344 m .42124 .43149 L .08826 .5515 L p .653 .755 .925 r F P s P p .7 .7 .2 r .003 w .38435 .29534 m .64086 .68344 L s P p 1 0 0 r .004 w .36209 .87854 m .37198 .61924 L s P p 1 0 0 r .004 w .37856 .44688 m .38435 .29534 L s P p .7 .7 .2 r .003 w .08826 .5515 m .38435 .29534 L s P p .7 .7 .2 r .003 w .38435 .29534 m .42124 .43149 L s P p .7 .7 .2 r .01 w .50652 .62673 Mdot P p .002 w .51209 .03279 m .91691 .58931 L s .91691 .58931 m .96721 1.16642 L s .96721 1.16642 m .50761 .6676 L s .50761 .6676 m .51209 .03279 L s .10148 .20103 m .03279 .8216 L s .03279 .8216 m .50761 .6676 L s .50761 .6676 m .51209 .03279 L s .51209 .03279 m .10148 .20103 L s P p P % End of Graphics MathPictureEnd :[font = output; output; inactive; dontPreserveAspect; endGroup] Graphics3D["<<>>"] ;[o] -Graphics3D- :[font = text; inactive; dontPreserveAspect] Clipping can be made at this stage, ;[s] 1:0,1;36,-1; 2:0,17,12,New York,0,12,0,0,0;1,14,10,New York,0,10,0,0,0; :[font = input; dontPreserveAspect; startGroup] Map[Function[Drop[#,-1]],windowcorners3D] :[font = output; output; inactive; dontPreserveAspect; endGroup] {{-2.5, -3.}, {-2.5, 3.}, {2.5, 3.}, {2.5, -3.}} ;[o] {{-2.5, -3.}, {-2.5, 3.}, {2.5, 3.}, {2.5, -3.}} :[font = input; dontPreserveAspect; startGroup] windowcorners = Append[%,%[[1]]] ;[s] 3:0,0;23,1;25,0;33,-1; 2:2,16,11,Courier,1,14,0,0,0;1,17,12,New York,1,12,0,0,0; :[font = output; output; inactive; preserveAspect; endGroup] {{-2.5, -3.}, {-2.5, 3.}, {2.5, 3.}, {2.5, -3.}, {-2.5, -3.}} ;[o] {{-2.5, -3.}, {-2.5, 3.}, {2.5, 3.}, {2.5, -3.}, {-2.5, -3.}} :[font = input; preserveAspect; startGroup] verticelist2D=Map[Drop[#,-1]&,verticelist] :[font = output; output; inactive; preserveAspect; endGroup] {{0.3752239814427282, 5.769701163440289}, {-0.896179120848588, 2.11598902921031}, {0.971949314305558, 1.663788213025755}, {-0.5099672606637457, 0.974364779511592}} ;[o] {{0.375224, 5.7697}, {-0.896179, 2.11599}, {0.971949, 1.66379}, {-0.509967, 0.974365}} :[font = input; dontPreserveAspect; startGroup] edgelist2D = Map[Function[verticelist2D[[#]]], facelist] :[font = output; output; inactive; preserveAspect; endGroup] {{{0.3752239814427282, 5.769701163440289}, {-0.896179120848588, 2.11598902921031}, {0.971949314305558, 1.663788213025755}}, {{0.3752239814427282, 5.769701163440289}, {0.971949314305558, 1.663788213025755}, {-0.5099672606637457, 0.974364779511592}}, {{0.3752239814427282, 5.769701163440289}, {-0.5099672606637457, 0.974364779511592}, {-0.896179120848588, 2.11598902921031}} , {{-0.896179120848588, 2.11598902921031}, {-0.5099672606637457, 0.974364779511592}, {0.971949314305558, 1.663788213025755}} } ;[o] {{{0.375224, 5.7697}, {-0.896179, 2.11599}, {0.971949, 1.66379}}, {{0.375224, 5.7697}, {0.971949, 1.66379}, {-0.509967, 0.974365}}, {{0.375224, 5.7697}, {-0.509967, 0.974365}, {-0.896179, 2.11599}}, {{-0.896179, 2.11599}, {-0.509967, 0.974365}, {0.971949, 1.66379}}} :[font = text; inactive; dontPreserveAspect] Finally, here is a picture of the 2D window. Only a corner of the scene appears within the window. The rest would have been clipped. ;[s] 1:0,1;135,-1; 2:0,17,12,New York,0,12,0,0,0;1,14,10,New York,0,10,0,0,0; :[font = input; dontPreserveAspect; startGroup] Show [Graphics[{RGBColor[1,0,0],Map[Line,edgelist2D], RGBColor[1,0,0],Line[windowcorners]}], Axes->True,AxesOrigin->{0,0}, PlotRange->{{-4,4},{-4,4}}] :[font = postscript; PostScript; formatAsPostScript; output; inactive; preserveAspect; pictureLeft = 34; pictureWidth = 282; pictureHeight = 174] %! %%Creator: Mathematica %%AspectRatio: .61803 MathPictureStart %% Graphics /Courier findfont 10 scalefont setfont % Scaling calculations 0.5 0.125 0.309017 0.0772542 [ [(-4)] 0 .30902 0 2 Msboxa [(-3)] .125 .30902 0 2 Msboxa [(-2)] .25 .30902 0 2 Msboxa [(-1)] .375 .30902 0 2 Msboxa [(1)] .625 .30902 0 2 Msboxa [(2)] .75 .30902 0 2 Msboxa [(3)] .875 .30902 0 2 Msboxa [(4)] 1 .30902 0 2 Msboxa [(-4)] .4875 0 1 0 Msboxa [(-3)] .4875 .07725 1 0 Msboxa [(-2)] .4875 .15451 1 0 Msboxa [(-1)] .4875 .23176 1 0 Msboxa [(1)] .4875 .38627 1 0 Msboxa [(2)] .4875 .46353 1 0 Msboxa [(3)] .4875 .54078 1 0 Msboxa [(4)] .4875 .61803 1 0 Msboxa [ -0.001 -0.001 0 0 ] [ 1.001 .61903 0 0 ] ] MathScale % Start of Graphics 1 setlinecap 1 setlinejoin newpath [ ] 0 setdash 0 g p p .002 w 0 .30902 m 0 .31527 L s P [(-4)] 0 .30902 0 2 Mshowa p .002 w .125 .30902 m .125 .31527 L s P [(-3)] .125 .30902 0 2 Mshowa p .002 w .25 .30902 m .25 .31527 L s P [(-2)] .25 .30902 0 2 Mshowa p .002 w .375 .30902 m .375 .31527 L s P [(-1)] .375 .30902 0 2 Mshowa p .002 w .625 .30902 m .625 .31527 L s P [(1)] .625 .30902 0 2 Mshowa p .002 w .75 .30902 m .75 .31527 L s P [(2)] .75 .30902 0 2 Mshowa p .002 w .875 .30902 m .875 .31527 L s P [(3)] .875 .30902 0 2 Mshowa p .002 w 1 .30902 m 1 .31527 L s P [(4)] 1 .30902 0 2 Mshowa p .001 w .025 .30902 m .025 .31277 L s P p .001 w .05 .30902 m .05 .31277 L s P p .001 w .075 .30902 m .075 .31277 L s P p .001 w .1 .30902 m .1 .31277 L s P p .001 w .15 .30902 m .15 .31277 L s P p .001 w .175 .30902 m .175 .31277 L s P p .001 w .2 .30902 m .2 .31277 L s P p .001 w .225 .30902 m .225 .31277 L s P p .001 w .275 .30902 m .275 .31277 L s P p .001 w .3 .30902 m .3 .31277 L s P p .001 w .325 .30902 m .325 .31277 L s P p .001 w .35 .30902 m .35 .31277 L s P p .001 w .4 .30902 m .4 .31277 L s P p .001 w .425 .30902 m .425 .31277 L s P p .001 w .45 .30902 m .45 .31277 L s P p .001 w .475 .30902 m .475 .31277 L s P p .001 w .525 .30902 m .525 .31277 L s P p .001 w .55 .30902 m .55 .31277 L s P p .001 w .575 .30902 m .575 .31277 L s P p .001 w .6 .30902 m .6 .31277 L s P p .001 w .65 .30902 m .65 .31277 L s P p .001 w .675 .30902 m .675 .31277 L s P p .001 w .7 .30902 m .7 .31277 L s P p .001 w .725 .30902 m .725 .31277 L s P p .001 w .775 .30902 m .775 .31277 L s P p .001 w .8 .30902 m .8 .31277 L s P p .001 w .825 .30902 m .825 .31277 L s P p .001 w .85 .30902 m .85 .31277 L s P p .001 w .9 .30902 m .9 .31277 L s P p .001 w .925 .30902 m .925 .31277 L s P p .001 w .95 .30902 m .95 .31277 L s P p .001 w .975 .30902 m .975 .31277 L s P p .002 w 0 .30902 m 1 .30902 L s P p .002 w .5 0 m .50625 0 L s P [(-4)] .4875 0 1 0 Mshowa p .002 w .5 .07725 m .50625 .07725 L s P [(-3)] .4875 .07725 1 0 Mshowa p .002 w .5 .15451 m .50625 .15451 L s P [(-2)] .4875 .15451 1 0 Mshowa p .002 w .5 .23176 m .50625 .23176 L s P [(-1)] .4875 .23176 1 0 Mshowa p .002 w .5 .38627 m .50625 .38627 L s P [(1)] .4875 .38627 1 0 Mshowa p .002 w .5 .46353 m .50625 .46353 L s P [(2)] .4875 .46353 1 0 Mshowa p .002 w .5 .54078 m .50625 .54078 L s P [(3)] .4875 .54078 1 0 Mshowa p .002 w .5 .61803 m .50625 .61803 L s P [(4)] .4875 .61803 1 0 Mshowa p .001 w .5 .01545 m .50375 .01545 L s P p .001 w .5 .0309 m .50375 .0309 L s P p .001 w .5 .04635 m .50375 .04635 L s P p .001 w .5 .0618 m .50375 .0618 L s P p .001 w .5 .09271 m .50375 .09271 L s P p .001 w .5 .10816 m .50375 .10816 L s P p .001 w .5 .12361 m .50375 .12361 L s P p .001 w .5 .13906 m .50375 .13906 L s P p .001 w .5 .16996 m .50375 .16996 L s P p .001 w .5 .18541 m .50375 .18541 L s P p .001 w .5 .20086 m .50375 .20086 L s P p .001 w .5 .21631 m .50375 .21631 L s P p .001 w .5 .24721 m .50375 .24721 L s P p .001 w .5 .26266 m .50375 .26266 L s P p .001 w .5 .27812 m .50375 .27812 L s P p .001 w .5 .29357 m .50375 .29357 L s P p .001 w .5 .32447 m .50375 .32447 L s P p .001 w .5 .33992 m .50375 .33992 L s P p .001 w .5 .35537 m .50375 .35537 L s P p .001 w .5 .37082 m .50375 .37082 L s P p .001 w .5 .40172 m .50375 .40172 L s P p .001 w .5 .41717 m .50375 .41717 L s P p .001 w .5 .43262 m .50375 .43262 L s P p .001 w .5 .44807 m .50375 .44807 L s P p .001 w .5 .47898 m .50375 .47898 L s P p .001 w .5 .49443 m .50375 .49443 L s P p .001 w .5 .50988 m .50375 .50988 L s P p .001 w .5 .52533 m .50375 .52533 L s P p .001 w .5 .55623 m .50375 .55623 L s P p .001 w .5 .57168 m .50375 .57168 L s P p .001 w .5 .58713 m .50375 .58713 L s P p .001 w .5 .60258 m .50375 .60258 L s P p .002 w .5 0 m .5 .61803 L s P P 0 0 m 1 0 L 1 .61803 L 0 .61803 L closepath clip newpath p 1 0 0 r p .004 w s .46993 .61803 m .38798 .47249 L s .38798 .47249 m .62149 .43755 L s s .57905 .61803 m .62149 .43755 L s .62149 .43755 m .43625 .38429 L s s .50607 .61803 m .43625 .38429 L s .43625 .38429 m .38798 .47249 L s .38798 .47249 m .43625 .38429 L .62149 .43755 L s P .004 w .1875 .07725 m .1875 .54078 L .8125 .54078 L .8125 .07725 L .1875 .07725 L s P % End of Graphics MathPictureEnd :[font = output; output; inactive; preserveAspect; endGroup] Graphics["<<>>"] ;[o] -Graphics- ^*)