Subversion Repositories gelsvn

Rev

Rev 89 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 bj 1
#ifndef __CGLA_ARITHSQMAT4X4FLOAT_H
2
#define __CGLA_ARITHSQMAT4X4FLOAT_H
3
 
4
#include "ExceptionStandard.h"
5
#include "CGLA.h"
6
#include "Vec3f.h"
7
#include "Vec3Hf.h"
8
#include "Vec4f.h"
9
#include "ArithSqMatFloat.h"
10
 
11
 
12 jab 12
namespace CGLA 
13
{
14
  CGLA_DERIVEEXCEPTION(Mat4x4fException)
15
  CGLA_DERIVEEXCEPTION(Mat4x4fNotAffine)
16
  CGLA_DERIVEEXCEPTION(Mat4x4fSingular)
17
 
89 jab 18
  /** \brief 4 by 4 float matrix template.
19
 
20
      this class template is useful for transformations such as perspective 
12 jab 21
      projections or translation where 3x3 matrices do not suffice. */
22
  template<class VT, class M>
23
  class ArithSqMat4x4Float: public ArithSqMatFloat<VT, M, 4>
24
  {
25
  public:
26
 
27
    /// Vector type
28
    typedef VT VectorType;
29
 
30
    /// The type of a matrix element
31
    typedef typename VT::ScalarType ScalarType;
32
 
33
  public:
34
 
35
    /// Construct a Mat4x4f from four V vectors
36
    ArithSqMat4x4Float(VT a, VT b, VT c, VT d): 
37
      ArithSqMatFloat<VT, M, 4> (a,b,c,d) {}
2 bj 38
 
12 jab 39
    /// Construct the NAN matrix
40
    ArithSqMat4x4Float() {}
2 bj 41
 
12 jab 42
    /// Construct matrix where all values are equal to constructor argument.
43
    explicit ArithSqMat4x4Float(ScalarType  _a):
44
      ArithSqMatFloat<VT,M,4>(_a) {}
10 jab 45
 
12 jab 46
    /** Multiply vector onto matrix. Here the fourth coordinate 
47
	is se to 0. This removes any translation from the matrix.
48
	Useful if one wants to transform a vector which does not
49
	represent a point but a direction. Note that this is not
50
	correct for transforming normal vectors if the matric 
51
	contains anisotropic scaling. */
52
    template<class T, class VecT>
53
    const VecT mul_3D_vector(const ArithVec3Float<T,VecT>& v_in) const
54
    {
55
      VT v_out  = (*this) * VT(v_in[0],v_in[1],v_in[2],0);
56
      return VecT(v_out[0],v_out[1],v_out[2]);
57
    }
10 jab 58
 
12 jab 59
    /** Multiply 3D point onto matrix. Here the fourth coordinate 
60
	becomes 1 to ensure that the point is translated. Note that
61
	the vector is converted back into a Vec3f without any 
62
	division by w. This is deliberate: Typically, w=1 except
63
	for projections. If we are doing projection, we can use
64
	project_3D_point instead */
65
    template<class T, class VecT>
66
    const VecT mul_3D_point(const ArithVec3Float<T,VecT> & v_in) const
67
    {
68
      VT v_out  = (*this) * VT(v_in[0],v_in[1],v_in[2],1);
69
      return VecT(v_out[0],v_out[1],v_out[2]);
70
    }
2 bj 71
 
12 jab 72
    /** Multiply 3D point onto matrix. We set w=1 before 
73
	multiplication and divide by w after multiplication. */
74
    template<class T, class VecT>
75
    const VecT project_3D_point(const ArithVec3Float<T,VecT>& v_in) const
76
    {
77
      VT v_out = (*this) * VT(v_in[0],v_in[1],v_in[2],1);
78
      v_out.de_homogenize();
79
      return VecT(v_out[0],v_out[1],v_out[2]);
80
    }
2 bj 81
 
12 jab 82
  };
2 bj 83
 
12 jab 84
  /** Compute the adjoint of a matrix. This is the matrix where each
85
      entry is the subdeterminant of 'in' where the row and column of 
86
      the element is removed. Use mostly to compute the inverse */
87
  template<class VT, class M>
88
  M adjoint(const ArithSqMat4x4Float<VT,M>&);
2 bj 89
 
325 jab 90
	/** Compute the determinant of a 4x4 matrix. The code below is what
91
			I found to be most robust. The original implementation used direct
92
			computation of the 3x3 sub-determinants and I also tried a direct
93
			computation based on enumerating all permutations. The code below
94
			is better. */
95
	template<class V, class M>
96
			inline double determinant(const ArithSqMat4x4Float<V,M>& m)
97
			{
98
/* 					return m[0][0] * (m[1][1]*(m[2][2]*m[3][3]-m[3][2]*m[2][3])- */
99
/* 														m[2][1]*(m[1][2]*m[3][3]-m[3][2]*m[1][3])+ */
100
/* 														m[3][1]*(m[1][2]*m[2][3]-m[2][2]*m[1][3])) */
101
/* 							- m[1][0] * (m[0][1]*(m[2][2]*m[3][3]-m[3][2]*m[2][3])- */
102
/* 													 m[2][1]*(m[0][2]*m[3][3]-m[3][2]*m[0][3])+ */
103
/* 													 m[3][1]*(m[0][2]*m[2][3]-m[2][2]*m[0][3])) */
104
/* 							+ m[2][0] * (m[0][1]*(m[1][2]*m[3][3]-m[3][2]*m[1][3])- */
105
/* 													 m[1][1]*(m[0][2]*m[3][3]-m[3][2]*m[0][3])+ */
106
/* 													 m[3][1]*(m[0][2]*m[1][3]-m[1][2]*m[0][3])) */
107
/* 							- m[3][0] * (m[0][1]*(m[1][2]*m[2][3]-m[2][2]*m[1][3])- */
108
/* 													 m[1][1]*(m[0][2]*m[2][3]-m[2][2]*m[0][3])+ */
109
/* 													 m[2][1]*(m[0][2]*m[1][3]-m[1][2]*m[0][3])); */
110
		typedef typename M::ScalarType ScalarType;
111
    ScalarType a1, a2, a3, a4, b1, b2, b3, b4, c1, c2, c3, c4, d1, d2, d3, d4;
112
 
113
    /* assign to individual variable names to aid selecting */
114
		/*  correct elements */
115
 
116
		a1 = m[0][0]; b1 = m[1][0]; c1 = m[2][0]; d1 = m[3][0];
117
		a2 = m[0][1]; b2 = m[1][1]; c2 = m[2][1]; d2 = m[3][1];
118
		a3 = m[0][2]; b3 = m[1][2]; c3 = m[2][2]; d3 = m[3][2];
119
		a4 = m[0][3]; b4 = m[1][3]; c4 = m[2][3]; d4 = m[3][3];
2 bj 120
 
325 jab 121
					return 
122
							a1 * (b2*(c3*d4-d3*c4)-c2*(b3*d4-d3*b4)+d2*(b3*c4-c3*b4))
123
							- b1 * (a2*(c3*d4-d3*c4)-c2*(a3*d4-d3*a4)+d2*(a3*c4-c3*a4))
124
							+ c1 * (a2*(b3*d4-d3*b4)-b2*(a3*d4-d3*a4)+d2*(a3*b4-b3*a4))
125
							- d1 * (a2*(b3*c4-c3*b4)-b2*(a3*c4-c3*a4)+c2*(a3*b4-b3*a4));
126
 
127
			}
128
 
12 jab 129
  /// Compute the inverse matrix of a Mat4x4f.
130
  template<class VT, class M>
131
  M invert(const ArithSqMat4x4Float<VT,M>&);
2 bj 132
 
12 jab 133
  /// Compute the inverse matrix of a Mat4x4f that is affine
134
  template<class VT, class M>
135
  M invert_affine(const ArithSqMat4x4Float<VT,M>&);
2 bj 136
 
137
}
138
#endif
139
 
140
 
141
 
142
 
143
 
144
 
145