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:
|
9bfae4d0
Pavel Govyadinov
extended gl_sphar...
|
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));
}
|