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 #include "opengl-effects.h"
00036
00037 #include "perf/perf.h"
00038 #include "wave-glut/texture.h"
00039
00040
00041 namespace glut {
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051 static float
00052 randomX
00053 (
00054 IN float x
00055 )
00056 {
00057 return (x * rand()) / RAND_MAX;
00058 }
00059
00060
00061
00062 static void
00063 jitter
00064 (
00065 IO point3d_t& p,
00066 IN float dx
00067 )
00068 throw()
00069 {
00070 p.x += randomX(dx) - 0.5 * dx;
00071 p.y += randomX(dx) - 0.5 * dx;
00072 p.z += randomX(dx) - 0.5 * dx;
00073 }
00074
00075
00076
00077 struct ring_t {
00078 ring_t(void) throw() {
00079 gamma = 1.01 + randomX(0.06);
00080
00081 axis.x = -1.0 + randomX(2.0);
00082 axis.y = -1.0 + randomX(2.0);
00083 axis.z = -1.0 + randomX(2.0);
00084 normalize(axis);
00085
00086 phi = randomX(2.0 * M_PI);
00087 dPhi = 0.2 * (5 + randomX(10));
00088 }
00089
00090 void tick(void) throw() {
00091 phi += dPhi;
00092 }
00093
00094
00095 float gamma;
00096 point3d_t axis;
00097 float phi;
00098 float dPhi;
00099 };
00100
00101
00102
00103 static void
00104 drawLightningRing
00105 (
00106 IN float radius,
00107 IN const point3d_t& axis,
00108 IN float phi,
00109 IN const glut_color_t& color
00110 )
00111 throw()
00112 {
00113 ASSERT(radius > 0, "bad radius: %f", radius);
00114 int nPoints = 32;
00115 ASSERT(nPoints > 1, "need at least 2!");
00116
00117
00118 glMatrixMode(GL_MODELVIEW);
00119 glPushMatrix();
00120 glRotatef(phi, axis.x, axis.y, axis.z);
00121
00122 float theta = 0;
00123 float dTheta = 2.0 * M_PI / (nPoints - 1);
00124
00125 const float dJitter = 0.3;
00126
00127 glDisable(GL_LIGHTING);
00128 glColor4fv(&color.red);
00129 glBegin(GL_LINE_LOOP);
00130 for (int i = 0; i < nPoints; ++i) {
00131 float mu = theta + randomX(dJitter) - 0.5 * dJitter;
00132 float nu = randomX(dJitter) - 0.5 * dJitter;
00133 point3d_t p(cos(mu) * cos(nu), sin(nu), sin(mu) * cos(nu));
00134 p *= radius;
00135 glVertex3fv(&p.x);
00136 theta += dTheta;
00137 }
00138 glEnd();
00139 glEnable(GL_LIGHTING);
00140
00141 glPopMatrix();
00142 }
00143
00144
00145
00146 class Sphere : public Renderable {
00147 public:
00148
00149 ~Sphere(void) throw();
00150
00151
00152 void initialize(IN const sphere_init_t& si);
00153
00154
00155 void render(IN const render_context_t& rc,
00156 IN RenderQueue * rq);
00157 rect3d_t getBoundingBox(void) const throw();
00158
00159 private:
00160
00161
00162
00163 float m_radius;
00164 float m_phi;
00165 float m_dPhi;
00166 int m_nRings;
00167 ring_t m_rings[sphere_init_t::eMaxRings];
00168 GLuint m_textureId;
00169 };
00170
00171
00172
00173 Sphere::~Sphere(void)
00174 throw()
00175 {
00176 if (m_textureId) {
00177 glDeleteTextures(1, &m_textureId);
00178 }
00179 }
00180
00181
00182
00183 void
00184 Sphere::initialize
00185 (
00186 IN const sphere_init_t& si
00187 )
00188 {
00189 ASSERT(si.isValid(), "invalid sphere initialization data");
00190
00191
00192 m_radius = si.radius;
00193 m_nRings = si.nRings;
00194
00195
00196 m_phi = randomX(2.0 * M_PI);
00197 m_dPhi = 5 * (5 + randomX(10));
00198 if (randomX(10) < 5) {
00199 m_dPhi = -m_dPhi;
00200 }
00201
00202
00203 media::image_t img;
00204
00205 createCircularDensityMap(64, si.color, img);
00206
00207
00208 m_textureId = createTextureFromImage(img);
00209 DPRINTF("Texture ID: %d", m_textureId);
00210 }
00211
00212
00213
00214 void
00215 Sphere::render
00216 (
00217 IN const render_context_t& rc,
00218 IN RenderQueue * rq
00219 )
00220 {
00221 perf::Timer timer("Sphere::render");
00222 ASSERT(rq, "null");
00223
00224 m_phi += m_dPhi;
00225
00226
00227 glMatrixMode(GL_MODELVIEW);
00228 glPushMatrix();
00229 glRotatef(m_phi, 0, 1, 0);
00230 glutSolidSphere(m_radius, 12, 12);
00231 glPopMatrix();
00232
00233
00234 for (int i = 0; i < m_nRings; ++i) {
00235 ring_t& r = m_rings[i];
00236 r.tick();
00237 drawLightningRing(r.gamma * m_radius,
00238 r.axis, r.phi, glut_color_t(1, 1, 1, 1));
00239 }
00240
00241
00242 point3d_t to = rc.placement.position - rc.viewer.getPosition();
00243 float z2 = dotProduct(to, to);
00244 if (z2 < 1.0e-4)
00245 return;
00246 float z = sqrt(z2);
00247 to = (1.0 / z) * to;
00248
00249
00250 point3d_t bogusUp = rc.viewer.getUp();
00251 point3d_t right = crossProduct(to, bogusUp);
00252 normalize(right);
00253
00254
00255 point3d_t up = -crossProduct(to, right);
00256 normalize(up);
00257
00258
00259 glut::poly_request_t * pr = rq->grabRequestSlot();
00260 if (!pr) {
00261 DPRINTF("No available request slots?");
00262 return;
00263 }
00264
00265 matrix4_t T;
00266 glut::getModelViewMatrix(T);
00267
00268
00269
00270
00271
00272
00273
00274 float beta = 1.17;
00275 float gamma = 1.1;
00276 float alpha = beta * (z - gamma * m_radius) / z;
00277
00278
00279
00280 float scale = alpha * m_radius;
00281 point3d_t mid = -gamma * m_radius * to;
00282
00283
00284 pr->nVertices = 4;
00285 pr->textureId = m_textureId;
00286 pr->normal = -to;
00287
00288 pr->vertex[0] = T * (mid + scale * (-up + right));
00289 pr->u[0] = 0;
00290 pr->v[0] = 0;
00291
00292 pr->vertex[1] = T * (mid + scale * ( up + right));
00293 pr->u[1] = 0;
00294 pr->v[1] = 1;
00295
00296 pr->vertex[2] = T * (mid + scale * ( up - right));
00297 pr->u[2] = 1;
00298 pr->v[2] = 1;
00299
00300 pr->vertex[3] = T * (mid + scale * (-up - right));
00301 pr->u[3] = 1;
00302 pr->v[3] = 0;
00303 }
00304
00305
00306
00307 rect3d_t
00308 Sphere::getBoundingBox
00309 (
00310 void
00311 )
00312 const
00313 throw()
00314 {
00315 rect3d_t r;
00316 r.clear();
00317 r.inflate(m_radius);
00318 return r;
00319 }
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329 smart_ptr<Renderable>
00330 createCoolSphere
00331 (
00332 IN const sphere_init_t& si
00333 )
00334 {
00335 ASSERT(si.isValid(), "invalid sphere initializer");
00336
00337 smart_ptr<Sphere> local = new Sphere;
00338 ASSERT(local, "out of memory");
00339
00340 local->initialize(si);
00341
00342 return local;
00343 }
00344
00345
00346
00347 };
00348