Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 #include "opengl-effects.h"
00039
00040 #include "perf/perf.h"
00041 #include "wave-glut/texture.h"
00042
00043
00044 #include <GL/glut.h>
00045 #include <stdio.h>
00046 #include <math.h>
00047
00048
00049 namespace glut {
00050
00051
00052
00053
00054 struct sphere_vertex_t {
00055
00056 float x;
00057 float y;
00058 float z;
00059 float u;
00060 float v;
00061 };
00062
00063
00064
00065 static const int s_degreesPerSlice = 9;
00066
00067 static const float s_radiansPerDegree = M_PI / 180.0;
00068
00069
00070
00071
00072 static const int s_vertexCount =
00073 4 * (90 / s_degreesPerSlice) * (360 / s_degreesPerSlice);
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083 static const sphere_vertex_t *
00084 getSphereVertices
00085 (
00086 void
00087 )
00088 {
00089
00090
00091 static sphere_vertex_t s_vertices[s_vertexCount];
00092
00093
00094
00095
00096 static bool s_haveVertices = false;
00097 if (s_haveVertices) {
00098 return s_vertices;
00099 }
00100
00101 perf::Timer timer("construct-sphere-map");
00102
00103
00104
00105
00106 sphere_vertex_t * psv = s_vertices;
00107 const float inv360 = 1.0 / 360.0;
00108 const float inv180 = 1.0 / 180.0;
00109
00110
00111 float sinBplus = 0.0;
00112 float cosBplus = 1.0;
00113
00114
00115 for (int b = 0; b < 90; b += s_degreesPerSlice) {
00116 float sinB = sinBplus;
00117 float cosB = cosBplus;
00118
00119
00120 sinBplus = sin((b + s_degreesPerSlice) * s_radiansPerDegree);
00121 cosBplus = cos((b + s_degreesPerSlice) * s_radiansPerDegree);
00122
00123 float sinAplus = 0.0;
00124 float cosAplus = 1.0;
00125
00126
00127 for (int a = 0; a < 360; a += s_degreesPerSlice) {
00128
00129 float sinA = sinAplus;
00130 float cosA = cosAplus;
00131
00132 sinAplus = sin((a + s_degreesPerSlice) * s_radiansPerDegree);
00133 cosAplus = cos((a + s_degreesPerSlice) * s_radiansPerDegree);
00134
00135
00136
00137 psv->x = sinA * sinB;
00138 psv->y = cosA * sinB;
00139 psv->z = cosB;
00140 psv->u = a * inv360;
00141 psv->v = b * inv180;
00142
00143 ++psv;
00144
00145 psv->x = sinA * sinBplus;
00146 psv->y = cosA * sinBplus;
00147 psv->z = cosBplus;
00148 psv->u = a * inv360;
00149 psv->v = (b + s_degreesPerSlice) * inv180;
00150 ++psv;
00151
00152 psv->x = sinAplus * sinB;
00153 psv->y = cosAplus * sinB;
00154 psv->z = cosB;
00155 psv->u = (a + s_degreesPerSlice) * inv360;
00156 psv->v = b * inv180;
00157 ++psv;
00158
00159 psv->x = sinAplus * sinBplus;
00160 psv->y = cosAplus * sinBplus;
00161 psv->z = cosBplus;
00162 psv->u = (a + s_degreesPerSlice) * inv360;
00163 psv->v = (b + s_degreesPerSlice) * inv180;
00164 ++psv;
00165 }
00166 }
00167
00168
00169 ASSERT(psv - s_vertices == s_vertexCount,
00170 "Incorrect vertex count?");
00171
00172
00173 s_haveVertices = true;
00174 return s_vertices;
00175 }
00176
00177
00178
00179 class TexSphere : public Renderable {
00180 public:
00181
00182 ~TexSphere(void) throw() { }
00183
00184
00185 void initialize(IN const tex_sphere_t& ts);
00186
00187
00188 void render(IN const render_context_t& rc,
00189 IN RenderQueue * rq);
00190 rect3d_t getBoundingBox(void) const throw();
00191
00192 private:
00193
00194
00195
00196 float m_radius;
00197 int m_textureId;
00198 };
00199
00200
00201 void
00202 TexSphere::initialize
00203 (
00204 IN const tex_sphere_t& ts
00205 )
00206 {
00207 ASSERT(ts.radius > 0, "bad sphere radius: %f", ts.radius);
00208 ASSERT(ts.textureId > -1, "bad texture id: %d", ts.textureId);
00209
00210 m_radius = ts.radius;
00211 m_textureId = ts.textureId;
00212 }
00213
00214
00215
00216 void
00217 TexSphere::render
00218 (
00219 IN const render_context_t& rc,
00220 IN RenderQueue * rq
00221 )
00222 {
00223 perf::Timer timer("TexSphere::render");
00224 ASSERT(m_radius > 0, "bad radius");
00225
00226
00227 glEnable(GL_TEXTURE_2D);
00228 glBindTexture(GL_TEXTURE_2D, m_textureId);
00229
00230
00231
00232
00233 glMatrixMode(GL_MODELVIEW);
00234 glPushMatrix();
00235
00236 glScalef(m_radius, m_radius, m_radius);
00237
00238 const sphere_vertex_t * v0 = getSphereVertices();
00239
00240
00241 glBegin(GL_TRIANGLE_STRIP);
00242 const sphere_vertex_t * psv = v0;
00243 for (int b = 0; b < s_vertexCount; ++b, ++psv) {
00244 glTexCoord2f(psv->u, 1.0 - psv->v);
00245 glVertex3f(psv->x, psv->z, psv->y);
00246 }
00247 glEnd();
00248
00249
00250 glBegin(GL_TRIANGLE_STRIP);
00251 psv = v0;
00252 for (int b = 0; b < s_vertexCount; ++b, ++psv) {
00253 glTexCoord2f(-psv->u, psv->v);
00254 glVertex3f(-psv->x, -psv->z, psv->y);
00255 }
00256 glEnd();
00257
00258
00259 glPopMatrix();
00260 glDisable(GL_TEXTURE_2D);
00261 }
00262
00263
00264
00265 rect3d_t
00266 TexSphere::getBoundingBox
00267 (
00268 void
00269 )
00270 const
00271 throw()
00272 {
00273 rect3d_t r;
00274 r.clear();
00275 r.inflate(m_radius);
00276 return r;
00277 }
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287 smart_ptr<Renderable>
00288 createMappedSphere
00289 (
00290 IN const tex_sphere_t& ts
00291 )
00292 {
00293 smart_ptr<TexSphere> local = new TexSphere;
00294 ASSERT(local, "out of memory");
00295
00296 local->initialize(ts);
00297
00298 return local;
00299 }
00300
00301
00302
00303 };
00304