1 /*
2  Copyright (C) 2001-2006, William Joseph.
3  All Rights Reserved.
4 
5  This file is part of GtkRadiant.
6 
7  GtkRadiant is free software; you can redistribute it and/or modify
8  it under the terms of the GNU General Public License as published by
9  the Free Software Foundation; either version 2 of the License, or
10  (at your option) any later version.
11 
12  GtkRadiant is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  GNU General Public License for more details.
16 
17  You should have received a copy of the GNU General Public License
18  along with GtkRadiant; if not, write to the Free Software
19  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20  */
21 
22 #if !defined (INCLUDED_EXPRESSION_H)
23 #define INCLUDED_EXPRESSION_H
24 
25 #include <math/matrix.h>
26 
27 template<typename Value>
28 class Literal
29 {
30 		Value m_value;
31 	public:
32 		typedef Value value_type;
33 
Literal(const Value & value)34 		Literal (const Value& value) :
35 			m_value(value)
36 		{
37 		}
eval()38 		const value_type& eval () const
39 		{
40 			return m_value;
41 		}
42 };
43 
44 template<typename Value>
float_literal(const Value & value)45 inline Literal<Value> float_literal (const Value& value)
46 {
47 	return Literal<Value> (value);
48 }
49 
50 template<typename Expression>
float_for_expression(const Expression & expression)51 inline float float_for_expression (const Expression& expression)
52 {
53 	return expression.eval();
54 }
55 
56 template<typename First, typename Second>
57 class ScalarDivided
58 {
59 		First first;
60 		Second second;
61 	public:
62 		typedef typename First::value_type value_type;
63 
ScalarDivided(const First & first_,const Second & second_)64 		ScalarDivided (const First& first_, const Second& second_) :
65 			first(first_), second(second_)
66 		{
67 		}
eval()68 		value_type eval () const
69 		{
70 			return static_cast<value_type> (first.eval() / second.eval());
71 		}
72 };
73 
74 template<typename First, typename Second>
float_divided(const First & first,const Second & second)75 inline ScalarDivided<First, Second> float_divided (const First& first, const Second& second)
76 {
77 	return ScalarDivided<First, Second> (first, second);
78 }
79 
80 template<typename First>
float_reciprocal(const First & first)81 inline ScalarDivided<Literal<typename First::value_type> , First> float_reciprocal (const First& first)
82 {
83 	typedef typename First::value_type first_value_type;
84 	return ScalarDivided<Literal<first_value_type> , First> (float_literal(first_value_type(1.0)), first);
85 }
86 
87 template<typename First>
88 class SquareRoot
89 {
90 		First first;
91 	public:
92 		typedef typename First::value_type value_type;
93 
SquareRoot(const First & first_)94 		SquareRoot (const First& first_) :
95 			first(first_)
96 		{
97 		}
eval()98 		value_type eval () const
99 		{
100 			return static_cast<value_type> (sqrt(first.eval()));
101 		}
102 };
103 
104 template<typename First>
float_square_root(const First & first)105 inline SquareRoot<First> float_square_root (const First& first)
106 {
107 	return SquareRoot<First> (first);
108 }
109 
110 template<typename Element>
111 class BasicVector3Literal
112 {
113 		const BasicVector3<Element> m_value;
114 	public:
115 		typedef Element value_type;
116 		typedef IntegralConstant<3> dimension;
117 
BasicVector3Literal(const BasicVector3<Element> & value)118 		BasicVector3Literal (const BasicVector3<Element>& value) :
119 			m_value(value)
120 		{
121 		}
eval(unsigned int i)122 		const value_type& eval (unsigned int i) const
123 		{
124 			return m_value[i];
125 		}
126 };
127 
128 template<typename Element>
vector3_literal(const BasicVector3<Element> & value)129 inline BasicVector3Literal<Element> vector3_literal (const BasicVector3<Element>& value)
130 {
131 	return BasicVector3Literal<Element> (value);
132 }
133 
134 typedef BasicVector3Literal<float> Vector3Literal;
135 
136 template<typename Element>
137 class BasicVector3Identity
138 {
139 		const BasicVector3<Element>& m_value;
140 	public:
141 		typedef Element value_type;
142 		typedef IntegralConstant<3> dimension;
143 
BasicVector3Identity(const BasicVector3<Element> & value)144 		BasicVector3Identity (const BasicVector3<Element>& value) :
145 			m_value(value)
146 		{
147 		}
eval(unsigned int i)148 		const value_type& eval (unsigned int i) const
149 		{
150 			return m_value[i];
151 		}
152 };
153 
154 template<typename Element>
vector3_identity(const BasicVector3<Element> & value)155 inline BasicVector3Identity<Element> vector3_identity (const BasicVector3<Element>& value)
156 {
157 	return BasicVector3Identity<Element> (value);
158 }
159 
160 typedef BasicVector3Identity<float> Vector3Identity;
161 
162 template<typename Expression>
vector3_for_expression(const Expression & expression)163 inline BasicVector3<typename Expression::value_type> vector3_for_expression (const Expression& expression)
164 {
165 	return Vector3(expression.eval(0), expression.eval(1), expression.eval(2));
166 }
167 
168 template<typename Operation, typename First, typename Second>
169 class VectorScalar
170 {
171 		First first;
172 		Literal<typename Second::value_type> second;
173 	public:
174 		typedef typename First::value_type value_type;
175 		typedef typename First::dimension dimension;
176 
VectorScalar(const First & first_,const Second & second_)177 		VectorScalar (const First& first_, const Second& second_) :
178 			first(first_), second(second_.eval())
179 		{
180 		}
eval(unsigned int i)181 		value_type eval (unsigned int i) const
182 		{
183 			return Operation::apply(first.eval(i), second.eval());
184 		}
185 };
186 
187 template<typename Operation, typename First, typename Second>
188 class VectorVector
189 {
190 		First first;
191 		Second second;
192 	public:
193 		typedef typename First::value_type value_type;
194 		typedef typename First::dimension dimension;
195 
VectorVector(const First & first_,const Second & second_)196 		VectorVector (const First& first_, const Second& second_) :
197 			first(first_), second(second_)
198 		{
199 		}
eval(unsigned int i)200 		value_type eval (unsigned int i) const
201 		{
202 			return Operation::apply(first.eval(i), second.eval(i));
203 		}
204 };
205 
206 template<typename First, typename Second>
207 class Added
208 {
209 	public:
210 		typedef First value_type;
211 
apply(const First & first,const Second & second)212 		static value_type apply (const First& first, const Second& second)
213 		{
214 			return static_cast<value_type> (first + second);
215 		}
216 };
217 
218 template<typename First, typename Second>
vector_added(const First & first,const Second & second)219 inline VectorVector<Added<typename First::value_type, typename Second::value_type> , First, Second> vector_added (
220 		const First& first, const Second& second)
221 {
222 	typedef typename First::value_type first_value_type;
223 	typedef typename Second::value_type second_value_type;
224 	return VectorVector<Added<first_value_type, second_value_type> , First, Second> (first, second);
225 }
226 
227 template<typename First, typename Second>
228 class Multiplied
229 {
230 	public:
231 		typedef First value_type;
232 
apply(const First & first,const Second & second)233 		static value_type apply (const First& first, const Second& second)
234 		{
235 			return static_cast<value_type> (first * second);
236 		}
237 };
238 
239 template<typename First, typename Second>
vector_multiplied(const First & first,const Second & second)240 inline VectorVector<Multiplied<typename First::value_type, typename Second::value_type> , First, Second> vector_multiplied (
241 		const First& first, const Second& second)
242 {
243 	typedef typename First::value_type first_value_type;
244 	typedef typename Second::value_type second_value_type;
245 	return VectorVector<Multiplied<first_value_type, second_value_type> , First, Second> (first, second);
246 }
247 
248 template<typename First, typename Second>
vector_scaled(const First & first,const Second & second)249 inline VectorScalar<Multiplied<typename First::value_type, typename Second::value_type> , First, Second> vector_scaled (
250 		const First& first, const Second& second)
251 {
252 	typedef typename First::value_type first_value_type;
253 	typedef typename Second::value_type second_value_type;
254 	return VectorScalar<Multiplied<first_value_type, second_value_type> , First, Second> (first, second);
255 }
256 
257 template<typename First>
258 class Negated
259 {
260 	public:
261 		typedef First value_type;
262 
apply(const First & first)263 		static value_type apply (const First& first)
264 		{
265 			return -first;
266 		}
267 };
268 
269 template<typename First, typename Operation>
270 class VectorUnary
271 {
272 		First first;
273 	public:
274 		typedef typename First::value_type value_type;
275 		typedef typename First::dimension dimension;
276 
VectorUnary(const First & first_)277 		VectorUnary (const First& first_) :
278 			first(first_)
279 		{
280 		}
eval(unsigned int i)281 		value_type eval (unsigned int i) const
282 		{
283 			return Operation::apply(first.eval(i));
284 		}
285 };
286 
287 template<typename First>
vector_negated(const First & first)288 inline VectorUnary<First, Negated<typename First::value_type> > vector_negated (const First& first)
289 {
290 	typedef typename First::value_type first_value_type;
291 	return VectorUnary<First, Negated<first_value_type> > (first);
292 }
293 
294 template<typename First, typename Second>
295 class VectorCross
296 {
297 		First first;
298 		Second second;
299 	public:
300 		typedef typename First::value_type value_type;
301 		typedef typename First::dimension dimension;
302 
VectorCross(const First & first_,const Second & second_)303 		VectorCross (const First& first_, const Second& second_) :
304 			first(first_), second(second_)
305 		{
306 		}
eval(unsigned int i)307 		value_type eval (unsigned int i) const
308 		{
309 			return first.eval((i + 1) % 3) * second.eval((i + 2) % 3) - first.eval((i + 2) % 3) * second.eval((i + 1)
310 					% 3);
311 		}
312 };
313 
314 template<typename First, typename Second>
vector_cross(const First & first,const Second & second)315 inline VectorCross<First, Second> vector_cross (const First& first, const Second& second)
316 {
317 	return VectorCross<First, Second> (first, second);
318 }
319 
320 template<typename First, typename Second>
321 class VectorDot
322 {
323 		First first;
324 		Second second;
325 	public:
326 		typedef typename First::value_type value_type;
327 		typedef typename First::dimension dimension;
328 
VectorDot(const First & first_,const Second & second_)329 		VectorDot (const First& first_, const Second& second_) :
330 			first(first_), second(second_)
331 		{
332 		}
333 
334 		template<typename Index>
335 		struct eval_dot
336 		{
applyeval_dot337 				static value_type apply (const First& first, const Second& second)
338 				{
339 					return static_cast<value_type> (first.eval(Index::VALUE) * second.eval(Index::VALUE) + eval_dot<
340 							IntegralConstant<Index::VALUE - 1> >::apply(first, second));
341 				}
342 		};
343 
344 		template<>
345 		struct eval_dot<IntegralConstant<0> >
346 		{
347 				static value_type apply (const First& first, const Second& second)
348 				{
349 					return first.eval(0) * second.eval(0);
350 				}
351 		};
352 
353 		value_type eval () const
354 		{
355 			return eval_dot<IntegralConstant<dimension::VALUE - 1> >::apply(first, second);
356 		}
357 };
358 
359 template<typename First, typename Second>
360 inline VectorDot<First, Second> vector_dot (const First& first, const Second& second)
361 {
362 	return VectorDot<First, Second> (first, second);
363 }
364 
365 template<typename First>
366 class VectorLengthSquared
367 {
368 		First first;
369 	public:
370 		typedef typename First::value_type value_type;
371 		typedef typename First::dimension dimension;
372 
373 		VectorLengthSquared (const First& first_) :
374 			first(first_)
375 		{
376 		}
377 
378 		static value_type squared (const value_type& value)
379 		{
380 			return value * value;
381 		}
382 
383 		template<typename Index>
384 		struct eval_squared
385 		{
386 				static value_type apply (const First& first)
387 				{
388 					return static_cast<value_type> (squared(first.eval(Index::VALUE)) + eval_squared<IntegralConstant<
389 							Index::VALUE - 1> >::apply(first));
390 				}
391 		};
392 
393 		template<>
394 		struct eval_squared<IntegralConstant<0> >
395 		{
396 				static value_type apply (const First& first)
397 				{
398 					return squared(first.eval(0));
399 				}
400 		};
401 
402 		value_type eval () const
403 		{
404 			return eval_squared<IntegralConstant<dimension::VALUE - 1> >::apply(first);
405 		}
406 };
407 
408 template<typename First>
409 inline VectorLengthSquared<First> vector_length_squared (const First& first)
410 {
411 	return VectorLengthSquared<First> (first);
412 }
413 
414 template<typename First>
415 inline SquareRoot<VectorLengthSquared<First> > vector_length (const First& first)
416 {
417 	return float_square_root(vector_length_squared(first));
418 }
419 
420 template<typename First>
421 inline VectorScalar <Multiplied<typename First::value_type, typename First::value_type>,First,
422 // multiple evaulations of subexpression
423 ScalarDivided <Literal<typename First::value_type>,SquareRoot <VectorLengthSquared<First>>>> vector_normalised(const First& first) {
424 	typedef typename First::value_type first_value_type;
425 	return vector_scaled(first, float_reciprocal(vector_length(first)));
426 }
427 
428 class Matrix4Literal
429 {
430 		const Matrix4 m_value;
431 	public:
432 		typedef float value_type;
433 		typedef IntegralConstant<4> dimension0;
434 		typedef IntegralConstant<4> dimension1;
435 
436 		Matrix4Literal (const Matrix4& value) :
437 			m_value(value)
438 		{
439 		}
440 		const value_type& eval (unsigned int r, unsigned int c) const
441 		{
442 			return m_value[r * 4 + c];
443 		}
444 };
445 
446 inline Matrix4Literal matrix4_literal (const Matrix4& value)
447 {
448 	return Matrix4Literal(value);
449 }
450 
451 class Matrix4Identity
452 {
453 		const Matrix4& m_value;
454 	public:
455 		typedef float value_type;
456 		typedef IntegralConstant<4> dimension0;
457 		typedef IntegralConstant<4> dimension1;
458 
459 		Matrix4Identity (const Matrix4& value) :
460 			m_value(value)
461 		{
462 		}
463 		const value_type& eval (unsigned int r, unsigned int c) const
464 		{
465 			return m_value[r * 4 + c];
466 		}
467 };
468 
469 inline Matrix4Identity matrix4_identity (const Matrix4& value)
470 {
471 	return Matrix4Identity(value);
472 }
473 
474 template<typename Expression>
475 inline Matrix4 matrix4_for_expression (const Expression& expression)
476 {
477 	return Matrix4(expression.eval(0, 0), expression.eval(0, 1), expression.eval(0, 2), expression.eval(0, 3),
478 			expression.eval(1, 0), expression.eval(1, 1), expression.eval(1, 2), expression.eval(1, 3),
479 			expression.eval(2, 0), expression.eval(2, 1), expression.eval(2, 2), expression.eval(2, 3),
480 			expression.eval(3, 0), expression.eval(3, 1), expression.eval(3, 2), expression.eval(3, 3));
481 }
482 
483 template<typename Expression>
484 inline Matrix4 matrix4_affine_for_expression (const Expression& expression)
485 {
486 	return Matrix4(expression.eval(0, 0), expression.eval(0, 1), expression.eval(0, 2), 0, expression.eval(1, 0),
487 			expression.eval(1, 1), expression.eval(1, 2), 0, expression.eval(2, 0), expression.eval(2, 1),
488 			expression.eval(2, 2), 0, expression.eval(3, 0), expression.eval(3, 1), expression.eval(3, 2), 1);
489 }
490 
491 template<typename First, typename Second>
492 class PointMultiplied
493 {
494 		const First& first;
495 		const Second& second;
496 	public:
497 		typedef typename First::value_type value_type;
498 		typedef typename First::dimension dimension;
499 
500 		PointMultiplied (const First& first_, const Second& second_) :
501 			first(first_), second(second_)
502 		{
503 		}
504 		value_type eval (unsigned int i) const
505 		{
506 			return static_cast<value_type> (second.eval(0, i) * first.eval(0) + second.eval(1, i) * first.eval(1)
507 					+ second.eval(2, i) * first.eval(2) + second.eval(3, i));
508 		}
509 };
510 
511 template<typename First, typename Second>
512 inline PointMultiplied<First, Second> point_multiplied (const First& point, const Second& matrix)
513 {
514 	return PointMultiplied<First, Second> (point, matrix);
515 }
516 
517 template<typename First, typename Second>
518 class Matrix4Multiplied
519 {
520 		const First& first;
521 		const Second& second;
522 	public:
523 		typedef typename First::value_type value_type;
524 		typedef typename First::dimension0 dimension0;
525 		typedef typename First::dimension1 dimension1;
526 
527 		Matrix4Multiplied (const First& first_, const Second& second_) :
528 			first(first_), second(second_)
529 		{
530 		}
531 
532 		value_type eval (unsigned int r, unsigned int c) const
533 		{
534 			return static_cast<value_type> (second.eval(r, 0) * first.eval(0, c) + second.eval(r, 1) * first.eval(1, c)
535 					+ second.eval(r, 2) * first.eval(2, c) + second.eval(r, 3) * first.eval(3, c));
536 		}
537 };
538 
539 template<typename First, typename Second>
540 inline Matrix4Multiplied<First, Second> matrix4_multiplied (const First& first, const Second& second)
541 {
542 	return Matrix4Multiplied<First, Second> (first, second);
543 }
544 
545 template<typename First>
546 class MatrixTransposed
547 {
548 		const First& first;
549 	public:
550 		typedef typename First::value_type value_type;
551 		typedef typename First::dimension0 dimension0;
552 		typedef typename First::dimension1 dimension1;
553 
554 		MatrixTransposed (const First& first_) :
555 			first(first_)
556 		{
557 		}
558 
559 		value_type eval (unsigned int r, unsigned int c) const
560 		{
561 			return first.eval(c, r);
562 		}
563 };
564 
565 template<typename First>
566 inline MatrixTransposed<First> matrix_transposed (const First& first)
567 {
568 	return MatrixTransposed<First> (first);
569 }
570 
571 #endif
572