3 <title>Overview - Sketch
</title>
4 <meta http-equiv=
"Content-Type" content=
"text/html">
5 <meta name=
"description" content=
"Sketch">
6 <meta name=
"generator" content=
"makeinfo 4.7">
7 <link title=
"Top" rel=
"start" href=
"index.html#Top">
8 <link rel=
"up" href=
"Building-a-drawing.html#Building-a-drawing" title=
"Building a drawing">
9 <link rel=
"prev" href=
"Building-a-drawing.html#Building-a-drawing" title=
"Building a drawing">
10 <link rel=
"next" href=
"A-technical-drawing.html#A-technical-drawing" title=
"A technical drawing">
11 <link href=
"http://www.gnu.org/software/texinfo/" rel=
"generator-home" title=
"Texinfo Homepage">
13 Copyright (C) 2005, 2006, 2007, 2008 Eugene K. Ressler.
15 This manual is for `sketch', version 0.2 (build 161),
16 Tuesday, September 08, 2009, a program that converts descriptions of simple
17 three-dimensional scenes into static drawings. This version generates
18 `PSTricks' or `PGF/TikZ' code suitable for use with the
19 TeX document processing system.
21 `Sketch' is free software; you can redistribute it and/or modify
22 it under the terms of the GNU General Public License as published by
23 the Free Software Foundation; either version 3, or (at your option)
26 Sketch is distributed in the hope that it will be useful,
27 but WITHOUT ANY WARRANTY; without even the implied warranty of
28 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
29 GNU General Public License for more details.
31 You should have received a copy of the GNU General Public License
32 along with `sketch'; see the file COPYING.txt. If not, see
33 http://www.gnu.org/copyleft.-->
34 <meta http-equiv=
"Content-Style-Type" content=
"text/css">
35 <style type=
"text/css"><!--
36 pre
.display
{ font-family:inherit
}
37 pre
.format
{ font-family:inherit
}
38 pre
.smalldisplay
{ font-family:inherit
; font-size:smaller
}
39 pre
.smallformat
{ font-family:inherit
; font-size:smaller
}
40 pre
.smallexample
{ font-size:smaller
}
41 pre
.smalllisp
{ font-size:smaller
}
42 span
.sc
{ font-variant:small-caps
}
43 span
.roman
{ font-family: serif
; font-weight: normal
; }
49 <a name=
"Overview"></a>Next:
<a rel=
"next" accesskey=
"n" href=
"A-technical-drawing.html#A-technical-drawing">A technical drawing
</a>,
50 Previous:
<a rel=
"previous" accesskey=
"p" href=
"Building-a-drawing.html#Building-a-drawing">Building a drawing
</a>,
51 Up:
<a rel=
"up" accesskey=
"u" href=
"Building-a-drawing.html#Building-a-drawing">Building a drawing
</a>
55 <!-- node-name, next, previous, up -->
56 <h3 class=
"section">4.1 Overview
</h3>
58 <p>As an overview, let's develop a diagram that shows how a perspective
60 <a name=
"index-perspective-projection-404"></a><a name=
"index-transform-405"></a><a name=
"index-projection_002c-perspective-406"></a>works. We'll start with the traditional reference object
61 used in computer graphics textbooks, a house-shaped prism. Begin
62 by defining the points of the house. Rather than defining the faces
63 of the house as polygons and transforming those, we are going to
64 transform the points themselves with
<code>sketch
</code> arithmetic so that
65 we have names for the transformed points later.
66 <a name=
"index-def-407"></a>
67 <pre class=
"verbatim">
68 % right side (outside to right)
69 def R1 (
1,
1,
1) def R2 (
1,-
1,
1) def R3 (
1,-
1,-
1) def R4 (
1,
1,-
1)
72 % left side (outside to right--backward)
74 def L1 (R1)-[W] def L2 (R2)-[W] def L3 (R3)-[W] def L4 (R4)-[W]
77 To add a door to the house, we use a polygon slightly in
78 front of the foremost face of the house.
79 <pre class=
"verbatim">
82 def D1 (
0,-
1,
1+e) def D2 (
.5,-
1,
1+e) def D3 (
.5,
0,
1+e) def D4 (
0,
0,
1+e)
84 Now let's create a new set of points that are a to-be-determined
85 transform of the originals.
86 <pre class=
"verbatim">
87 def hp scale(
1) % house positioner
88 def pR1 [[hp]]*(R1) def pR2 [[hp]]*(R2) def pR3 [[hp]]*(R3)
89 def pR4 [[hp]]*(R4) def pR5 [[hp]]*(R5)
90 def pL1 [[hp]]*(L1) def pL2 [[hp]]*(L2) def pL3 [[hp]]*(L3)
91 def pL4 [[hp]]*(L4) def pL5 [[hp]]*(L5)
92 def pD1 [[hp]]*(D1) def pD2 [[hp]]*(D2) def pD3 [[hp]]*(D3)
95 Note the use of a
<dfn>transform definition
</dfn>
96 <a name=
"index-transform-definition-408"></a><a name=
"index-definition_002c-transform-409"></a><a name=
"index-_005b_005bfoo_005d_005d_0040r_007b_002c-transform-reference_007d-410"></a>and
97 <dfn>transform references
</dfn>.
98 <a name=
"index-transform-reference-411"></a><a name=
"index-reference_002c-transform-412"></a><a name=
"index-_005b_005bfoo_005d_005d_0040r_007b_002c-transform-reference_007d-413"></a>Now define the seven polygonal faces of the house and the door using
99 the transformed points as vertices. Be careful with vertex order!
100 <a name=
"index-polygon-vertex-order-414"></a><a name=
"index-order_002c-polygon-vertex-415"></a><a name=
"index-fillcolor-416"></a><a name=
"index-def-417"></a><a name=
"index-polygon-418"></a><a name=
"index-_0040_007b-_0040_007d_0040r_007b_002c-block-drawable_007d-419"></a>
101 <pre class=
"verbatim">
102 def rgt polygon (pR1)(pR2)(pR3)(pR4)(pR5)
103 def lft polygon (pL5)(pL4)(pL3)(pL2)(pL1)
104 def frt polygon (pR2)(pR1)(pL1)(pL2)
105 def bck polygon (pR4)(pR3)(pL3)(pL4)
106 def tfr polygon (pR1)(pR5)(pL5)(pL1)
107 def tbk polygon (pR5)(pR4)(pL4)(pL5)
108 def bot polygon (pR2)(pL2)(pL3)(pR3)
109 def door polygon[fillcolor=brown] (pD1)(pD2)(pD3)(pD4)
110 def house { {rgt}{lft}{frt}{bck}{tfr}{tbk}{bot}{door} }
112 Time for a sanity check. Add the line
113 <a name=
"index-_0040_007bfoo_0040_007d_0040r_007b_002c-drawable-reference_007d-420"></a><a name=
"index-reference_002c-drawable-421"></a>
114 <pre class=
"verbatim">
117 and this is what we get.
119 <div align=
"center"><img src=
"ex130.png" alt=
"ex130.png"></div>
121 <p class=
"noindent">This is correct, but does not reveal very much. Common errors are
122 misplaced vertices and polygons missing entirely due to incorrect
124 <a name=
"index-polygon-vertex-order-422"></a><a name=
"index-order_002c-polygon-vertex-423"></a>To rule these out, let's inspect all sides of the
125 house. This is not hard. Merely replace the reference
126 <tt>{house}
</tt> with a
<code>repeat
</code>. See
<a href=
"Repeats.html#Repeats">Repeats
</a>.
127 <a name=
"index-_0040_007bfoo_0040_007d_0040r_007b_002c-drawable-reference_007d-424"></a><a name=
"index-reference_002c-drawable-425"></a><a name=
"index-repeat-426"></a><a name=
"index-rotate-427"></a><a name=
"index-translate-428"></a>
128 <pre class=
"verbatim">
129 repeat {
13, rotate(
30, [
1,
2,
3]), translate([
3,
0,
0]) } {house}
131 <div align=
"center"><img src=
"ex140.png" alt=
"ex140.png"></div>
133 <p class=
"noindent">Again things look correct. Note that the hidden surface algorithm
134 handles intersecting polygons correctly where some copies of the house
137 <p>Let's lay out the geometry of perspective projection of the house onto
138 a plane with rays passing through the origin. Begin by positioning the
139 house twelve units back on the negative z-axis and adding a set
140 of coordinate axes. To move the house we need only change the
“house
141 positioning
” transform defined earlier.
142 <a name=
"index-def-429"></a><a name=
"index-rotate-430"></a><a name=
"index-translate-431"></a><a name=
"index-arrows-432"></a><a name=
"index-linewidth-433"></a><a name=
"index-linecolor-434"></a><a name=
"index-linestyle-435"></a><a name=
"index-special-436"></a><a name=
"index-line-437"></a>
143 <pre class=
"verbatim">
144 def hp rotate(-
40, [
0,
1,
0]) then translate([
0,
0,-
12])
147 line [arrows=
<-
>] (sz,
0,
0)(O)(
0,sz,
0)
148 line [arrows=-
>] (O)(
0,
0,sz)
149 line [linewidth=
.2pt,linecolor=blue,linestyle=dashed] (O)(
0,
0,-
10)
150 special |\uput[r]#
1{$x$}\uput[u]#
2{$y$}\uput[l]#
3{$z$}|
151 (sz,
0,
0)(
0,sz,
0)(
0,
0,sz)
155 <p>Time for another test. Let's build a real view transform,
156 creating a
<dfn>virtual camera
</dfn>
157 <a name=
"index-virtual-camera-438"></a>to look at the scene we are constructing. Replace the
<code>repeat
</code>
159 <pre class=
"verbatim">
162 put { view((eye), (look_at)) } { {house}{axes} }
164 The
<dfn>view transform
</dfn> repositions the scene so that the point
165 <code>eye
</code> is at the origin and the direction from
<code>eye
</code> to
166 <code>look_at
</code> is the negative z-axis. This requires a
167 rotation and a translation that are all packed into the constructor
170 <div align=
"center"><img src=
"ex150.png" alt=
"ex150.png"></div>
172 <p class=
"noindent">This is starting to look good! Add the projection plane half way
173 between the origin and the house at z=-
5. We'll try
174 the angle argument feature of
<code>special
</code> to position a label.
175 <pre class=
"verbatim">
176 def p
5 % projection distance (plane at z=-p)
177 def projection_plane {
179 polygon (-sz,-sz,-p)(sz,-sz,-p)(sz,sz,-p)(-sz,sz,-p)
180 special |\rput[b]#
1-
2#
3{\footnotesize\sf projection plane}|
181 (-sz,-sz,-p)(sz,-sz,-p)(
0,-sz+
.1,-p)
184 Add
<tt>{projection_plane}
</tt> to the list of objects in the
185 <code>put
</code> above.
187 <div align=
"center"><img src=
"ex160.png" alt=
"ex160.png"></div>
189 <p class=
"indent">The way we constructed the points of the house now makes it easy to
190 draw rays of projection. We'll cast one ray from every visible vertex
191 of the house and define options so the appearance of
192 all rays can be changed at the same time.
193 <pre class=
"verbatim">
194 def projection_rays {
195 def rayopt [linewidth=
.3pt,linecolor=lightgray]
196 line [rayopt](O)(pR1) line [rayopt](O)(pR2) line[rayopt](O)(pR3)
197 line [rayopt](O)(pR4) line [rayopt](O)(pR5)
198 line [rayopt](O)(pL1) line [rayopt](O)(pL2) line[rayopt](O)(pL5)
199 line [rayopt](O)(pD1) line [rayopt](O)(pD2)
200 line [rayopt](O)(pD3) line [rayopt](O)(pD4)
203 The result is shown here.
205 <div align=
"center"><img src=
"ex170.png" alt=
"ex170.png"></div>
207 <p class=
"noindent">The rays pierce the projection plane at the corresponding points on
208 the perspective image we are trying to draw. Albrecht D
ürer and his
209 Renaissance contemporaries had the same idea in the early
1500's.
211 <div align=
"center"><img src=
"duerer.png" alt=
"duerer.png"></div>
213 <p>All that's left is to find a way to connect the points of the house
214 on the projection plane. We could pull out a good computer graphics
215 text, find the necessary matrix, and enter it ourselves as a
216 transform literal. See
<a href=
"Transform-literals.html#Transform-literals">Transform literals
</a>. That work is
217 already done, however. We can use the
<code>project(p)
</code> constructor.
219 <p>There are still some details that require care. Projection will
220 flatten whatever is transformed onto the plane z=-p. Therefore
221 any part of the house could disappear behind the projection plane (the
222 hidden surface algorithm orders objects at the same depth
223 arbitrarily). The door may also disappear behind the front of the
224 house. To make sure everything remains visible, we'll place the house
225 a tiny bit in front of the projection plane and a second copy of the
226 door in front of the house.
227 <pre class=
"verbatim">
229 % e is a small number defined above
230 put { project(p) then translate([
0,
0,
1*e]) } {house}
231 put { project(p) then translate([
0,
0,
2*e]) } {door}
235 <div align=
"center"><img src=
"ex180.png" alt=
"ex180.png"></div>
237 <p>If you have studied and understand all this, you are well on the way
238 to success with
<code>sketch
</code>. Not shown are the
20 or so iterations
239 that were required to find a reasonable viewing angle and house
240 position, etc. Nonetheless, this drawing was completed in about an
241 hour. While a GUI tool may have been a little faster, it is unlikely
242 that a new drawing, itself a perspective projection of the scene,
243 could be generated with two more minutes' work! Just change the view
245 <pre class=
"verbatim">
246 put { view((eye), (look_at)) then perspective(
9) } { ...
250 <div align=
"center"><img src=
"ex190.png" alt=
"ex190.png"></div>