Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(84)

Side by Side Diff: utils/matrix/matrix4.dart

Issue 8872007: beginning of matrix class (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: no change Created 9 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file.
4
5 // based on code from
6 // http://code.google.com/p/closure-library/source/browse/trunk/closure/goog/vec /mat4.js
7
8 /**
9 * Thrown if you attempt to normalize a zero length vector.
10 */
11 class ZeroLengthVectorException implements Exception {
12 ZeroLengthVectorException() {}
13 }
14
15 /**
16 * Thrown if you attempt to invert a singular matrix. (A
17 * singular matrix has no inverse.)
18 */
19 class SingularMatrixException implements Exception {
20 SingularMatrixException() {}
21 }
22
23 /**
24 * 3 dimensional vector.
25 */
26 class Vector3 {
27 final double x;
Jacob 2011/12/12 22:59:14 One more high level comment. Is there a good reas
mattsh 2011/12/12 23:06:35 I think for consistency and interoperability with
28 final double y;
29 final double z;
30
31 // TODO - should be const, but cannot because of
32 // bug http://code.google.com/p/dart/issues/detail?id=777
Bob Nystrom 2011/12/12 21:46:09 According to the bug, this is fixed now.
33 Vector3(double x, double y, double z) : x = x, y = y, z = z {}
Jacob 2011/12/12 18:38:17 replace " {}" with ";"
mattsh 2011/12/12 19:14:45 Done.
Bob Nystrom 2011/12/12 21:46:09 Why not just use this.x, this.y, this.z?
mattsh 2011/12/12 22:48:26 Currently the this.x style syntax does not lift th
Jacob 2011/12/12 22:59:14 is there a good reason why these are double instea
mattsh 2011/12/12 23:06:35 See above
34
35 double magnitude() {
Jacob 2011/12/12 18:38:17 switch short one liners to use => syntax
mattsh 2011/12/12 19:14:45 Prefer non-arrow syntax here, since it is consiste
Bob Nystrom 2011/12/12 21:46:09 Personally, I'd prefer arrow here too (and elsewhe
Bob Nystrom 2011/12/12 21:46:09 Should this be a getter? Also, I'd add magnitudeSq
mattsh 2011/12/12 22:48:26 OK, switch to arrow syntax.
mattsh 2011/12/12 22:48:26 I think it's better to keep it a method, to make i
36 return Math.sqrt(x*x + y*y + z*z);
37 }
38
39 Vector3 normalize() {
40 double len = magnitude();
41 if (len == 0.0) {
42 throw new ZeroLengthVectorException();
43 }
44 return new Vector3(x/len, y/len, z/len);
45 }
46
47 Vector3 operator negate() {
48 return new Vector3(-x,-y,-z);
Bob Nystrom 2011/12/12 21:46:09 Space after comma.
mattsh 2011/12/12 22:48:26 Done.
49 }
50
51 Vector3 operator -(Vector3 other) {
52 return new Vector3(this.x - other.x, this.y - other.y, this.z - other.z);
Bob Nystrom 2011/12/12 21:46:09 Get rid of "this.".
mattsh 2011/12/12 22:48:26 Done.
53 }
54
55 Vector3 cross(Vector3 other) {
56 double xResult = y * other.z - z * other.y;
Bob Nystrom 2011/12/12 21:46:09 "final" instead of "double".
mattsh 2011/12/12 22:48:26 I think I prefer writing the type here.
57 double yResult = z * other.x - x * other.z;
58 double zResult = x * other.y - y * other.x;
59 return new Vector3(xResult, yResult, zResult);
60 }
61
62 String toString() {
63 return "Vector3($x,$y,$z)";
Jacob 2011/12/12 22:59:14 one more style nit. why not "($x, $y, $z)" instead
64 }
65 }
66
67 /**
68 * A 4x4 transformation matrix (for use with webgl)
69 *
70 * We label the elements of the matrix as follows:
71 *
72 * m00 m01 m02 m03
Bob Nystrom 2011/12/12 21:46:09 Indent these two more and dartdoc will recognize i
mattsh 2011/12/12 22:48:26 Done.
73 * m10 m11 m12 m13
74 * m20 m21 m22 m23
75 * m30 m31 m32 m33
76 *
77 * These are stored in a 16 element Float32Array, in column major
Bob Nystrom 2011/12/12 21:46:09 Put Float32Array in square brackets to cross-link.
mattsh 2011/12/12 22:48:26 Done.
78 * order, so they are ordered like this:
79 *
80 * [ m00,m10,m20,m30, m11,m21,m31,m41, m02,m12,m22,m32, m03,m13,m23,m33 ]
81 * 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
82 *
83 * We use column major order because that is what WebGL APIs expect.
84 *
85 */
86 class Matrix4 {
87 final Float32Array buf;
Bob Nystrom 2011/12/12 21:46:09 "buffer" or "elements"?
mattsh 2011/12/12 22:48:26 Tried elements, but actually it just doesn't look
88
89 /**
90 * returns the index into [buf] for a given
91 * row and column.
92 */
93 static int rc(int row, int col) => row + col * 4;
Jacob 2011/12/12 18:38:17 add a leading _?
mattsh 2011/12/12 19:14:45 Prefer to keep it public.
Bob Nystrom 2011/12/12 21:46:09 If you want this to be public, I would give it a m
mattsh 2011/12/12 22:48:26 Done.
94
95 double get m00() => buf[rc(0, 0)];
96 double get m01() => buf[rc(0, 1)];
97 double get m02() => buf[rc(0, 2)];
98 double get m03() => buf[rc(0, 3)];
99 double get m10() => buf[rc(1, 0)];
100 double get m11() => buf[rc(1, 1)];
101 double get m12() => buf[rc(1, 2)];
102 double get m13() => buf[rc(1, 3)];
103 double get m20() => buf[rc(2, 0)];
104 double get m21() => buf[rc(2, 1)];
105 double get m22() => buf[rc(2, 2)];
106 double get m23() => buf[rc(2, 3)];
107 double get m30() => buf[rc(3, 0)];
108 double get m31() => buf[rc(3, 1)];
109 double get m32() => buf[rc(3, 2)];
110 double get m33() => buf[rc(3, 3)];
111
112 void set m00(double m) { buf[rc(0, 0)] = m; }
113 void set m01(double m) { buf[rc(0, 1)] = m; }
114 void set m02(double m) { buf[rc(0, 2)] = m; }
115 void set m03(double m) { buf[rc(0, 3)] = m; }
116 void set m10(double m) { buf[rc(1, 0)] = m; }
117 void set m11(double m) { buf[rc(1, 1)] = m; }
118 void set m12(double m) { buf[rc(1, 2)] = m; }
119 void set m13(double m) { buf[rc(1, 3)] = m; }
120 void set m20(double m) { buf[rc(2, 0)] = m; }
121 void set m21(double m) { buf[rc(2, 1)] = m; }
122 void set m22(double m) { buf[rc(2, 2)] = m; }
123 void set m23(double m) { buf[rc(2, 3)] = m; }
124 void set m30(double m) { buf[rc(3, 0)] = m; }
125 void set m31(double m) { buf[rc(3, 1)] = m; }
126 void set m32(double m) { buf[rc(3, 2)] = m; }
127 void set m33(double m) { buf[rc(3, 3)] = m; }
128
129 String toString() {
130 List<String> rows = new List();
131 for (int row = 0; row < 4; row++) {
132 List<String> items = new List();
133 for (int col = 0; col < 4; col++) {
134 double v = buf[rc(row, col)];
135 if (v.abs() < 1e-16) {
136 v = 0.0;
137 }
138 String display;
139 try {
140 display = v.toStringAsPrecision(4);
141 } catch (Object e) {
142 // TODO - remove this once toStringAsPrecision is implemented in vm
143 display = v.toString();
144 }
145 items.add(display);
146 }
147 rows.add("| ${Strings.join(items, ", ")} |");
148 }
149 return "Matrix4:\n${Strings.join(rows, '\n')}";
150 }
151
152 /**
153 * Constructs a new Matrix4 with all entries initialized
154 * to zero.
155 */
156 Matrix4() : buf = new Float32Array(16) {}
Jacob 2011/12/12 18:38:17 move constructors above members and replace " {}"
mattsh 2011/12/12 19:14:45 Done.
157
158 /**
159 * Cosntructs a new Matrix4 that represents the identity transformation
160 * (all the diagonal entries are 1, and everything else is zero).
161 */
162 static Matrix4 identity() {
Jacob 2011/12/12 18:38:17 change statics for identity, rotation and transpos
mattsh 2011/12/12 19:14:45 Actually, prefer these to be static methods, not f
Jacob 2011/12/12 22:59:14 One advantage of making the factory constructors i
163 Matrix4 m = new Matrix4();
164 m.m00 = 1.0;
165 m.m11 = 1.0;
166 m.m22 = 1.0;
167 m.m33 = 1.0;
168 return m;
169 }
170
171 /**
172 * Constructs a new Matrix4 that represents a rotation around an axis.
173 *
174 * [degrees] number of degrees to rotate
175 * [axis] direction of axis of rotation (must not be zero length)
176 */
177 static Matrix4 rotation(double degrees, Vector3 axis) {
178 double radians = degrees / 180.0 * Math.PI;
179 axis = axis.normalize();
180
181 double x = axis.x;
182 double y = axis.y;
183 double z = axis.z;
184 double s = Math.sin(radians);
185 double c = Math.cos(radians);
186 double t = 1 - c;
187
188 Matrix4 m = new Matrix4();
189 m.m00 = x * x * t + c;
190 m.m10 = x * y * t + z * s;
191 m.m20 = x * z * t - y * s;
192
193 m.m01 = x * y * t - z * s;
194 m.m11 = y * y * t + c;
195 m.m21 = y * z * t + x * s;
196
197 m.m02 = x * z * t + y * s;
198 m.m12 = y * z * t - x * s;
199 m.m22 = z * z * t + c;
200
201 m.m33 = 1.0;
202 return m;
203 }
204
205 /**
206 * Constructs a new Matrix4 that represents a translation.
207 *
208 * [v] vector representing which direction to move and how much to move
209 */
210 static Matrix4 translation(Vector3 v) {
211 Matrix4 m = identity();
212 m.m03 = v.x;
213 m.m13 = v.y;
214 m.m23 = v.z;
215 return m;
216 }
217
218 /**
219 * returns the transpose of this matrix
220 */
221 Matrix4 transpose() {
222 Matrix4 m = new Matrix4();
223 for (int row = 0; row < 4; row++) {
224 for (int col = 0; col < 4; col++) {
225 m.buf[rc(col, row)] = this.buf[rc(row, col)];
226 }
227 }
228 return m;
229 }
230
231 /**
232 * Returns result of multiplication of this matrix
233 * by another matrix.
234 *
235 * In this equation:
236 *
237 * C = A * B
238 *
239 * C is the result of multiplying A * B.
240 * A is this matrix
241 * B is another matrix
242 *
243 */
244 Matrix4 operator *(Matrix4 matrixB) {
245 Matrix4 matrixC = new Matrix4();
246 Float32Array bufA = this.buf;
247 Float32Array bufB = matrixB.buf;
248 Float32Array bufC = matrixC.buf;
249 for (int row = 0; row < 4; row++) {
250 for (int col = 0; col < 4; col++) {
251 for (int i = 0; i < 4; i++) {
252 bufC[rc(row, col)] += bufA[rc(row, i)] * bufB[rc(i, col)];
253 }
254 }
255 }
256 return matrixC;
257 }
258
259 /**
260 * Constructs a 4x4 matrix matrix so that the eye is 'looking at' a
261 * given center point. (What this means is that the returned matrix can be
262 * used transform points from world coordinates to a new coordinate system
263 * where the eye is at the origin, and the negative z-axis of the new
264 * coordinate system goes from the eye towards the center point.)
265 *
266 * [eye] position of the eye (i.e. camera origin).
267 * [center] point to aim the camera at.
268 * [up] vector that identifies the up direction of the camera
269 */
270 static Matrix4 lookAt(Vector3 eye, Vector3 center, Vector3 up) {
Jacob 2011/12/12 18:38:17 make factory constructor
mattsh 2011/12/12 19:14:45 see above
271 // Compute the z basis vector. (The z-axis negative direction is
272 // from eye to center point.)
273 Vector3 zBasis = (eye - center).normalize();
274
275 // Compute x basis. (The positive x-axis points right.)
276 Vector3 xBasis = up.cross(zBasis).normalize();
277
278 // Compute the y basis. (The positive y-axis points approximately the same
279 // direction as the supplied [up] direction, and is perpendicular to z and
280 // x.)
281 Vector3 yBasis = zBasis.cross(xBasis);
282
283 // We now have an orthonormal basis.
284 Matrix4 b = new Matrix4();
285 b.m00 = xBasis.x; b.m01 = xBasis.y; b.m02 = xBasis.z;
286 b.m10 = yBasis.x; b.m11 = yBasis.y; b.m12 = yBasis.z;
287 b.m20 = zBasis.x; b.m21 = zBasis.y; b.m22 = zBasis.z;
288 b.m33 = 1.0;
289
290 // Before switching to the new basis, first translate by the negation
291 // of the eye point. (This will put the eye at the origin of the
292 // new coordinate system.)
293 return b * Matrix4.translation(-eye);
294 }
295
296 /**
297 * Makse a 4x4 matrix perspective projection matrix given a field of view and
298 * aspect ratio.
299 *
300 * [fovyDegrees] field of view (in degrees) of the y-axis
301 * [aspectRatio] width to height aspect ratio.
302 * [zNear] distance to the near clipping plane.
303 * [zFar] distance to the far clipping plane.
304 */
305 static Matrix4 perspective(double fovyDegrees, double aspectRatio,
Jacob 2011/12/12 18:38:17 factory constructor
mattsh 2011/12/12 19:14:45 see above
306 double zNear, double zFar) {
307 double yTop = Math.tan(fovyDegrees * Math.PI / 180.0 / 2.0) * zNear;
308 double xRight = aspectRatio * yTop;
309 double zDepth = zFar - zNear;
310
311 Matrix4 m = new Matrix4();
312 m.m00 = zNear / xRight;
313 m.m11 = zNear / yTop;
314 m.m22 = -(zFar + zNear) / zDepth;
315 m.m23 = -(2 * zNear * zFar) / zDepth;
316 m.m32 = -1;
317 return m;
318 }
319
320 /**
321 * Returns the inverse of this matrix.
322 */
323 Matrix4 inverse() {
324 double a0 = m00 * m11 - m10 * m01;
325 double a1 = m00 * m21 - m20 * m01;
326 double a2 = m00 * m31 - m30 * m01;
327 double a3 = m10 * m21 - m20 * m11;
328 double a4 = m10 * m31 - m30 * m11;
329 double a5 = m20 * m31 - m30 * m21;
330
331 double b0 = m02 * m13 - m12 * m03;
332 double b1 = m02 * m23 - m22 * m03;
333 double b2 = m02 * m33 - m32 * m03;
334 double b3 = m12 * m23 - m22 * m13;
335 double b4 = m12 * m33 - m32 * m13;
336 double b5 = m22 * m33 - m32 * m23;
337
338 // compute determinant
Bob Nystrom 2011/12/12 21:46:09 "Compute determinant."
mattsh 2011/12/12 22:48:26 Done.
339 double det = a0 * b5 - a1 * b4 + a2 * b3 + a3 * b2 - a4 * b1 + a5 * b0;
340 if (det == 0) {
341 throw new SingularMatrixException();
342 }
343
344 Matrix4 m = new Matrix4();
345 m.m00 = (m11 * b5 - m21 * b4 + m31 * b3) / det;
346 m.m10 = (-m10 * b5 + m20 * b4 - m30 * b3) / det;
347 m.m20 = (m13 * a5 - m23 * a4 + m33 * a3) / det;
348 m.m30 = (-m12 * a5 + m22 * a4 - m32 * a3) / det;
349
350 m.m01 = (-m01 * b5 + m21 * b2 - m31 * b1) / det;
351 m.m11 = (m00 * b5 - m20 * b2 + m30 * b1) / det;
352 m.m21 = (-m03 * a5 + m23 * a2 - m33 * a1) / det;
353 m.m31 = (m02 * a5 - m22 * a2 + m32 * a1) / det;
354
355 m.m02 = (m01 * b4 - m11 * b2 + m31 * b0) / det;
356 m.m12 = (-m00 * b4 + m10 * b2 - m30 * b0) / det;
357 m.m22 = (m03 * a4 - m13 * a2 + m33 * a0) / det;
358 m.m32 = (-m02 * a4 + m12 * a2 - m32 * a0) / det;
359
360 m.m03 = (-m01 * b3 + m11 * b1 - m21 * b0) / det;
361 m.m13 = (m00 * b3 - m10 * b1 + m20 * b0) / det;
362 m.m23 = (-m03 * a3 + m13 * a1 - m23 * a0) / det;
363 m.m33 = (m02 * a3 - m12 * a1 + m22 * a0) / det;
364
365 return m;
366 }
367 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698