]> de.git.xonotic.org Git - xonotic/netradiant.git/blob - plugins/entity/light.cpp
Q2Tools source - didn't import this in initially
[xonotic/netradiant.git] / plugins / entity / light.cpp
1
2 #include "plugin.h"
3 #include "entity.h"
4 #include "light.h"
5
6 void DrawSphere( vec3_t center, float radius, int sides, int nGLState ){
7         int i, j;
8         float dt = (float) ( 2 * Q_PI / (float) sides );
9         float dp = (float) ( Q_PI / (float) sides );
10         float t, p;
11         vec3_t v;
12
13         if ( radius <= 0 ) {
14                 return;
15         }
16
17         g_QglTable.m_pfn_qglBegin( GL_TRIANGLES );
18         for ( i = 0; i <= sides - 1; i++ ) {
19                 for ( j = 0; j <= sides - 2; j++ ) {
20                         t = i * dt;
21                         p = (float) ( ( j * dp ) - ( Q_PI / 2 ) );
22
23                         VectorPolar( v, radius, t, p );
24                         VectorAdd( v, center, v );
25                         g_QglTable.m_pfn_qglVertex3fv( v );
26
27                         VectorPolar( v, radius, t, p + dp );
28                         VectorAdd( v, center, v );
29                         g_QglTable.m_pfn_qglVertex3fv( v );
30
31                         VectorPolar( v, radius, t + dt, p + dp );
32                         VectorAdd( v, center, v );
33                         g_QglTable.m_pfn_qglVertex3fv( v );
34
35                         VectorPolar( v, radius, t, p );
36                         VectorAdd( v, center, v );
37                         g_QglTable.m_pfn_qglVertex3fv( v );
38
39                         VectorPolar( v, radius, t + dt, p + dp );
40                         VectorAdd( v, center, v );
41                         g_QglTable.m_pfn_qglVertex3fv( v );
42
43                         VectorPolar( v, radius, t + dt, p );
44                         VectorAdd( v, center, v );
45                         g_QglTable.m_pfn_qglVertex3fv( v );
46                 }
47         }
48
49         p = (float) ( ( sides - 1 ) * dp - ( Q_PI / 2 ) );
50         for ( i = 0; i <= sides - 1; i++ ) {
51                 t = i * dt;
52
53                 VectorPolar( v, radius, t, p );
54                 VectorAdd( v, center, v );
55                 g_QglTable.m_pfn_qglVertex3fv( v );
56
57                 VectorPolar( v, radius, t + dt, p + dp );
58                 VectorAdd( v, center, v );
59                 g_QglTable.m_pfn_qglVertex3fv( v );
60
61                 VectorPolar( v, radius, t + dt, p );
62                 VectorAdd( v, center, v );
63                 g_QglTable.m_pfn_qglVertex3fv( v );
64         }
65         g_QglTable.m_pfn_qglEnd();
66 }
67
68 #define LIGHT_ATTEN_LINEAR  1
69 #define LIGHT_ATTEN_ANGLE       2
70 #define LIGHT_ATTEN_DISTANCE    4
71
72 #define LIGHT_Q3A_DEFAULT       ( LIGHT_ATTEN_ANGLE | LIGHT_ATTEN_DISTANCE )
73 #define LIGHT_WOLF_DEFAULT  ( LIGHT_ATTEN_LINEAR | LIGHT_ATTEN_DISTANCE )
74
75 float CalculateEnvelopeForLight( entity_t * e, float fFalloffTolerance ){
76         float fEnvelope = 0.f;
77         int iSpawnFlags = atoi( ValueForKey( e, "spawnflags" ) );
78         int iLightFlags = 0;
79         float fFade = 1.f;
80         float fIntensity, fPhotons;
81         float fScale;
82         const char *gameFile = g_FuncTable.m_pfnGetGameFile();
83
84         // These variables are tweakable on the q3map2 console, setting to q3map2
85         // default here as there is no way to find out what the user actually uses
86         // right now. Maybe move them to worldspawn?
87         float fPointScale = 7500.f;
88         float fLinearScale = 1.f / 8000.f;
89         //float fFalloffTolerance = 1.f;  // Need it as parameter
90
91         // Arnout: HACK for per-game radii - really need to move this to a per-game module?
92         if ( !strcmp( gameFile, "wolf.game" ) || !strcmp( gameFile, "et.game" ) ) {
93                 // Spawnflags :
94                 // 1: nonlinear
95                 // 2: angle
96
97                 // set default flags
98                 iLightFlags = LIGHT_WOLF_DEFAULT;
99
100                 // inverse distance squared attenuation?
101                 if ( iSpawnFlags & 1 ) {
102                         iLightFlags &= ~LIGHT_ATTEN_LINEAR;
103                         iLightFlags |= LIGHT_ATTEN_ANGLE;
104                 }
105                 // angle attenuate
106                 if ( iSpawnFlags & 2 ) {
107                         iLightFlags |= LIGHT_ATTEN_ANGLE;
108                 }
109         }
110         else {
111                 // Spawnflags :
112                 // 1: linear
113                 // 2: no angle
114
115                 // set default flags
116                 iLightFlags = LIGHT_Q3A_DEFAULT;
117
118                 // linear attenuation?
119                 if ( iSpawnFlags & 1 ) {
120                         iLightFlags |= LIGHT_ATTEN_LINEAR;
121                         iLightFlags &= ~LIGHT_ATTEN_ANGLE;
122                 }
123                 // no angle attenuate?
124                 if ( iSpawnFlags & 2 ) {
125                         iLightFlags &= ~LIGHT_ATTEN_ANGLE;
126                 }
127         }
128
129         // set fade key (from wolf)
130         if ( iLightFlags & LIGHT_ATTEN_LINEAR ) {
131                 fFade = FloatForKey( e, "fade" );
132                 if ( fFade <= 0.f ) {
133                         fFade = 1.f;
134                 }
135         }
136         // set light intensity
137         fIntensity = FloatForKey( e, "_light" );
138         if ( fIntensity == 0.f ) {
139                 fIntensity = FloatForKey( e, "light" );
140         }
141         if ( fIntensity == 0.f ) {
142                 fIntensity = 300.f;
143         }
144
145         // set light scale (sof2)
146         fScale = FloatForKey( e, "scale" );
147         if ( fScale <= 0.f ) {
148                 fScale = 1.f;
149         }
150         fIntensity *= fScale;
151
152         // amount of photons
153         fPhotons = fIntensity * fPointScale;
154
155         // calculate envelope
156
157         // solve distance for non-distance lights
158         if ( !( iLightFlags & LIGHT_ATTEN_DISTANCE ) ) {
159                 //!\todo (spog) can't access global objects in a module - globals are EVIL - solution: API for querying global settings.
160                 fEnvelope = 131072 /*g_MaxWorldCoord * 2.f*/;
161         }
162         // solve distance for linear lights
163         else if ( iLightFlags & LIGHT_ATTEN_LINEAR ) {
164                 fEnvelope = ( ( fPhotons * fLinearScale ) - fFalloffTolerance ) / fFade;
165         }
166         // solve for inverse square falloff
167         else{
168                 fEnvelope = sqrt( fPhotons / fFalloffTolerance ) /* + fRadius */ ; // Arnout radius is always 0, only for area lights
169
170         }
171         return fEnvelope;
172 }
173
174 float CalculateLightRadius( entity_t * e, bool outer ){
175         float fEnvelope = 0.f;
176         int iSpawnFlags = atoi( ValueForKey( e, "spawnflags" ) );
177         float fIntensity;
178         float fScale;
179         const char *gameFile = g_FuncTable.m_pfnGetGameFile();
180
181         fIntensity = FloatForKey( e, "light" );
182         if ( fIntensity == 0.f ) {
183                 fIntensity = 300.f;
184         }
185
186         // Arnout: HACK for per-game radii - really need to move this to a per-game module
187         if ( !strcmp( gameFile, "sof2.game" ) || !strcmp( gameFile, "jk2.game" ) || !strcmp( gameFile, "ja.game" ) ) {
188                 // Spawnflags :
189                 // 1: linear
190                 // 2: noincidence
191
192                 if ( !outer ) {
193                         if ( iSpawnFlags & 2 ) {
194                                 fIntensity *= .9f;
195                         }
196                         else{
197                                 fIntensity *= .25f;
198                         }
199                 }
200                 // set light scale (sof2)
201                 fScale = FloatForKey( e, "scale" );
202                 if ( fScale <= 0.f ) {
203                         fScale = 1.f;
204                 }
205                 fIntensity *= fScale;
206
207                 fEnvelope = fIntensity;
208         }
209         else {
210                 float fPointScale = 7500.f;
211
212                 if ( outer ) {
213                         fEnvelope = sqrt( fIntensity * fPointScale / 48.f );
214                 }
215                 else{
216                         fEnvelope = sqrt( fIntensity * fPointScale / 255.f );
217                 }
218         }
219
220         return fEnvelope;
221 }
222
223 void Light_OnIntensityChanged( entity_t* e ){
224         e->fLightEnvelope1[0] = CalculateEnvelopeForLight( e, 1.f );
225         e->fLightEnvelope1[1] = CalculateEnvelopeForLight( e, 48.f );
226         e->fLightEnvelope1[2] = CalculateEnvelopeForLight( e, 255.f );
227
228         e->fLightEnvelope2[0] = CalculateLightRadius( e, TRUE );
229         e->fLightEnvelope2[1] = CalculateLightRadius( e, FALSE );
230 }
231
232 void Light_OnKeyValueChanged( entity_t *e, const char *key, const char* value ){
233         if ( strcmp( key,"_color" ) == 0 ) {
234                 if ( sscanf( ValueForKey( e, "_color" ),"%f %f %f",
235                                          &e->color[0], &e->color[1], &e->color[2] ) != 3 ) {
236                         VectorSet( e->color, 1, 1, 1 );
237                 }
238         }
239         else if ( strcmp( key,"spawnflags" ) == 0 ||
240                           strcmp( key,"fade" ) == 0 ||
241                           strcmp( key,"_light" ) == 0 ||
242                           strcmp( key,"light" ) == 0 ||
243                           strcmp( key,"scale" ) == 0 ) {
244                 Light_OnIntensityChanged( e );
245         }
246 }
247
248 bool Entity_IsLight( entity_t *e ){
249         return e->eclass != NULL && e->eclass->nShowFlags & ECLASS_LIGHT; //strncmp(ValueforKey(e, "classname"), "light") == 0
250 }
251
252 static void DrawLightSphere( entity_t * e, int nGLState, int pref ){
253         const char *target = ValueForKey( e, "target" );
254         bool bIsSpotLight = !!target[0];
255         //!\todo Write an API for modules to register preference settings, and make this preference module-specific.
256         // int nPasses = pref == 1 ? 3 : 2;
257
258         g_QglTable.m_pfn_qglPushAttrib( GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT );
259         g_QglTable.m_pfn_qglDepthMask( GL_FALSE );
260         g_QglTable.m_pfn_qglEnable( GL_BLEND );
261         g_QglTable.m_pfn_qglBlendFunc( GL_ONE, GL_ONE );
262
263         // Arnout: TODO: spotlight rendering
264         if ( !( bIsSpotLight ) ) {
265                 switch ( pref )
266                 {
267                 case 1:
268                         g_QglTable.m_pfn_qglColor3f( e->color[0] * .05f,
269                                                                                  e->color[1] * .05f,
270                                                                                  e->color[2] * .05f );
271                         DrawSphere( e->origin, e->fLightEnvelope1[0], 16, nGLState );
272                         DrawSphere( e->origin, e->fLightEnvelope1[1], 16, nGLState );
273                         DrawSphere( e->origin, e->fLightEnvelope1[2], 16, nGLState );
274                         break;
275                 case 2:
276                         g_QglTable.m_pfn_qglColor3f( e->color[0] * .15f * .95f,
277                                                                                  e->color[1] * .15f * .95f,
278                                                                                  e->color[2] * .15f * .95f );
279                         DrawSphere( e->origin, e->fLightEnvelope2[0], 16, nGLState );
280                         DrawSphere( e->origin, e->fLightEnvelope2[1], 16, nGLState );
281                         break;
282
283                 }
284         }
285
286         g_QglTable.m_pfn_qglPopAttrib();
287 }
288
289 float F = 0.70710678f;
290 // North, East, South, West
291 vec3_t normals[8] = { { 0, F, F }, { F, 0, F }, { 0,-F, F }, {-F, 0, F },
292                                           { 0, F,-F }, { F, 0,-F }, { 0,-F,-F }, {-F, 0,-F } };
293
294 unsigned short indices[24] = { 0, 2, 3, 0, 3, 4, 0, 4, 5, 0, 5, 2,
295                                                            1, 2, 5, 1, 5, 4, 1, 4, 3, 1, 3, 2 };
296
297 void DrawLight( entity_t* e, int nGLState, int pref, int nViewType ){
298 //  int i;
299         // top, bottom, tleft, tright, bright, bleft
300         vec3_t points[6];
301         vec3_t vMid, vMin, vMax;
302         VectorAdd( e->origin, e->eclass->mins, vMin );
303         VectorAdd( e->origin, e->eclass->maxs, vMax );
304         vMid[0] = ( vMin[0] + vMax[0] ) * 0.5;
305         vMid[1] = ( vMin[1] + vMax[1] ) * 0.5;
306         vMid[2] = ( vMin[2] + vMax[2] ) * 0.5;
307
308         VectorSet( points[0], vMid[0], vMid[1], vMax[2] );
309         VectorSet( points[1], vMid[0], vMid[1], vMin[2] );
310         VectorSet( points[2], vMin[0], vMax[1], vMid[2] );
311         VectorSet( points[3], vMax[0], vMax[1], vMid[2] );
312         VectorSet( points[4], vMax[0], vMin[1], vMid[2] );
313         VectorSet( points[5], vMin[0], vMin[1], vMid[2] );
314
315         if ( nGLState & DRAW_GL_LIGHTING ) { // && g_PrefsDlg.m_bGLLighting)
316                 g_QglTable.m_pfn_qglBegin( GL_TRIANGLES ); // NOTE: comment to use gl_triangle_fan instead
317                 //g_QglTable.m_pfn_qglBegin(GL_TRIANGLE_FAN);
318                 g_QglTable.m_pfn_qglVertex3fv( points[0] );
319                 g_QglTable.m_pfn_qglVertex3fv( points[2] );
320                 g_QglTable.m_pfn_qglNormal3fv( normals[0] );
321                 g_QglTable.m_pfn_qglVertex3fv( points[3] );
322
323                 g_QglTable.m_pfn_qglVertex3fv( points[0] ); //
324                 g_QglTable.m_pfn_qglVertex3fv( points[3] ); //
325                 g_QglTable.m_pfn_qglNormal3fv( normals[1] );
326                 g_QglTable.m_pfn_qglVertex3fv( points[4] );
327
328                 g_QglTable.m_pfn_qglVertex3fv( points[0] ); //
329                 g_QglTable.m_pfn_qglVertex3fv( points[4] ); //
330                 g_QglTable.m_pfn_qglNormal3fv( normals[2] );
331                 g_QglTable.m_pfn_qglVertex3fv( points[5] );
332
333                 g_QglTable.m_pfn_qglVertex3fv( points[0] ); //
334                 g_QglTable.m_pfn_qglVertex3fv( points[5] ); //
335                 g_QglTable.m_pfn_qglNormal3fv( normals[3] );
336                 g_QglTable.m_pfn_qglVertex3fv( points[2] );
337
338                 //g_QglTable.m_pfn_qglEnd();
339                 //g_QglTable.m_pfn_qglBegin(GL_TRIANGLE_FAN);
340
341                 g_QglTable.m_pfn_qglVertex3fv( points[1] );
342                 g_QglTable.m_pfn_qglVertex3fv( points[2] );
343                 g_QglTable.m_pfn_qglNormal3fv( normals[7] );
344                 g_QglTable.m_pfn_qglVertex3fv( points[5] );
345
346                 g_QglTable.m_pfn_qglVertex3fv( points[1] ); //
347                 g_QglTable.m_pfn_qglVertex3fv( points[5] ); //
348                 g_QglTable.m_pfn_qglNormal3fv( normals[6] );
349                 g_QglTable.m_pfn_qglVertex3fv( points[4] );
350
351                 g_QglTable.m_pfn_qglVertex3fv( points[1] ); //
352                 g_QglTable.m_pfn_qglVertex3fv( points[4] ); //
353                 g_QglTable.m_pfn_qglNormal3fv( normals[5] );
354                 g_QglTable.m_pfn_qglVertex3fv( points[3] );
355
356                 g_QglTable.m_pfn_qglVertex3fv( points[1] ); //
357                 g_QglTable.m_pfn_qglVertex3fv( points[3] ); //
358                 g_QglTable.m_pfn_qglNormal3fv( normals[4] );
359                 g_QglTable.m_pfn_qglVertex3fv( points[2] );
360
361                 g_QglTable.m_pfn_qglEnd();
362         }
363         else if ( nGLState & DRAW_GL_FILL ) {
364                 vec3_t colors[4];
365                 VectorScale( e->color, 0.95, colors[0] );
366                 VectorScale( colors[0], 0.95, colors[1] );
367                 VectorScale( colors[1], 0.95, colors[2] );
368                 VectorScale( colors[2], 0.95, colors[3] );
369                 g_QglTable.m_pfn_qglBegin( GL_TRIANGLES ); // NOTE: comment to use gl_triangle_fan instead
370                 //g_QglTable.m_pfn_qglBegin(GL_TRIANGLE_FAN);
371                 g_QglTable.m_pfn_qglColor3fv( colors[0] );
372                 g_QglTable.m_pfn_qglVertex3fv( points[0] );
373                 g_QglTable.m_pfn_qglVertex3fv( points[2] );
374                 g_QglTable.m_pfn_qglVertex3fv( points[3] );
375
376                 g_QglTable.m_pfn_qglColor3fv( colors[1] );
377                 g_QglTable.m_pfn_qglVertex3fv( points[0] ); //
378                 g_QglTable.m_pfn_qglVertex3fv( points[3] ); //
379                 g_QglTable.m_pfn_qglVertex3fv( points[4] );
380
381                 g_QglTable.m_pfn_qglColor3fv( colors[2] );
382                 g_QglTable.m_pfn_qglVertex3fv( points[0] ); //
383                 g_QglTable.m_pfn_qglVertex3fv( points[4] ); //
384                 g_QglTable.m_pfn_qglVertex3fv( points[5] );
385
386                 g_QglTable.m_pfn_qglColor3fv( colors[3] );
387                 g_QglTable.m_pfn_qglVertex3fv( points[0] ); //
388                 g_QglTable.m_pfn_qglVertex3fv( points[5] ); //
389                 g_QglTable.m_pfn_qglVertex3fv( points[2] );
390
391                 //g_QglTable.m_pfn_qglEnd();
392                 //g_QglTable.m_pfn_qglBegin(GL_TRIANGLE_FAN);
393
394                 g_QglTable.m_pfn_qglColor3fv( colors[0] );
395                 g_QglTable.m_pfn_qglVertex3fv( points[1] );
396                 g_QglTable.m_pfn_qglVertex3fv( points[2] );
397                 g_QglTable.m_pfn_qglVertex3fv( points[5] );
398
399                 g_QglTable.m_pfn_qglColor3fv( colors[1] );
400                 g_QglTable.m_pfn_qglVertex3fv( points[1] ); //
401                 g_QglTable.m_pfn_qglVertex3fv( points[5] ); //
402                 g_QglTable.m_pfn_qglVertex3fv( points[4] );
403
404                 g_QglTable.m_pfn_qglColor3fv( colors[2] );
405                 g_QglTable.m_pfn_qglVertex3fv( points[1] ); //
406                 g_QglTable.m_pfn_qglVertex3fv( points[4] ); //
407                 g_QglTable.m_pfn_qglVertex3fv( points[3] );
408
409                 g_QglTable.m_pfn_qglColor3fv( colors[3] );
410                 g_QglTable.m_pfn_qglVertex3fv( points[1] ); //
411                 g_QglTable.m_pfn_qglVertex3fv( points[3] ); //
412                 g_QglTable.m_pfn_qglVertex3fv( points[2] );
413
414                 g_QglTable.m_pfn_qglEnd();
415         }
416         else
417         {
418                 g_QglTable.m_pfn_qglVertexPointer( 3, GL_FLOAT, 0, points );
419                 g_QglTable.m_pfn_qglDrawElements( GL_TRIANGLES, 24, GL_UNSIGNED_SHORT, indices );
420         }
421
422
423         // NOTE: prolly not relevant until some time..
424         // check for DOOM lights
425         if ( strlen( ValueForKey( e, "light_right" ) ) > 0 ) {
426                 vec3_t vRight, vUp, vTarget, vTemp;
427                 GetVectorForKey( e, "light_right", vRight );
428                 GetVectorForKey( e, "light_up", vUp );
429                 GetVectorForKey( e, "light_target", vTarget );
430
431                 g_QglTable.m_pfn_qglColor3f( 0, 1, 0 );
432                 g_QglTable.m_pfn_qglBegin( GL_LINE_LOOP );
433                 VectorAdd( vTarget, e->origin, vTemp );
434                 VectorAdd( vTemp, vRight, vTemp );
435                 VectorAdd( vTemp, vUp, vTemp );
436                 g_QglTable.m_pfn_qglVertex3fv( e->origin );
437                 g_QglTable.m_pfn_qglVertex3fv( vTemp );
438                 VectorAdd( vTarget, e->origin, vTemp );
439                 VectorAdd( vTemp, vUp, vTemp );
440                 VectorSubtract( vTemp, vRight, vTemp );
441                 g_QglTable.m_pfn_qglVertex3fv( e->origin );
442                 g_QglTable.m_pfn_qglVertex3fv( vTemp );
443                 VectorAdd( vTarget, e->origin, vTemp );
444                 VectorAdd( vTemp, vRight, vTemp );
445                 VectorSubtract( vTemp, vUp, vTemp );
446                 g_QglTable.m_pfn_qglVertex3fv( e->origin );
447                 g_QglTable.m_pfn_qglVertex3fv( vTemp );
448                 VectorAdd( vTarget, e->origin, vTemp );
449                 VectorSubtract( vTemp, vUp, vTemp );
450                 VectorSubtract( vTemp, vRight, vTemp );
451                 g_QglTable.m_pfn_qglVertex3fv( e->origin );
452                 g_QglTable.m_pfn_qglVertex3fv( vTemp );
453                 g_QglTable.m_pfn_qglEnd();
454
455         }
456
457         if ( nGLState & DRAW_GL_FILL ) {
458                 DrawLightSphere( e, nGLState, pref );
459         }
460         else
461         {
462                 // Arnout: FIXME: clean this up a bit
463                 // now draw lighting radius stuff...
464                 if ( pref ) {
465                         bool bDrawSpotlightArc = false;
466                         int nPasses = pref == 1 ? 3 : 2;
467
468                         const char *target = ValueForKey( e, "target" );
469                         bool bIsSpotLight = !!target[0];
470
471                         /*!\todo Spotlight..
472                            if (bIsSpotLight)
473                            {
474                            // find the origin of the target...
475                            entity_t *e = FindEntity("targetname", target);
476
477                            if (e)
478                             bDrawSpotlightArc = true;
479                            }
480                          */
481
482                         g_QglTable.m_pfn_qglPushAttrib( GL_LINE_BIT );
483                         g_QglTable.m_pfn_qglLineStipple( 8, 0xAAAA );
484                         g_QglTable.m_pfn_qglEnable( GL_LINE_STIPPLE );
485
486                         float* envelope = ( pref == 1 ) ? e->fLightEnvelope1 : e->fLightEnvelope2;
487                         for ( int iPass = 0; iPass < nPasses; iPass++ )
488                         {
489                                 float fRadius = envelope[iPass];
490
491                                 g_QglTable.m_pfn_qglBegin( GL_LINE_LOOP );
492
493                                 if ( bIsSpotLight ) {
494                                         if ( bDrawSpotlightArc ) {
495                                                 // I give up on this, it's beyond me
496                                         }
497                                 }
498                                 else
499                                 {
500                                         if ( fRadius > 0 ) {
501                                                 int i;
502                                                 float ds, dc;
503
504                                                 for ( i = 0; i <= 24; i++ )
505                                                 {
506                                                         ds = sin( ( i * 2 * Q_PI ) / 24 );
507                                                         dc = cos( ( i * 2 * Q_PI ) / 24 );
508
509                                                         switch ( nViewType )
510                                                         {
511                                                         case 2:
512                                                                 g_QglTable.m_pfn_qglVertex3f( e->origin[0] + fRadius * dc,
513                                                                                                                           e->origin[1] + fRadius * ds,
514                                                                                                                           e->origin[2] );
515                                                                 break;
516                                                         case 1:
517                                                                 g_QglTable.m_pfn_qglVertex3f( e->origin[0] + fRadius * dc,
518                                                                                                                           e->origin[1],
519                                                                                                                           e->origin[2] + fRadius * ds );
520                                                                 break;
521                                                         case 0:
522                                                                 g_QglTable.m_pfn_qglVertex3f( e->origin[0],
523                                                                                                                           e->origin[1] + fRadius * dc,
524                                                                                                                           e->origin[2] + fRadius * ds );
525                                                                 break;
526                                                         }
527                                                 }
528                                         }
529                                 }
530                                 g_QglTable.m_pfn_qglEnd();
531                         }
532                         g_QglTable.m_pfn_qglPopAttrib();
533                 }
534         }
535 }