1 /**
2 3x3 matrix datatype.
3 
4 Copyright:
5 Copyright (c) 2007-2018 Juan Linietsky, Ariel Manzur.  
6 Copyright (c) 2014-2018 Godot Engine contributors (cf. AUTHORS.md)  
7 Copyright (c) 2017-2018 Godot-D contributors  
8 
9 License: $(LINK2 https://opensource.org/licenses/MIT, MIT License)
10 
11 
12 */
13 module godot.core.basis;
14 
15 import godot.core.defs;
16 import godot.core.vector3;
17 import godot.core.quat;
18 
19 import std.math;
20 import std.algorithm.mutation : swap;
21 
22 /**
23 3x3 matrix used for 3D rotation and scale. Contains 3 vector fields x, y, and z as its columns, which can be interpreted as the local basis vectors of a transformation. Can also be accessed as array of 3D vectors. These vectors are orthogonal to each other, but are not necessarily normalized. Almost always used as orthogonal basis for a $(D Transform).
24 
25 For such use, it is composed of a scaling and a rotation matrix, in that order (M = R.S).
26 */
27 struct Basis
28 {
29 	@nogc nothrow:
30 	
31 	Vector3[3] elements = 
32 	[
33 		Vector3(1.0,0.0,0.0),
34 		Vector3(0.0,1.0,0.0),
35 		Vector3(0.0,0.0,1.0),
36 	];
37 	
38 	this(in Vector3 row0, in Vector3 row1, in Vector3 row2)
39 	{
40 		elements[0]=row0;
41 		elements[1]=row1;
42 		elements[2]=row2;
43 	}
44 	
45 	this(real_t xx, real_t xy, real_t xz, real_t yx, real_t yy, real_t yz, real_t zx, real_t zy, real_t zz)
46 	{
47 		set(xx, xy, xz, yx, yy, yz, zx, zy, zz);
48 	}
49 	
50 	const(Vector3) opIndex(int axis) const
51 	{
52 		return elements[axis];
53 	}
54 	ref Vector3 opIndex(int axis) return
55 	{
56 		return elements[axis];
57 	}
58 	
59 	private pragma(inline, true)
60 	real_t cofac(int row1, int col1, int row2, int col2) const
61 	{
62 		return (elements[row1][col1] * elements[row2][col2] -
63 		        elements[row1][col2] * elements[row2][col1]);
64 	}
65 	
66 	void invert()
67 	{
68 		real_t[3] co=[
69 			cofac(1, 1, 2, 2), cofac(1, 2, 2, 0), cofac(1, 0, 2, 1)
70 		];
71 		real_t det = elements[0][0] * co[0] +
72 		             elements[0][1] * co[1] +
73 		             elements[0][2] * co[2];
74 		
75 		/// ERR_FAIL_COND(det != 0);
76 		/// TODO: implement errors; D assert/exceptions won't work!
77 		
78 		real_t s = 1.0/det;
79 	
80 		set(co[0]*s, cofac(0, 2, 2, 1) * s, cofac(0, 1, 1, 2) * s,
81 		    co[1]*s, cofac(0, 0, 2, 2) * s, cofac(0, 2, 1, 0) * s,
82 		    co[2]*s, cofac(0, 1, 2, 0) * s, cofac(0, 0, 1, 1) * s );
83 	}
84 	
85 	bool isEqualApprox(in Basis a, in Basis b) const
86 	{
87 		for (int i=0;i<3;i++) {
88 			for (int j=0;j<3;j++) {
89 				if ((fabs(a.elements[i][j]-b.elements[i][j]) < CMP_EPSILON) == false)
90 					return false;
91 			}
92 		}
93 	
94 		return true;
95 	}
96 	
97 	
98 	bool isOrthogonal() const
99 	{
100 		Basis id;
101 		Basis m = (this)*transposed();
102 	
103 		return isEqualApprox(id,m);
104 	}
105 	
106 	bool isRotation() const
107 	{
108 		return fabs(determinant()-1) < CMP_EPSILON && isOrthogonal();
109 	}
110 	
111 	void transpose()
112 	{
113 		swap(elements[0][1],elements[1][0]);
114 		swap(elements[0][2],elements[2][0]);
115 		swap(elements[1][2],elements[2][1]);
116 	}
117 	
118 	Basis inverse() const
119 	{
120 		Basis b = this;
121 		b.invert();
122 		return b;
123 	}
124 	
125 	Basis transposed() const
126 	{
127 		Basis b = this;
128 		b.transpose();
129 		return b;
130 	}
131 	
132 	real_t determinant() const
133 	{
134 		return elements[0][0]*(elements[1][1]*elements[2][2] - elements[2][1]*elements[1][2]) -
135 		       elements[1][0]*(elements[0][1]*elements[2][2] - elements[2][1]*elements[0][2]) +
136 		       elements[2][0]*(elements[0][1]*elements[1][2] - elements[1][1]*elements[0][2]);
137 	}
138 	
139 	Vector3 getAxis(int p_axis) const
140 	{
141 		// get actual basis axis (elements is transposed for performance)
142 		return Vector3( elements[0][p_axis], elements[1][p_axis], elements[2][p_axis] );
143 	}
144 	void setAxis(int p_axis, in Vector3 p_value)
145 	{
146 		// get actual basis axis (elements is transposed for performance)
147 		elements[0][p_axis]=p_value.x;
148 		elements[1][p_axis]=p_value.y;
149 		elements[2][p_axis]=p_value.z;
150 	}
151 	
152 	void rotate(in Vector3 p_axis, real_t p_phi)
153 	{
154 		this = rotated(p_axis, p_phi);
155 	}
156 	
157 	Basis rotated(in Vector3 p_axis, real_t p_phi) const
158 	{
159 		return Basis(p_axis, p_phi) * (this);
160 	}
161 	
162 	void scale( in Vector3 p_scale )
163 	{
164 		elements[0][0]*=p_scale.x;
165 		elements[0][1]*=p_scale.x;
166 		elements[0][2]*=p_scale.x;
167 		elements[1][0]*=p_scale.y;
168 		elements[1][1]*=p_scale.y;
169 		elements[1][2]*=p_scale.y;
170 		elements[2][0]*=p_scale.z;
171 		elements[2][1]*=p_scale.z;
172 		elements[2][2]*=p_scale.z;
173 	}
174 	
175 	Basis scaled( in Vector3 p_scale ) const
176 	{
177 		Basis b = this;
178 		b.scale(p_scale);
179 		return b;
180 	}
181 	
182 	Vector3 getScale() const
183 	{
184 		// We are assuming M = R.S, and performing a polar decomposition to extract R and S.
185 		// FIXME: We eventually need a proper polar decomposition.
186 		// As a cheap workaround until then, to ensure that R is a proper rotation matrix with determinant +1
187 		// (such that it can be represented by a Quat or Euler angles), we absorb the sign flip into the scaling matrix.
188 		// As such, it works in conjuction with get_rotation().
189 		real_t det_sign = determinant() > 0 ? 1 : -1;
190 		return det_sign*Vector3(
191 			Vector3(elements[0][0],elements[1][0],elements[2][0]).length,
192 			Vector3(elements[0][1],elements[1][1],elements[2][1]).length,
193 			Vector3(elements[0][2],elements[1][2],elements[2][2]).length
194 		);
195 	}
196 	
197 	Vector3 getEuler() const
198 	{
199 		// Euler angles in XYZ convention.
200 		// See https://en.wikipedia.org/wiki/Euler_angles#Rotation_matrix
201 		//
202 		// rot =  cy*cz		  -cy*sz		   sy
203 		//		cz*sx*sy+cx*sz  cx*cz-sx*sy*sz -cy*sx
204 		//	   -cx*cz*sy+sx*sz  cz*sx+cx*sy*sz  cx*cy
205 	
206 		Vector3 euler;
207 	
208 		if (isRotation() == false)
209 			return euler;
210 	
211 		euler.y = asin(elements[0][2]);
212 		if( euler.y < PI*0.5)
213 		{
214 			if( euler.y > -PI*0.5)
215 			{
216 				euler.x = atan2(-elements[1][2],elements[2][2]);
217 				euler.z = atan2(-elements[0][1],elements[0][0]);
218 			}
219 			else
220 			{
221 				real_t r = atan2(elements[1][0],elements[1][1]);
222 				euler.z = 0.0;
223 				euler.x = euler.z - r;
224 			}
225 		}
226 		else
227 		{
228 			real_t r = atan2(elements[0][1],elements[1][1]);
229 			euler.z = 0;
230 			euler.x = r - euler.z;
231 		}
232 		return euler;
233 	}
234 	
235 	void setEuler(in Vector3 p_euler)
236 	{
237 		real_t c, s;
238 	
239 		c = cos(p_euler.x);
240 		s = sin(p_euler.x);
241 		Basis xmat = Basis(1.0,0.0,0.0,0.0,c,-s,0.0,s,c);
242 	
243 		c = cos(p_euler.y);
244 		s = sin(p_euler.y);
245 		Basis ymat = Basis(c,0.0,s,0.0,1.0,0.0,-s,0.0,c);
246 	
247 		c = cos(p_euler.z);
248 		s = sin(p_euler.z);
249 		Basis zmat = Basis(c,-s,0.0,s,c,0.0,0.0,0.0,1.0);
250 	
251 		//optimizer will optimize away all this anyway
252 		this = xmat*(ymat*zmat);
253 	}
254 	
255 	// transposed dot products
256 	real_t tdotx(in Vector3 v) const
257 	{
258 		return elements[0][0] * v[0] + elements[1][0] * v[1] + elements[2][0] * v[2];
259 	}
260 	real_t tdoty(in Vector3 v) const
261 	{
262 		return elements[0][1] * v[0] + elements[1][1] * v[1] + elements[2][1] * v[2];
263 	}
264 	real_t tdotz(in Vector3 v) const
265 	{
266 		return elements[0][2] * v[0] + elements[1][2] * v[1] + elements[2][2] * v[2];
267 	}
268 	
269 	int opCmp(in Basis other) const
270 	{
271 		for (int i=0;i<3;i++)
272 		{
273 			for (int j=0;j<3;j++)
274 			{
275 				if (elements[i][j] != other.elements[i][j])
276 					return (elements[i][j] > other.elements[i][j])?1:-1;
277 			}
278 		}
279 		return 0;
280 	}
281 	
282 	Vector3 xform(in Vector3 p_vector) const
283 	{
284 		return Vector3(
285 			elements[0].dot(p_vector),
286 			elements[1].dot(p_vector),
287 			elements[2].dot(p_vector)
288 		);
289 	}
290 	
291 	Vector3 xformInv(in Vector3 p_vector) const
292 	{
293 		return Vector3(
294 			(elements[0][0]*p_vector.x ) + ( elements[1][0]*p_vector.y ) + ( elements[2][0]*p_vector.z ),
295 			(elements[0][1]*p_vector.x ) + ( elements[1][1]*p_vector.y ) + ( elements[2][1]*p_vector.z ),
296 			(elements[0][2]*p_vector.x ) + ( elements[1][2]*p_vector.y ) + ( elements[2][2]*p_vector.z )
297 		);
298 	}
299 	void opOpAssign(string op : "*")(in Basis p_matrix)
300 	{
301 		set(
302 			p_matrix.tdotx(elements[0]), p_matrix.tdoty(elements[0]), p_matrix.tdotz(elements[0]),
303 			p_matrix.tdotx(elements[1]), p_matrix.tdoty(elements[1]), p_matrix.tdotz(elements[1]),
304 			p_matrix.tdotx(elements[2]), p_matrix.tdoty(elements[2]), p_matrix.tdotz(elements[2]));
305 	
306 	}
307 	
308 	Basis opBinary(string op : "*")(in Basis p_matrix) const
309 	{
310 		return Basis(
311 			p_matrix.tdotx(elements[0]), p_matrix.tdoty(elements[0]), p_matrix.tdotz(elements[0]),
312 			p_matrix.tdotx(elements[1]), p_matrix.tdoty(elements[1]), p_matrix.tdotz(elements[1]),
313 			p_matrix.tdotx(elements[2]), p_matrix.tdoty(elements[2]), p_matrix.tdotz(elements[2]) );
314 	
315 	}
316 	
317 	
318 	void opOpAssign(string op : "+")(in Basis p_matrix)
319 	{
320 		elements[0] += p_matrix.elements[0];
321 		elements[1] += p_matrix.elements[1];
322 		elements[2] += p_matrix.elements[2];
323 	}
324 	
325 	Basis opBinary(string op : "+")(in Basis p_matrix) const
326 	{
327 		Basis ret = this;
328 		ret += p_matrix;
329 		return ret;
330 	}
331 	
332 	void opOpAssign(string op : "-")(in Basis p_matrix)
333 	{
334 		elements[0] -= p_matrix.elements[0];
335 		elements[1] -= p_matrix.elements[1];
336 		elements[2] -= p_matrix.elements[2];
337 	}
338 	
339 	Basis opBinary(string op : "-")(in Basis p_matrix) const
340 	{
341 		Basis ret = this;
342 		ret -= p_matrix;
343 		return ret;
344 	}
345 	
346 	void opOpAssign(string op : "*")(real_t p_val) {
347 	
348 		elements[0]*=p_val;
349 		elements[1]*=p_val;
350 		elements[2]*=p_val;
351 	}
352 	
353 	Basis opBinary(string op : "*")(real_t p_val) const {
354 	
355 			Basis ret = this;
356 			ret *= p_val;
357 			return ret;
358 	}
359 	
360 	
361 	/++String opCast(T : String)() const
362 	{
363 		String s;
364 		// @Todo
365 		return s;
366 	}+/
367 	
368 	/* create / set */
369 	
370 	
371 	void set(real_t xx, real_t xy, real_t xz, real_t yx, real_t yy, real_t yz, real_t zx, real_t zy, real_t zz)
372 	{
373 		elements[0][0]=xx;
374 		elements[0][1]=xy;
375 		elements[0][2]=xz;
376 		elements[1][0]=yx;
377 		elements[1][1]=yy;
378 		elements[1][2]=yz;
379 		elements[2][0]=zx;
380 		elements[2][1]=zy;
381 		elements[2][2]=zz;
382 	}
383 	Vector3 getColumn(int i) const
384 	{
385 		return Vector3(elements[0][i],elements[1][i],elements[2][i]);
386 	}
387 	
388 	Vector3 getRow(int i) const
389 	{
390 		return Vector3(elements[i][0],elements[i][1],elements[i][2]);
391 	}
392 	Vector3 getMainDiagonal() const
393 	{
394 		return Vector3(elements[0][0],elements[1][1],elements[2][2]);
395 	}
396 	
397 	void setRow(int i, in Vector3 p_row)
398 	{
399 		elements[i][0]=p_row.x;
400 		elements[i][1]=p_row.y;
401 		elements[i][2]=p_row.z;
402 	}
403 	
404 	Basis transposeXform(in Basis m) const
405 	{
406 		return Basis(
407 			elements[0].x * m[0].x + elements[1].x * m[1].x + elements[2].x * m[2].x,
408 			elements[0].x * m[0].y + elements[1].x * m[1].y + elements[2].x * m[2].y,
409 			elements[0].x * m[0].z + elements[1].x * m[1].z + elements[2].x * m[2].z,
410 			elements[0].y * m[0].x + elements[1].y * m[1].x + elements[2].y * m[2].x,
411 			elements[0].y * m[0].y + elements[1].y * m[1].y + elements[2].y * m[2].y,
412 			elements[0].y * m[0].z + elements[1].y * m[1].z + elements[2].y * m[2].z,
413 			elements[0].z * m[0].x + elements[1].z * m[1].x + elements[2].z * m[2].x,
414 			elements[0].z * m[0].y + elements[1].z * m[1].y + elements[2].z * m[2].y,
415 			elements[0].z * m[0].z + elements[1].z * m[1].z + elements[2].z * m[2].z);
416 	}
417 	
418 	void orthonormalize()
419 	{
420 		///ERR_FAIL_COND(determinant() != 0);
421 		
422 		// Gram-Schmidt Process
423 		
424 		Vector3 x=getAxis(0);
425 		Vector3 y=getAxis(1);
426 		Vector3 z=getAxis(2);
427 		
428 		x.normalize();
429 		y = (y-x*(x.dot(y)));
430 		y.normalize();
431 		z = (z-x*(x.dot(z))-y*(y.dot(z)));
432 		z.normalize();
433 		
434 		setAxis(0,x);
435 		setAxis(1,y);
436 		setAxis(2,z);
437 	}
438 	
439 	Basis orthonormalized() const
440 	{
441 		Basis b = this;
442 		b.orthonormalize();
443 		return b;
444 	}
445 	
446 	bool isSymmetric() const
447 	{
448 		if (fabs(elements[0][1] - elements[1][0]) > CMP_EPSILON)
449 			return false;
450 		if (fabs(elements[0][2] - elements[2][0]) > CMP_EPSILON)
451 			return false;
452 		if (fabs(elements[1][2] - elements[2][1]) > CMP_EPSILON)
453 			return false;
454 	
455 		return true;
456 	}
457 	
458 	Basis diagonalize()
459 	{
460 		// much copy paste, WOW
461 		if (!isSymmetric())
462 			return Basis();
463 	
464 		const int ite_max = 1024;
465 	
466 		real_t off_matrix_norm_2 = elements[0][1] * elements[0][1] + elements[0][2] * elements[0][2] + elements[1][2] * elements[1][2];
467 	
468 		int ite = 0;
469 		Basis acc_rot;
470 		while (off_matrix_norm_2 > CMP_EPSILON2 && ite++ < ite_max )
471 		{
472 			real_t el01_2 = elements[0][1] * elements[0][1];
473 			real_t el02_2 = elements[0][2] * elements[0][2];
474 			real_t el12_2 = elements[1][2] * elements[1][2];
475 			// Find the pivot element
476 			int i, j;
477 			if (el01_2 > el02_2) {
478 				if (el12_2 > el01_2) {
479 					i = 1;
480 					j = 2;
481 				} else {
482 					i = 0;
483 					j = 1;
484 				}
485 			} else {
486 				if (el12_2 > el02_2) {
487 					i = 1;
488 					j = 2;
489 				} else {
490 					i = 0;
491 					j = 2;
492 				}
493 			}
494 	
495 			// Compute the rotation angle
496 			real_t angle;
497 			if (fabs(elements[j][j] - elements[i][i]) < CMP_EPSILON)
498 			{
499 				angle = PI / 4;
500 			}
501 			else
502 			{
503 				angle = 0.5 * atan(2 * elements[i][j] / (elements[j][j] - elements[i][i]));
504 			}
505 	
506 			// Compute the rotation matrix
507 			Basis rot;
508 			rot.elements[i][i] = rot.elements[j][j] = cos(angle);
509 			rot.elements[i][j] = - (rot.elements[j][i] = sin(angle));
510 	
511 			// Update the off matrix norm
512 			off_matrix_norm_2 -= elements[i][j] * elements[i][j];
513 	
514 			// Apply the rotation
515 			this = rot * this * rot.transposed();
516 			acc_rot = rot * acc_rot;
517 		}
518 	
519 		return acc_rot;
520 	}
521 	
522 	
523 	static immutable Basis[24] _ortho_bases =
524 	[
525 		Basis(1, 0, 0, 0, 1, 0, 0, 0, 1),
526 		Basis(0, -1, 0, 1, 0, 0, 0, 0, 1),
527 		Basis(-1, 0, 0, 0, -1, 0, 0, 0, 1),
528 		Basis(0, 1, 0, -1, 0, 0, 0, 0, 1),
529 		Basis(1, 0, 0, 0, 0, -1, 0, 1, 0),
530 		Basis(0, 0, 1, 1, 0, 0, 0, 1, 0),
531 		Basis(-1, 0, 0, 0, 0, 1, 0, 1, 0),
532 		Basis(0, 0, -1, -1, 0, 0, 0, 1, 0),
533 		Basis(1, 0, 0, 0, -1, 0, 0, 0, -1),
534 		Basis(0, 1, 0, 1, 0, 0, 0, 0, -1),
535 		Basis(-1, 0, 0, 0, 1, 0, 0, 0, -1),
536 		Basis(0, -1, 0, -1, 0, 0, 0, 0, -1),
537 		Basis(1, 0, 0, 0, 0, 1, 0, -1, 0),
538 		Basis(0, 0, -1, 1, 0, 0, 0, -1, 0),
539 		Basis(-1, 0, 0, 0, 0, -1, 0, -1, 0),
540 		Basis(0, 0, 1, -1, 0, 0, 0, -1, 0),
541 		Basis(0, 0, 1, 0, 1, 0, -1, 0, 0),
542 		Basis(0, -1, 0, 0, 0, 1, -1, 0, 0),
543 		Basis(0, 0, -1, 0, -1, 0, -1, 0, 0),
544 		Basis(0, 1, 0, 0, 0, -1, -1, 0, 0),
545 		Basis(0, 0, 1, 0, -1, 0, 1, 0, 0),
546 		Basis(0, 1, 0, 0, 0, 1, 1, 0, 0),
547 		Basis(0, 0, -1, 0, 1, 0, 1, 0, 0),
548 		Basis(0, -1, 0, 0, 0, -1, 1, 0, 0)
549 	];
550 	
551 	
552 	int getOrthogonalIndex() const
553 	{
554 		//could be sped up if i come up with a way
555 		Basis orth=this;
556 		for(int i=0;i<3;i++) {
557 			for(int j=0;j<3;j++) {
558 	
559 				real_t v = orth[i][j];
560 				if (v>0.5)
561 					v=1.0;
562 				else if (v<-0.5)
563 					v=-1.0;
564 				else
565 					v=0;
566 	
567 				orth[i][j]=v;
568 			}
569 		}
570 	
571 		for(int i=0;i<24;i++) {
572 	
573 			if (_ortho_bases[i]==orth)
574 				return i;
575 	
576 	
577 		}
578 	
579 		return 0;
580 	}
581 	
582 	
583 	void setOrthogonalIndex(int p_index)
584 	{
585 		//there only exist 24 orthogonal bases in r3
586 		///ERR_FAIL_COND(p_index >= 24);
587 		this=_ortho_bases[p_index];
588 	}
589 	
590 	
591 	
592 	this(in Vector3 p_euler)
593 	{
594 		setEuler( p_euler );
595 	}
596 	
597 	this(in Quat p_quat)
598 	{
599 	
600 		real_t d = p_quat.lengthSquared();
601 		real_t s = 2.0 / d;
602 		real_t xs = p_quat.x * s,   ys = p_quat.y * s,   zs = p_quat.z * s;
603 		real_t wx = p_quat.w * xs,  wy = p_quat.w * ys,  wz = p_quat.w * zs;
604 		real_t xx = p_quat.x * xs,  xy = p_quat.x * ys,  xz = p_quat.x * zs;
605 		real_t yy = p_quat.y * ys,  yz = p_quat.y * zs,  zz = p_quat.z * zs;
606 		set(	1.0 - (yy + zz), xy - wz, xz + wy,
607 			xy + wz, 1.0 - (xx + zz), yz - wx,
608 			xz - wy, yz + wx, 1.0 - (xx + yy))	;
609 	
610 	}
611 	
612 	this(in Vector3 p_axis, real_t p_phi)
613 	{
614 		// Rotation matrix from axis and angle, see https://en.wikipedia.org/wiki/Rotation_matrix#Rotation_matrix_from_axis_and_angle
615 	
616 		Vector3 axis_sq = Vector3(p_axis.x*p_axis.x,p_axis.y*p_axis.y,p_axis.z*p_axis.z);
617 	
618 		real_t cosine= cos(p_phi);
619 		real_t sine= sin(p_phi);
620 	
621 		elements[0][0] = axis_sq.x + cosine * ( 1.0 - axis_sq.x );
622 		elements[0][1] = p_axis.x * p_axis.y *  ( 1.0 - cosine ) - p_axis.z * sine;
623 		elements[0][2] = p_axis.z * p_axis.x * ( 1.0 - cosine ) + p_axis.y * sine;
624 	
625 		elements[1][0] = p_axis.x * p_axis.y * ( 1.0 - cosine ) + p_axis.z * sine;
626 		elements[1][1] = axis_sq.y + cosine  * ( 1.0 - axis_sq.y );
627 		elements[1][2] = p_axis.y * p_axis.z * ( 1.0 - cosine ) - p_axis.x * sine;
628 	
629 		elements[2][0] = p_axis.z * p_axis.x * ( 1.0 - cosine ) - p_axis.y * sine;
630 		elements[2][1] = p_axis.y * p_axis.z * ( 1.0 - cosine ) + p_axis.x * sine;
631 		elements[2][2] = axis_sq.z + cosine  * ( 1.0 - axis_sq.z );
632 	
633 	}
634 	
635 	Quat quat() const
636 	{
637 		///ERR_FAIL_COND_V(is_rotation() == false, Quat());
638 		
639 		real_t trace = elements[0][0] + elements[1][1] + elements[2][2];
640 		real_t[4] temp;
641 		
642 		if (trace > 0.0)
643 		{
644 			real_t s = sqrt(trace + 1.0);
645 			temp[3]=(s * 0.5);
646 			s = 0.5 / s;
647 	
648 			temp[0]=((elements[2][1] - elements[1][2]) * s);
649 			temp[1]=((elements[0][2] - elements[2][0]) * s);
650 			temp[2]=((elements[1][0] - elements[0][1]) * s);
651 		}
652 		else
653 		{
654 			int i = elements[0][0] < elements[1][1] ?
655 				(elements[1][1] < elements[2][2] ? 2 : 1) :
656 				(elements[0][0] < elements[2][2] ? 2 : 0);
657 			int j = (i + 1) % 3;
658 			int k = (i + 2) % 3;
659 	
660 			real_t s = sqrt(elements[i][i] - elements[j][j] - elements[k][k] + 1.0);
661 			temp[i] = s * 0.5;
662 			s = 0.5 / s;
663 	
664 			temp[3] = (elements[k][j] - elements[j][k]) * s;
665 			temp[j] = (elements[j][i] + elements[i][j]) * s;
666 			temp[k] = (elements[k][i] + elements[i][k]) * s;
667 		}
668 		return Quat(temp[0],temp[1],temp[2],temp[3]);
669 	}
670 }
671 
672 
673