sourcedemos/rosetta/cube.xtl
1⍝!/usr/bin/env xetal
2⍝ A cube turning in space, drawn by the Geometry3D and Svg libraries:
3⍝ twelve frames as a wireframe, then twelve shaded, each shown with
4⍝ []S_HOW (the browser's pane shows them in turn; the command line
5⍝ writes cube-1.svg, cube-2.svg, ... under --draw). Every number here
6⍝ is computed by arrays: the eight corners are one matrix, a turn is
7⍝ one inner product, the faces are ordered far to near by their mean
8⍝ depth, and a face's shade is the angle between its normal and the
9⍝ light. The Rosetta stone's rehearsal (docs/rosetta.md).
10ᵍ⁼u̲se< "Geometry3D"
11ᵛ⁼u̲se< "Svg"
12
13size ← 300.0 ⍝ the picture is size by size
14eye ← 6.0 ⍝ the viewer's distance along z
15zoom ← 70.0 ⍝ pixels per unit
16light ← 0.3 0.5 0.8 ⍝ from the viewer's side, upper right
17
18cube ← ᵍc̲ube 2
19faces ← ᵍc̲ubeFaces @
20
21⍝ The screen points of a face: projected, zoomed, centered, y up.
22ᵘs̲creen ← { f →
23 p ← eye ᵍp̲roject f
24 xs ← (size ÷ 2) + zoom × 1 s̲elect p
25 ys ← (size ÷ 2) − zoom × 2 s̲elect p
26 (2 c̲at t̲ally xs) r̲eshape xs c̲at ys
27}
28
29⍝ The normal of a face: the cross product of two of its edges.
30ᵘn̲ormal ← { f →
31 u ← (2 s̲elect₂ f) − 1 s̲elect₂ f
32 w ← (4 s̲elect₂ f) − 1 s̲elect₂ f
33 ((1 o̲- u) × 2 o̲- w) − (2 o̲- u) × 1 o̲- w
34}
35
36⍝ How lit a face is, 0 to 1: the cosine of the angle between its
37⍝ outward normal and the light, and 0 when it faces away. The normal
38⍝ is turned outward by the side of the cube's center it is on.
39ᵘl̲it ← { f →
40 n ← ᵘn̲ormal f
41 center ← ('+ r̲/ o̲\ f) ÷ 4.0
42 outward ← n × (2.0 × f̲loat 0 < '+ r̲/ n × center) − 1.0
43 0 m̲ax ('+ r̲/ outward × light) ÷ ('+ r̲/ n × n) ^ 0.5
44}
45
46⍝ A face as a polygon, shaded (or, with fill "none", as a wireframe).
47ᵘp̲olygon ← { shaded f →
48 fill ← ᵛf̲ill "shaded" i̲f< "v:r_gb 3 r_eshape 40 + 200 * u:l_it f; \"none\""
49 (fill c̲at "#222" ᵛs̲troke 1.5) ᵛp̲olygon f̲loor 0.5 + ᵘs̲creen f
50}
51
52⍝ The cube turned by a degrees about x and 1.3 a about y, as a picture:
53⍝ its faces drawn far to near, so nearer faces cover farther ones.
54ᵘs̲cene ← { shaded a →
55 turned ← ((ᵍr̲otY 1.3 × a) ᵍt̲urn ᵍr̲otX a) ᵍt̲urn cube
56 solid ← faces ᵍs̲olid turned
57 polygons ← '{ i → shaded ᵘp̲olygon i s̲elect solid } m̲ap ᵍo̲rder solid
58 (size c̲at size) ᵛp̲icture d̲isclose '{ x y → e̲nclose (d̲isclose x) c̲at d̲isclose y } r̲/ polygons
59}
60
61ᵘf̲rame ← { shaded a → ⎕S̲HOW shaded ᵘs̲cene a◆ ⎕D̲L 0.04◆ @ }
62
63angles ← 30.0 × f̲loat o̲ffsets 12
64shown ← '{ a → 0 ᵘf̲rame a } e̲ach angles
65shown ← '{ a → 1 ᵘf̲rame a } e̲ach angles
66"24 frames shown"