Blame view

stim/visualization/gl_spharmonics.h 6.48 KB
487a9b49   David Mayerich   added the ability...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
  #ifndef STIM_GL_SPHARMONICS_H

  #define STIM_GL_SPHARMONICS_H

  

  #include <GL/gl.h>

  

  #include <stim/gl/error.h>

  #include <stim/visualization/colormap.h>

  #include <stim/math/spharmonics.h>

  

  namespace stim{

  

  	

  template <typename T>

  class gl_spharmonics : public spharmonics<T>{

  

  protected:

321ff17a   David Mayerich   Optimized the mat...
17
18
  	using spharmonics<T>::C;

  	using spharmonics<T>::SH;

487a9b49   David Mayerich   added the ability...
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
  	

  	T* func;		//stores the raw function data (samples at each point)

  

  	GLuint color_tex;	//texture map that acts as a colormap for the spherical function

  		

  	unsigned int N;		//resolution of the spherical grid

  

  	void gen_function(){

  

  		//initialize the function to zero

  		memset(func, 0, sizeof(double) * N * N);

  

  		double theta, phi;

  		double result;

  		int l, m;

  

  

  		l = m = 0;

  		//for each coefficient

  		for(unsigned int c = 0; c < C.size(); c++){				

  

  			//iterate through the entire 2D grid representing the function

  			for(unsigned int xi = 0; xi < N; xi++){

  				for(unsigned int yi = 0; yi < N; yi++){

  

  					//get the spherical coordinates for each grid point

  					theta = (2 * PI) * ((double)xi / (N-1));

  					phi = PI * ((double)yi / (N-1));

  

  					//sum the contribution of the current spherical harmonic based on the coefficient

  					result = C[c] * SH(l, m, theta, phi);

  

  					//store the result in a 2D array (which will later be used as a texture map)

  					func[yi * N + xi] += result;

  				}

  			}

  

  			//keep track of m and l here

  			m++;			//increment m

  			//if we're in a new tier, increment l and set m = -l

  			if(m > l){		

  				l++;

  				m = -l;

  			}

  		}

  	}

  

  	void gl_prep_draw(){

  

  		//enable depth testing

  			//this has to be used instead of culling because the sphere can have negative values

  		glEnable(GL_DEPTH_TEST);

  		glDepthMask(GL_TRUE);

  		glEnable(GL_TEXTURE_2D);	//enable 2D texture mapping

  	}

  

  	//draw a texture mapped sphere representing the function surface

  	void gl_draw_sphere() {

  

  		//bind the 2D texture representing the color map

  		glBindTexture(GL_TEXTURE_2D, color_tex);

  

  		//Draw the Sphere

  		int i, j;

  

  		for(i = 1; i <= N-1; i++) {

  			double phi0 = PI * ((double) (i - 1) / (N-1));

  			double phi1 = PI * ((double) i / (N-1));

  

  			glBegin(GL_QUAD_STRIP);

  			for(j = 0; j <= N; j++) {

  

  				//calculate the indices into the function array

  				int phi0_i = i-1;

  				int phi1_i = i;

  				int theta_i = j;

  				if(theta_i == N)

  					theta_i = 0;

  

  				double v0 = func[phi0_i * N + theta_i];

  				double v1 = func[phi1_i * N + theta_i];

  

  				v0 = fabs(v0);

  				v1 = fabs(v1);

  

  

  				double theta = 2 * PI * (double) (j - 1) / N;

  				double x0 = v0 * cos(theta) * sin(phi0);

  				double y0 = v0 * sin(theta) * sin(phi0);

  				double z0 = v0 * cos(phi0);

  

  				double x1 = v1 * cos(theta) * sin(phi1);

  				double y1 = v1 * sin(theta) * sin(phi1);

  				double z1 = v1 * cos(phi1);

  

  				glTexCoord2f(theta / (2 * PI), phi0 / PI);

  				glVertex3f(x0, y0, z0);

  

  				glTexCoord2f(theta / (2 * PI), phi1 / PI);

  				glVertex3f(x1, y1, z1);

  			}

  			glEnd();

  		}

  	}

  

  	void gl_init(unsigned int n){

  

  		//set the sphere resolution

  		N = n;

  

  		//allocate space for the color map

  		unsigned int bytes = N * N * sizeof(unsigned char) * 3;

  		unsigned char* color_image;

  		color_image = (unsigned char*) malloc(bytes);

  

  		//allocate space for the function

  		func = (double*) malloc(N * N * sizeof(double));

  

  		//generate a functional representation that will be used for the texture map and vertices

  		gen_function();

  

  		//generate a colormap from the function

  		stim::cpu2cpu<double>(func, color_image, N*N, stim::cmBrewer);

  

  		//prep everything for drawing

  		gl_prep_draw();			

  

  		//generate an OpenGL texture map in the current context

  		glGenTextures(1, &color_tex);

  		//bind the texture

  		glBindTexture(GL_TEXTURE_2D, color_tex);

  

  		//copy the color data from the buffer to the GPU

  		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, N, N, 0, GL_RGB, GL_UNSIGNED_BYTE, color_image);

  

  		//initialize all of the texture parameters

  		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);

  		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);

  		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

  		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

  		glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);

  			

  		//free the buffer

  		free(color_image);

  	}

  

  public:

