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