File: cs_172.html

package info (click to toggle)
crystalspace 0.94-20020412-3
  • links: PTS
  • area: main
  • in suites: woody
  • size: 62,276 kB
  • ctags: 52,843
  • sloc: cpp: 274,783; ansic: 6,608; perl: 6,276; objc: 3,952; asm: 2,942; python: 2,354; php: 542; pascal: 530; sh: 430; makefile: 370; awk: 193
file content (342 lines) | stat: -rw-r--r-- 13,239 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<!-- Created by texi2html 1.64 -->
<!-- 
Written by: Lionel Cons <Lionel.Cons@cern.ch> (original author)
            Karl Berry  <karl@freefriends.org>
            Olaf Bachmann <obachman@mathematik.uni-kl.de>
            and many others.
Maintained by: Olaf Bachmann <obachman@mathematik.uni-kl.de>
Send bugs and suggestions to <texi2html@mathematik.uni-kl.de>
 
-->
<HTML>
<HEAD>
<TITLE>Crystal Space: Cameras and Matrices</TITLE>

<META NAME="description" CONTENT="Crystal Space: Cameras and Matrices">
<META NAME="keywords" CONTENT="Crystal Space: Cameras and Matrices">
<META NAME="resource-type" CONTENT="document">
<META NAME="distribution" CONTENT="global">
<META NAME="Generator" CONTENT="texi2html 1.64">

</HEAD>

<BODY LANG="" BGCOLOR="#FFFFFF" TEXT="#000000" LINK="#0000FF" VLINK="#800080" ALINK="#FF0000">

<A NAME="SEC373"></A>
<TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0>
<TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="cs_171.html#SEC368"> &lt; </A>]</TD>
<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="cs_173.html#SEC376"> &gt; </A>]</TD>
<TD VALIGN="MIDDLE" ALIGN="LEFT"> &nbsp; <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="cs_167.html#SEC358"> &lt;&lt; </A>]</TD>
<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="cs_168.html#SEC359"> Up </A>]</TD>
<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="cs_196.html#SEC414"> &gt;&gt; </A>]</TD>
<TD VALIGN="MIDDLE" ALIGN="LEFT"> &nbsp; <TD VALIGN="MIDDLE" ALIGN="LEFT"> &nbsp; <TD VALIGN="MIDDLE" ALIGN="LEFT"> &nbsp; <TD VALIGN="MIDDLE" ALIGN="LEFT"> &nbsp; <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="index.html#SEC_Top">Top</A>]</TD>
<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="cs_toc.html#SEC_Contents">Contents</A>]</TD>
<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="cs_285.html#SEC711">Index</A>]</TD>
<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="cs_abt.html#SEC_About"> ? </A>]</TD>
</TR></TABLE>
<HR SIZE=1>
<H3> 7.6.4 Cameras and Matrices </H3>
<!--docid::SEC373::-->
<P>

<EM>Written by Jorrit Tyberghein,
<A HREF="mailto:jorrit.tyberghein@uz.kuleuven.ac.be">jorrit.tyberghein@uz.kuleuven.ac.be</A>.  Mathematical typesetting for
TeX performed by Eric Sunshine, <A HREF="mailto:sunshine@sunshineco.com">sunshine@sunshineco.com</A>.</EM>
</P><P>

This section describes how a camera in a 3D engine can be represented by a 3x3
matrix and a 3-element vector.  This is the method that is used in the Crystal
Space engine but it is general enough that it can be used in other engines as
well.
</P><P>

<A NAME="SEC374"></A>
<H4> Theory </H4>
<!--docid::SEC374::-->
<P>

A way to look at the matrix and vector representation of a camera is by seeing
the matrix as a 3 dimensional arrow pointing in some direction (the direction
the camera is looking at) and the vector as the starting point (origin) of
that arrow.
</P><P>

What does this matrix do? It performs a linear transformation from 3D to 3D.
With a 3x3 matrix you can represent every linear transformation from one 3D
space to another 3D space.  The matrix that we use for a camera is just a
linear transformation matrix that transforms coordinates represented in one
coordinate system to another.  Let's assume that everything in the world is
defined by using 3D vertices with an <EM>x</EM>, <EM>y</EM>, and <EM>z</EM>
component.  So a vertex is defined by three numbers: <EM>x</EM>, <EM>y</EM>, and
<EM>z</EM>.  These three numbers only have meaning when used relative to some
origin.  A origin is defined by three axes (if it is a 3D origin that is).
</P><P>

