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
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
|
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:
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();
}
}; //end gl_spharmonics
}; //end namespace stim
|