2 Copyright (C) 2001-2006, William Joseph.
5 This file is part of GtkRadiant.
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.
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.
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
22 #if !defined ( INCLUDED_EXPRESSION_H )
23 #define INCLUDED_EXPRESSION_H
25 #include <math/matrix.h>
27 template<typename Value>
32 typedef Value value_type;
34 Literal( const Value& value )
37 const value_type& eval() const {
42 template<typename Value>
43 inline Literal<Value> float_literal( const Value& value ){
44 return Literal<Value>( value );
47 template<typename Expression>
48 inline float float_for_expression( const Expression& expression ){
49 return expression.eval();
53 template<typename First, typename Second>
59 typedef typename First::value_type value_type;
61 ScalarDivided( const First& first_, const Second& second_ ) : first( first_ ), second( second_ ){
63 value_type eval() const {
64 return static_cast<value_type>( first.eval() / second.eval() );
68 template<typename First, typename Second>
69 inline ScalarDivided<First, Second> float_divided( const First& first, const Second& second ){
70 return ScalarDivided<First, Second>( first, second );
73 template<typename First>
74 inline ScalarDivided<Literal<typename First::value_type>, First> float_reciprocal( const First& first ){
75 typedef typename First::value_type first_value_type;
76 return ScalarDivided<Literal<first_value_type>, First>( float_literal( first_value_type( 1.0 ) ), first );
79 template<typename First>
84 typedef typename First::value_type value_type;
86 SquareRoot( const First& first_ ) : first( first_ ){
88 value_type eval() const {
89 return static_cast<value_type>( sqrt( first.eval() ) );
93 template<typename First>
94 inline SquareRoot<First> float_square_root( const First& first ){
95 return SquareRoot<First>( first );
99 template<typename Element>
100 class BasicVector3Literal
102 const BasicVector3<Element> m_value;
104 typedef Element value_type;
105 typedef IntegralConstant<3> dimension;
107 BasicVector3Literal( const BasicVector3<Element>& value )
110 const value_type& eval( unsigned int i ) const {
115 template<typename Element>
116 inline BasicVector3Literal<Element> vector3_literal( const BasicVector3<Element>& value ){
117 return BasicVector3Literal<Element>( value );
120 typedef BasicVector3Literal<float> Vector3Literal;
122 template<typename Element>
123 class BasicVector3Identity
125 const BasicVector3<Element>& m_value;
127 typedef Element value_type;
128 typedef IntegralConstant<3> dimension;
130 BasicVector3Identity( const BasicVector3<Element>& value )
133 const value_type& eval( unsigned int i ) const {
138 template<typename Element>
139 inline BasicVector3Identity<Element> vector3_identity( const BasicVector3<Element>& value ){
140 return BasicVector3Identity<Element>( value );
143 typedef BasicVector3Identity<float> Vector3Identity;
145 template<typename Expression>
146 inline BasicVector3<typename Expression::value_type> vector3_for_expression( const Expression& expression ){
147 return Vector3( expression.eval( 0 ), expression.eval( 1 ), expression.eval( 2 ) );
151 template<typename Operation, typename First, typename Second>
155 Literal<typename Second::value_type> second;
157 typedef typename First::value_type value_type;
158 typedef typename First::dimension dimension;
160 VectorScalar( const First& first_, const Second& second_ )
161 : first( first_ ), second( second_.eval() ){
163 value_type eval( unsigned int i ) const {
164 return Operation::apply( first.eval( i ), second.eval() );
170 template<typename Operation, typename First, typename Second>
176 typedef typename First::value_type value_type;
177 typedef typename First::dimension dimension;
179 VectorVector( const First& first_, const Second& second_ )
180 : first( first_ ), second( second_ ){
182 value_type eval( unsigned int i ) const {
183 return Operation::apply( first.eval( i ), second.eval( i ) );
187 template<typename First, typename Second>
191 typedef First value_type;
193 static value_type apply( const First& first, const Second& second ){
194 return static_cast<value_type>( first + second );
198 template<typename First, typename Second>
199 inline VectorVector<Added<typename First::value_type, typename Second::value_type>, First, Second>
200 vector_added( const First& first, const Second& second ){
201 typedef typename First::value_type first_value_type;
202 typedef typename Second::value_type second_value_type;
203 return VectorVector<Added<first_value_type, second_value_type>, First, Second>( first, second );
206 template<typename First, typename Second>
210 typedef First value_type;
212 static value_type apply( const First& first, const Second& second ){
213 return static_cast<value_type>( first * second );
217 template<typename First, typename Second>
218 inline VectorVector<Multiplied<typename First::value_type, typename Second::value_type>, First, Second>
219 vector_multiplied( const First& first, const Second& second ){
220 typedef typename First::value_type first_value_type;
221 typedef typename Second::value_type second_value_type;
222 return VectorVector<Multiplied<first_value_type, second_value_type>, First, Second>( first, second );
225 template<typename First, typename Second>
226 inline VectorScalar<Multiplied<typename First::value_type, typename Second::value_type>, First, Second>
227 vector_scaled( const First& first, const Second& second ){
228 typedef typename First::value_type first_value_type;
229 typedef typename Second::value_type second_value_type;
230 return VectorScalar<Multiplied<first_value_type, second_value_type>, First, Second>( first, second );
233 template<typename First>
237 typedef First value_type;
239 static value_type apply( const First& first ){
244 template<typename First, typename Operation>
249 typedef typename First::value_type value_type;
250 typedef typename First::dimension dimension;
252 VectorUnary( const First& first_ ) : first( first_ ){
254 value_type eval( unsigned int i ) const {
255 return Operation::apply( first.eval( i ) );
259 template<typename First>
260 inline VectorUnary<First, Negated<typename First::value_type> >
261 vector_negated( const First& first ){
262 typedef typename First::value_type first_value_type;
263 return VectorUnary<First, Negated<first_value_type> >( first );
266 template<typename First, typename Second>
272 typedef typename First::value_type value_type;
273 typedef typename First::dimension dimension;
275 VectorCross( const First& first_, const Second& second_ )
276 : first( first_ ), second( second_ ){
278 value_type eval( unsigned int i ) const {
279 return first.eval( ( i + 1 ) % 3 ) * second.eval( ( i + 2 ) % 3 ) - first.eval( ( i + 2 ) % 3 ) * second.eval( ( i + 1 ) % 3 );
283 template<typename First, typename Second>
284 inline VectorCross<First, Second>
285 vector_cross( const First& first, const Second& second ){
286 return VectorCross<First, Second>( first, second );
290 template<typename First, typename Second>
296 typedef typename First::value_type value_type;
297 typedef typename First::dimension dimension;
299 VectorDot( const First& first_, const Second& second_ )
300 : first( first_ ), second( second_ ){
303 template<typename Index>
306 static value_type apply( const First& first, const Second& second ){
307 return static_cast<value_type>(
308 first.eval( Index::VALUE ) * second.eval( Index::VALUE )
309 + eval_dot< IntegralConstant<Index::VALUE - 1> >::apply( first, second )
315 struct eval_dot< IntegralConstant<0> >
317 static value_type apply( const First& first, const Second& second ){
318 return first.eval( 0 ) * second.eval( 0 );
322 value_type eval() const {
323 return eval_dot< IntegralConstant<dimension::VALUE - 1> >::apply( first, second );
328 template<typename First, typename Second>
329 inline VectorDot<First, Second> vector_dot( const First& first, const Second& second ){
330 return VectorDot<First, Second>( first, second );
333 template<typename First>
334 class VectorLengthSquared
338 typedef typename First::value_type value_type;
339 typedef typename First::dimension dimension;
341 VectorLengthSquared( const First& first_ )
345 static value_type squared( const value_type& value ){
346 return value * value;
349 template<typename Index>
352 static value_type apply( const First& first ){
353 return static_cast<value_type>(
354 squared( first.eval( Index::VALUE ) )
355 + eval_squared< IntegralConstant<Index::VALUE - 1> >::apply( first )
361 struct eval_squared< IntegralConstant<0> >
363 static value_type apply( const First& first ){
364 return squared( first.eval( 0 ) );
368 value_type eval() const {
369 return eval_squared< IntegralConstant<dimension::VALUE - 1> >::apply( first );
373 template<typename First>
374 inline VectorLengthSquared<First> vector_length_squared( const First& first ){
375 return VectorLengthSquared<First>( first );
378 template<typename First>
379 inline SquareRoot< VectorLengthSquared<First> > vector_length( const First& first ){
380 return float_square_root( vector_length_squared( first ) );
384 template<typename First>
386 Multiplied<typename First::value_type, typename First::value_type>,
388 // multiple evaulations of subexpression
390 Literal<typename First::value_type>,
392 VectorLengthSquared<First>
395 > vector_normalised( const First& first ){
396 typedef typename First::value_type first_value_type;
397 return vector_scaled( first, float_reciprocal( vector_length( first ) ) );
400 template<typename First>
402 Multiplied<typename First::value_type, typename First::value_type>,
404 // single evaluation of subexpression
405 Literal<typename First::value_type>
407 vector_normalised( const First& first ){
408 typedef typename First::value_type first_value_type;
409 return vector_scaled( first, float_literal( static_cast<first_value_type>( first_value_type( 1.0 ) / vector_length( first ).eval() ) ) );
416 const Matrix4 m_value;
418 typedef float value_type;
419 typedef IntegralConstant<4> dimension0;
420 typedef IntegralConstant<4> dimension1;
422 Matrix4Literal( const Matrix4& value )
425 const value_type& eval( unsigned int r, unsigned int c ) const {
426 return m_value[r * 4 + c];
430 inline Matrix4Literal matrix4_literal( const Matrix4& value ){
431 return Matrix4Literal( value );
434 class Matrix4Identity
436 const Matrix4& m_value;
438 typedef float value_type;
439 typedef IntegralConstant<4> dimension0;
440 typedef IntegralConstant<4> dimension1;
442 Matrix4Identity( const Matrix4& value )
445 const value_type& eval( unsigned int r, unsigned int c ) const {
446 return m_value[r * 4 + c];
450 inline Matrix4Identity matrix4_identity( const Matrix4& value ){
451 return Matrix4Identity( value );
454 template<typename Expression>
455 inline Matrix4 matrix4_for_expression( const Expression& expression ){
457 expression.eval( 0, 0 ), expression.eval( 0, 1 ), expression.eval( 0, 2 ), expression.eval( 0, 3 ),
458 expression.eval( 1, 0 ), expression.eval( 1, 1 ), expression.eval( 1, 2 ), expression.eval( 1, 3 ),
459 expression.eval( 2, 0 ), expression.eval( 2, 1 ), expression.eval( 2, 2 ), expression.eval( 2, 3 ),
460 expression.eval( 3, 0 ), expression.eval( 3, 1 ), expression.eval( 3, 2 ), expression.eval( 3, 3 )
464 template<typename Expression>
465 inline Matrix4 matrix4_affine_for_expression( const Expression& expression ){
467 expression.eval( 0, 0 ), expression.eval( 0, 1 ), expression.eval( 0, 2 ), 0,
468 expression.eval( 1, 0 ), expression.eval( 1, 1 ), expression.eval( 1, 2 ), 0,
469 expression.eval( 2, 0 ), expression.eval( 2, 1 ), expression.eval( 2, 2 ), 0,
470 expression.eval( 3, 0 ), expression.eval( 3, 1 ), expression.eval( 3, 2 ), 1
475 template<typename First, typename Second>
476 class PointMultiplied
479 const Second& second;
481 typedef typename First::value_type value_type;
482 typedef typename First::dimension dimension;
484 PointMultiplied( const First& first_, const Second& second_ )
485 : first( first_ ), second( second_ ){
487 value_type eval( unsigned int i ) const {
488 return static_cast<value_type>( second.eval( 0, i ) * first.eval( 0 )
489 + second.eval( 1, i ) * first.eval( 1 )
490 + second.eval( 2, i ) * first.eval( 2 )
491 + second.eval( 3, i ) );
495 template<typename First, typename Second>
496 inline PointMultiplied<First, Second> point_multiplied( const First& point, const Second& matrix ){
497 return PointMultiplied<First, Second>( point, matrix );
500 template<typename First, typename Second>
501 class Matrix4Multiplied
504 const Second& second;
506 typedef typename First::value_type value_type;
507 typedef typename First::dimension0 dimension0;
508 typedef typename First::dimension1 dimension1;
510 Matrix4Multiplied( const First& first_, const Second& second_ )
511 : first( first_ ), second( second_ ){
514 value_type eval( unsigned int r, unsigned int c ) const {
515 return static_cast<value_type>(
516 second.eval( r, 0 ) * first.eval( 0, c )
517 + second.eval( r, 1 ) * first.eval( 1, c )
518 + second.eval( r, 2 ) * first.eval( 2, c )
519 + second.eval( r, 3 ) * first.eval( 3, c )
524 template<typename First, typename Second>
525 inline Matrix4Multiplied<First, Second> matrix4_multiplied( const First& first, const Second& second ){
526 return Matrix4Multiplied<First, Second>( first, second );
529 template<typename First>
530 class MatrixTransposed
534 typedef typename First::value_type value_type;
535 typedef typename First::dimension0 dimension0;
536 typedef typename First::dimension1 dimension1;
538 MatrixTransposed( const First& first_ )
542 value_type eval( unsigned int r, unsigned int c ) const {
543 return first.eval( c, r );
547 template<typename First>
548 inline MatrixTransposed<First> matrix_transposed( const First& first ){
549 return MatrixTransposed<First>( first );