So our camera matrix transforms 3D vertices from world space to camera space.
This means that a vertex with position (<EM>x,y,z</EM>) in the world (in world
space) will get new coordinates (<EM>x',y',z'</EM>) in camera space.  The only
reason that we want to apply this transformation is to make things easier for
the rest of the 3D engine.  Because after this transformation we can program
the rest of the engine as if every vertex is represented in camera space.  In
other words; a vertex with coordinates (<EM>0,0,5</EM>) will be a vertex that
lies just in front of the camera at distance 5.  A vertex with coordinates
(<EM>1,3,-5</EM>) is behind the plane of the camera and can thus be easily
discarded.  The test <EM>Z &#60; 0</EM> is thus an easy test to see if a vertex will
be visible or not.
</P><P>

How does this transformation work? In fact it is just matrix algebra.  For
example, if the camera matrix is represented by <EM>M</EM> and the camera
position is represented by <EM>P</EM> then we can write the equation to
transform from world space to camera space by using:
</P><P>

<BLOCKQUOTE>
<EM>C = M * (W - P)</EM>
</BLOCKQUOTE>
<P>

<EM>W</EM> is a 3D vector describing the position of a vertex in world space
coordinates.  <EM>C</EM> is a 3D vector describing the position of a vertex in
camera space coordinates.
</P><P>

This formula does the following.  First it translates the world space position
so that the camera position is at (<EM>0,0,0</EM>).  This is done by <EM>W -
P</EM>.  As you can see a vertex that would be on the same world space coordinates
as the camera would be translated to (<EM>0,0,0</EM>).  The result of this
calculation is another 3D vector.
</P><P>

This vector is then multiplied by the camera matrix <EM>M</EM> to transform it
to camera space.  You can visualize this by treating <EM>M</EM> as an arrow
pointing in some direction and the vertex lying somewhere relative to that
arrow.  By transforming with <EM>M</EM> (multiplying) we move the arrow until it
points just the way we want it (with the Z-axis in front and so on).
</P><P>

A matrix by vector multiplication is defined as follows:
</P><P>

<TABLE><tr><td>&nbsp;</td><td class=example><pre>/ a b c \     / x \     / a * x + b * y + c * z \
| d e f |  *  | y |  =  | d * x + e * y + f * z |
\ g h i /     \ z /     \ g * x + h * y + i * z /
</pre></td></tr></table></P><P>

So for example, let's apply this formula in the initial configuration, with
the camera pointing forwards in world space.  The camera matrix is then equal
to:
</P><P>

<TABLE><tr><td>&nbsp;</td><td class=example><pre>/ 1 0 0 \
| 0 1 0 |
\ 0 0 1 /
</pre></td></tr></table></P><P>

And the vector is equal to:
</P><P>

<TABLE><tr><td>&nbsp;</td><td class=example><pre>/ 0 \
| 0 |
\ 0 /
</pre></td></tr></table></P><P>

Translation of a vertex in world space coordinates to camera space coordinates
makes no changes since the camera is at the origin of the world.
Transformation results in the previous formula being applied:
</P><P>

<TABLE><tr><td>&nbsp;</td><td class=example><pre>/ 1 0 0 \     / x \     / 1 * x + 0 * y + 0 * z \
| 0 1 0 |  *  | y |  =  | 0 * x + 1 * y + 0 * z |
\ 0 0 1 /     \ z /     \ 0 * x + 0 * y + 1 * z /
</pre></td></tr></table></P><P>

So as you can see, this does not change the vertex at all.
</P><P>

<A NAME="SEC375"></A>
<H4> Practice </H4>
<!--docid::SEC375::-->
<P>

Now that the theory behind camera mathematics has been described, it is time
to see everything put into practice in order to actually move the camera.  All
of the different kind of movements that the camera can do are also performed
as transformations.
</P><P>

For example, let's say that you want to move the camera forward a bit.  If you
would represent this movement in camera space than you would say that the
camera moves from (<EM>0,0,0</EM>)---since the camera is at the origin in camera
space--to (<EM>0,0,d</EM>) with <EM>d</EM> the distance that you want it to move.
This is because we defined camera space so that <EM>Z</EM> is in front of you.
</P><P>

But we want to know the position of the camera in world space.  In fact, what
we want to do is to transfrom the camera space position (<EM>0,0,d</EM>) to
world space.  This would then be the new position for the camera.
</P><P>

So we need the inverse transformation.  To calculate the inverse
transformation you need to calculate the inverse of the matrix <EM>M</EM>.
Let's call this inverse <EM>M'</EM>.  From Matrix Algebra, we know that
<EM>M * M' = I</EM>
(where <EM>I</EM> is the identity matrix).
</P><P>

Calculation of the inverse of a matrix is a bit complicated.  For exact
details, consult a Matrix Algebra textbook.  In practical terms, it is done by
starting with the following formula which is our transformation from world to
camera space equation:
</P><P>

<BLOCKQUOTE>
<EM>C = M * (W - P)</EM>
</BLOCKQUOTE>
<P>

We would now like to calculate the new equation for the inverse
transformation.  We already have <EM>M'</EM> (the inverse matrix).  Ok, let us
multiply both sides of the equation by <EM>M'</EM>.  This gives:
</P><P>

<BLOCKQUOTE>
<EM>M' * C = M' * M * (W - P)</EM>
</BLOCKQUOTE>
<P>

Since
<EM>M' * M = I</EM>,
this results in:
</P><P>

<BLOCKQUOTE>
<EM>M' * C = W - P</EM>
</BLOCKQUOTE>
<P>

So the equation we are looking for is:
</P><P>

<BLOCKQUOTE>
<EM>W = M' * C + P</EM>
</BLOCKQUOTE>
<P>

So this is the equation that transforms camera space to world space.  Now we
can use this to transform (<EM>0,0,d</EM>) to the new camera space coordinates.
Other movements (like moving to the right (<EM>d,0,0</EM>), up (<EM>0,d,0</EM>),
down (<EM>0,-d,0</EM>), and so on) are all performed in an equivalent manner.
</P><P>

If you want to turn right then your position will not change but you will have
to change the transformation matrix.  This works differently.  For example, to
turn right you would want to rotate a certain angle around the Y-axis (since
the Y-axis points upwards).  This rotation can be represented by the following
matrix (known as a <EM>rotation matrix</EM>) which rotates about the Y-axis:
</P><P>

<TABLE><tr><td>&nbsp;</td><td class=example><pre>/ cos(a)   0    -sin(a) \
| 0        1    0       |
\ sin(a)   0    cos(a)  /
</pre></td></tr></table></P><P>

To see why this works, just try multiplying it by some vectors in 3D and see
where they will transform too.
</P><P>

How can we then use this matrix to turn our camera to the right? An important
thing to realize is that transformations can be combined by multiplying the
transformation matrices together.  For example, if we have our matrix <EM>M</EM>
transforming from world to camera space and we would like to apply the Y-axis
rotation on the camera then you can see this as a combination of first the
transformation from world to camera space followed by the rotation along the
Y-axis.  So instead of:
</P><P>

<BLOCKQUOTE>
<EM>C = M * (W - P)</EM>
</BLOCKQUOTE>
<P>

We would want to use:
</P><P>

<BLOCKQUOTE>
<EM>C = R * M * (W - P)</EM>
</BLOCKQUOTE>
<P>

Where <EM>R</EM> is the rotation matrix.
</P><P>

<EM>R * M * (W - P)</EM>
means to first apply transformation <EM>M</EM> on (<EM>W - P</EM>) and after that
apply transformation <EM>R</EM> on the result.  Note that multiplication of
matrices is not commutative.
<EM>R * M</EM>
is not guaranteed to be the same as
<EM>M * R</EM>.
</P><P>

So, we can conclude from this that we just have to multiply the camera matrix
by <EM>R</EM> to get the new camera matrix:
</P><P>

<BLOCKQUOTE>
<EM>M' = R * M</EM>
</BLOCKQUOTE>
<P>

Matrix multiplication works as follows:
</P><P>

<TABLE><tr><td>&nbsp;</td><td class=example><pre>/ a b c \   / A B C \   / a*A+b*D+c*G a*B+b*E+c*H a*C+b*F+c*I \
| d e f | * | D E F | = | d*A+e*D+f*G d*B+e*E+f*H d*C+e*F+f*I |
\ g h i /   \ G H I /   \ g*A+h*D+i*G g*B+h*E+i*H g*C+h*F+i*I /
</pre></td></tr></table></P><P>

Rotation along the other axes works in a similar fashion.  Rotation along the
X-axis is represented by:
</P><P>

<TABLE><tr><td>&nbsp;</td><td class=example><pre>/ 1   0        0       \
| 0   cos(a)   -sin(a) |
\ 0   sin(a)   cos(a)  /
</pre></td></tr></table></P><P>

Rotation along the Z-axis is represented by:
</P><P>

<TABLE><tr><td>&nbsp;</td><td class=example><pre>/ cos(a)   -sin(a) 0  \
| sin(a)   cos(a)  0  |
\ 0        0       1  /
</pre></td></tr></table></P><P>

With these formulae you should be able to do any movement of the camera that
you want, including rotating the camera around the direction it is looking.
</P><P>

<A NAME="Space Warping"></A>
<HR SIZE=1>
<TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0>
<TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="cs_171.html#SEC368"> &lt; </A>]</TD>
<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="cs_173.html#SEC376"> &gt; </A>]</TD>
<TD VALIGN="MIDDLE" ALIGN="LEFT"> &nbsp; <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="cs_167.html#SEC358"> &lt;&lt; </A>]</TD>
<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="cs_168.html#SEC359"> Up </A>]</TD>
<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="cs_196.html#SEC414"> &gt;&gt; </A>]</TD>
<TD VALIGN="MIDDLE" ALIGN="LEFT"> &nbsp; <TD VALIGN="MIDDLE" ALIGN="LEFT"> &nbsp; <TD VALIGN="MIDDLE" ALIGN="LEFT"> &nbsp; <TD VALIGN="MIDDLE" ALIGN="LEFT"> &nbsp; <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="index.html#SEC_Top">Top</A>]</TD>
<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="cs_toc.html#SEC_Contents">Contents</A>]</TD>
<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="cs_285.html#SEC711">Index</A>]</TD>
<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="cs_abt.html#SEC_About"> ? </A>]</TD>
</TR></TABLE>
<BR>  
<FONT SIZE="-1">
This document was generated

using <A HREF="http://www.mathematik.uni-kl.de/~obachman/Texi2html
"><I>texi2html</I></A>

</BODY>
</HTML>