1
//---------------------------------------------------------------------------
3
// Project: OpenWalnut ( http://www.openwalnut.org )
5
// Copyright 2009 OpenWalnut Community, BSV-Leipzig and CNCF-CBS
6
// For more information see http://www.openwalnut.org/copying
8
// This file is part of OpenWalnut.
10
// OpenWalnut is free software: you can redistribute it and/or modify
11
// it under the terms of the GNU Lesser General Public License as published by
12
// the Free Software Foundation, either version 3 of the License, or
13
// (at your option) any later version.
15
// OpenWalnut is distributed in the hope that it will be useful,
16
// but WITHOUT ANY WARRANTY; without even the implied warranty of
17
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18
// GNU Lesser General Public License for more details.
20
// You should have received a copy of the GNU Lesser General Public License
21
// along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
23
//---------------------------------------------------------------------------
25
#ifndef WGETENSORTOOLS_GLSL
26
#define WGETENSORTOOLS_GLSL
30
// (c) 2007 by Mario Hlawitschka
32
// tensors have to be stored in the following way:
33
// diag.x = Dxx Diagonal elements are stored in one vector
36
// offdiag.x = Dyz Off diagonal elements are stored in another vector
37
// offdiag.y = Dxz where all components are stored in that location
38
// offdiag.z = Dxy that is indexed by the coordinate that is not in the tensor index
41
// compute the eigenvalues of a tensor
42
// (Hasan et al. 2001)
43
vec3 getEigenvaluesHasan( vec3 diag, vec3 offdiag )
45
const float PiThird = 3.14159265358979323846264 / 3.;
46
float I1 = diag.x + diag.y + diag.z;
47
float I2 = diag.x * diag.y + diag.x * diag.z + diag.y * diag.z - dot( offdiag, offdiag );
48
float I3 = diag.x * diag.y * diag.z + 2. * offdiag.x * offdiag.y * offdiag.z
49
- ( diag.x * offdiag.x * offdiag.x + diag.y * offdiag.y * offdiag.y + diag.z * offdiag.z * offdiag.z );
51
const float third = 1. / 3.;
52
float I1third = I1 * third;
53
float I1thirdsqr = I1third * I1third;
54
float I2third = I2 * third;
55
float v = I1thirdsqr - I2third;
61
//if( v < 0.000001 ) lambda = vec3(1.,0.,0.);
64
float s = I1thirdsqr * I1third - I1 * I2/6. + 0.5 * I3;
66
// for real eigenvalues: v>0, s^2 < v^3
67
float sqrtv = sqrt( v );
68
float phi= acos( s / ( v * sqrtv ) ) * third;
70
float sqrtv2 = 2. * sqrtv;
72
// due to the cosine function and the fact, that 0 <= phi <= pi/3
73
// it is obvious that the eigenvalues need no further sorting
74
lambda.x = I1third + sqrtv2 * cos( phi );
75
lambda.y = I1third - sqrtv2 * cos( PiThird + phi );
76
lambda.z = I1third - sqrtv2 * cos( PiThird - phi );
82
// Method similar to the above by Hasan proposed by Cardano et al.
83
// implementation is more stable than the above one, so use this as
84
// default in all applications
90
vec3 getEigenvaluesCardano( in vec3 diag, in vec3 offdiag )
92
const float M_SQRT3 = 1.73205080756887729352744634151;
93
float de = offdiag.z * offdiag.x;
94
float dd = sqr( offdiag.z );
95
float ee = sqr( offdiag.x );
96
float ff = sqr( offdiag.y );
97
float m = diag.x + diag.y + diag.z;
98
float c1 = diag.x * diag.y + diag.x * diag.z + diag.y * diag.z
100
float c0 = diag.z * dd + diag.x * ee + diag.y * ff - diag.x * diag.y * diag.z - 2. * offdiag.y * de;
102
float p, sqrt_p, q, c, s, phi;
103
p = sqr( m ) - 3. * c1;
104
q = m * ( p - ( 3. / 2. ) * c1 ) - ( 27. / 2. ) * c0;
105
sqrt_p = sqrt( abs( p ) );
107
phi = 27. * ( 0.25 * sqr( c1 ) * ( p - c1 ) + c0 * ( q + 27. / 4. * c0 ) );
108
phi = ( 1. / 3. ) * atan( sqrt( abs( phi ) ), q );
110
c = sqrt_p * cos( phi );
111
s = ( 1. / M_SQRT3 ) * sqrt_p * sin( phi );
114
w[2] = ( 1. / 3. ) * ( m - c );
121
vec3 getEigenvalues( in vec3 diag, in vec3 offdiag )
123
return getEigenvaluesCardano( diag, offdiag );
126
float getMajorEigenvalue( vec3 diag, vec3 offdiag )
128
return getEigenvalues( diag, offdiag )[0];
132
* use the above if more than one eigenvector is required and only use this if you need exactly one value
134
float getMajorEigenvalueOld( vec3 diag, vec3 offdiag )
136
const float PiThird = 3.14159265358979323846264/3.;
137
float I1 = diag.x + diag.y + diag.z;
138
float I2 = diag.x * diag.y + diag.x * diag.z + diag.y * diag.z - dot( offdiag, offdiag );
139
float I3 = diag.x * diag.y * diag.z + 2. * offdiag.x * offdiag.y * offdiag.z
140
- ( diag.x * offdiag.x * offdiag.x + diag.y * offdiag.y * offdiag.y + diag.z * offdiag.z * offdiag.z );
142
const float third = 1. / 3.;
143
float I1third = I1 * third;
144
float I1thirdsqr = I1third * I1third;
145
float I2third = I2 * third;
146
float v = I1thirdsqr - I2third;
150
float s = I1thirdsqr * I1third - I1 * I2 / 6. + 0.5 * I3;
152
// for real eigenvalues: v>0, s^2 < v^3
153
float sqrtv = sqrt( v );
154
float phi= acos( s / ( v * sqrtv ) ) * third;
156
float sqrtv2 = 2. * sqrtv;
158
// due to the cosine function and the fact, that 0 <= phi <= pi/3
159
// it is obvious that the eigenvalues need no further sorting
160
return I1third + sqrtv2 * cos( phi );
163
// compute vector direction depending on information computed by getEigenvalues
164
// before (Hasan et al. 2001)
165
vec3 getEigenvector( vec3 ABC /*diag without eigenalue i*/, vec3 offdiag )
168
vec.x = ( offdiag.z * offdiag.x - ABC.y * offdiag.y ) * ( offdiag.y * offdiag.x - ABC.z * offdiag.z ); // FIXME
169
//< last component is missing in the paper! there is only a Dx?
170
vec.y = ( offdiag.y * offdiag.x - ABC.z * offdiag.z ) * ( offdiag.y * offdiag.z - ABC.x * offdiag.x );
171
vec.z = ( offdiag.z * offdiag.x - ABC.y * offdiag.y ) * ( offdiag.y * offdiag.z - ABC.x * offdiag.x );
173
return normalize( vec );
176
// FA as used everywhere (Kondratieva et al 2005)
177
// computes FA from eigenvalues
178
float getFA( vec3 evalues )
180
float sqrt32 = sqrt( 3. / 2. ); // would make this const, if compiler let me
181
float I1 = evalues.x + evalues.y + evalues.z;
184
deriv.x = ( evalues.x - mu );
185
deriv.y = ( evalues.y - mu );
186
deriv.z = ( evalues.z - mu );
187
float FA = sqrt32 * length( deriv ) / length( evalues );
191
// Compute FA without doing eigenvalue decomposition
192
float getFA( vec3 diag, vec3 offdiag )
194
float cross = dot( offdiag, offdiag );
195
float j2 = diag.x * diag.y + diag.y * diag.z + diag.z * diag.x - cross;
196
float j4 = dot( diag, diag ) + 2. * cross;
197
return sqrt( ( j4 - j2 ) / j4 );
201
// simple default color map, but with precomputed FA values
202
vec4 getColor( vec3 dir, float FA )
205
//dir = normalize( dir );
206
//dir = clamp( dir, 1., 1.);
207
color = vec4( abs( dir ) * FA, 1. );
211
// compute the default RGB color scheme
212
vec4 getColor( vec3 evec, vec3 evalues )
214
float fa = getFA( evalues );
215
return getColor( evec, fa );
218
// make things transparent, proportional to FA
219
vec4 getColorAlpha( vec3 evec, vec3 evalues )
221
float fa = getFA( evalues );
222
//evec = clamp( evec, 1., 1.);
223
return vec4( abs( evec ), 1. ) * fa;
226
#endif // WGETENSORTOOLS_GLSL