761ebaa9   David Mayerich   spherical harmoni...
166
167
168
169
170
171
172
173
174
175
176
177
178
  	gl_spharmonics<T>() {

  

  	}

  

  	gl_spharmonics<T>(const spharmonics<T> copy) : gl_spharmonics<T>() {

  		C = copy.C;

  	}

  

  	gl_spharmonics<T>& operator=(const spharmonics<T> rhs) {

  		gl_spharmonics<T> result(rhs.C.size());

  		result.C = spharmonics<T>::rhs.C;

  		return result;

  	}

487a9b49   David Mayerich   added the ability...
179
180
181
182
183
184
185
186
187
188
189
190
191
192
  

  	void glRender(){

  		//set all OpenGL parameters required for drawing

  		gl_prep_draw();

  

  		//draw the sphere

  		gl_draw_sphere();

  	}

  

  	void glInit(unsigned int n = 256){

  		gl_init(n);

  		gen_function();

  	}

  

39d843e3   Pavel Govyadinov   fixed spharmonics...
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
  	//overload arithmetic operations

  	gl_spharmonics<T> operator*(T rhs) const {

  		gl_spharmonics<T> result(C.size());                                //create a new sph    erical harmonics object

  		for (size_t c = 0; c < C.size(); c++)                   //for each coefficient

  			result.C[c] = C[c] * rhs;                                       //calculat    e the factor and store the result in the new spharmonics object

  		return result;

  	}

  

  	gl_spharmonics<T> operator+(gl_spharmonics<T> rhs) {

  		size_t low = std::min(C.size(), rhs.C.size());                          //store th    e number of coefficients in the lowest object

  		size_t high = std::max(C.size(), rhs.C.size());                         //store th    e number of coefficients in the result

  		bool rhs_lowest = false;                                                                    //true if rhs has the lowest number of coefficients

  		if (rhs.C.size() < C.size()) rhs_lowest = true;                 //if rhs has a low    er number of coefficients, set the flag

  

  		gl_spharmonics<T> result(high);                                                                //create a new object

  		size_t c;

  		for (c = 0; c < low; c++)                                               //perform     the first batch of additions

  			result.C[c] = C[c] + rhs.C[c];                                          //    perform the addition

  

  		for (c = low; c < high; c++) {

  			if (rhs_lowest)

  				result.C[c] = C[c];

  			else

  				result.C[c] = rhs.C[c];

  		}

  		return result;

  	}

  

  	gl_spharmonics<T> operator-(gl_spharmonics<T> rhs) {

  		return (*this) + (rhs * (T)(-1));

  	}

  

  

  

487a9b49   David Mayerich   added the ability...
227
228
229
230
231
232
233
234
  };		//end gl_spharmonics

  

  

  };		//end namespace stim

  

  

  

  

321ff17a   David Mayerich   Optimized the mat...
235
  #endif