]> de.git.xonotic.org Git - xonotic/netradiant.git/blobdiff - plugins/entity/light.cpp
more eol-style
[xonotic/netradiant.git] / plugins / entity / light.cpp
index 1650c075072e76d5ea23ae3b0a1340e39aa2f009..477fc72d44d61c5fcd4e1c48126304b53b194495 100644 (file)
-\r
-#include "plugin.h"\r
-#include "entity.h"\r
-#include "light.h"\r
-\r
-void DrawSphere(vec3_t center, float radius, int sides, int nGLState)\r
-{\r
-  int i, j;\r
-  float dt = (float) (2 * Q_PI / (float) sides);\r
-  float dp = (float) (Q_PI / (float) sides);\r
-  float t, p;\r
-  vec3_t v;\r
-\r
-  if (radius <= 0)\r
-    return;\r
-\r
-  g_QglTable.m_pfn_qglBegin(GL_TRIANGLES);\r
-  for (i = 0; i <= sides - 1; i++) {\r
-    for (j = 0; j <= sides - 2; j++) {\r
-      t = i * dt;\r
-      p = (float) ((j * dp) - (Q_PI / 2));\r
-\r
-      VectorPolar(v, radius, t, p);\r
-      VectorAdd(v, center, v);\r
-      g_QglTable.m_pfn_qglVertex3fv(v);\r
-\r
-      VectorPolar(v, radius, t, p + dp);\r
-      VectorAdd(v, center, v);\r
-      g_QglTable.m_pfn_qglVertex3fv(v);\r
-\r
-      VectorPolar(v, radius, t + dt, p + dp);\r
-      VectorAdd(v, center, v);\r
-      g_QglTable.m_pfn_qglVertex3fv(v);\r
-\r
-      VectorPolar(v, radius, t, p);\r
-      VectorAdd(v, center, v);\r
-      g_QglTable.m_pfn_qglVertex3fv(v);\r
-\r
-      VectorPolar(v, radius, t + dt, p + dp);\r
-      VectorAdd(v, center, v);\r
-      g_QglTable.m_pfn_qglVertex3fv(v);\r
-\r
-      VectorPolar(v, radius, t + dt, p);\r
-      VectorAdd(v, center, v);\r
-      g_QglTable.m_pfn_qglVertex3fv(v);\r
-    }\r
-  }\r
-\r
-  p = (float) ((sides - 1) * dp - (Q_PI / 2));\r
-  for (i = 0; i <= sides - 1; i++) {\r
-    t = i * dt;\r
-\r
-    VectorPolar(v, radius, t, p);\r
-    VectorAdd(v, center, v);\r
-    g_QglTable.m_pfn_qglVertex3fv(v);\r
-\r
-    VectorPolar(v, radius, t + dt, p + dp);\r
-    VectorAdd(v, center, v);\r
-    g_QglTable.m_pfn_qglVertex3fv(v);\r
-\r
-    VectorPolar(v, radius, t + dt, p);\r
-    VectorAdd(v, center, v);\r
-    g_QglTable.m_pfn_qglVertex3fv(v);\r
-  }\r
-  g_QglTable.m_pfn_qglEnd();\r
-}\r
-\r
-#define LIGHT_ATTEN_LINEAR     1\r
-#define LIGHT_ATTEN_ANGLE              2\r
-#define LIGHT_ATTEN_DISTANCE   4\r
-\r
-#define LIGHT_Q3A_DEFAULT              (LIGHT_ATTEN_ANGLE | LIGHT_ATTEN_DISTANCE)\r
-#define LIGHT_WOLF_DEFAULT     (LIGHT_ATTEN_LINEAR | LIGHT_ATTEN_DISTANCE)\r
-\r
-float CalculateEnvelopeForLight(entity_t * e, float fFalloffTolerance)\r
-{\r
-  float fEnvelope = 0.f;\r
-  int iSpawnFlags = atoi(ValueForKey(e, "spawnflags"));\r
-  int iLightFlags = 0;\r
-  float fFade = 1.f;\r
-  float fIntensity, fPhotons;\r
-  float fScale;\r
-  const char *gameFile = g_FuncTable.m_pfnGetGameFile();\r
-\r
-  // These variables are tweakable on the q3map2 console, setting to q3map2\r
-  // default here as there is no way to find out what the user actually uses\r
-  // right now. Maybe move them to worldspawn?\r
-  float fPointScale = 7500.f;\r
-  float fLinearScale = 1.f / 8000.f;\r
-  //float fFalloffTolerance = 1.f;  // Need it as parameter\r
-\r
-  // Arnout: HACK for per-game radii - really need to move this to a per-game module?\r
-  if( !strcmp( gameFile, "wolf.game" ) || !strcmp( gameFile, "et.game" ) ) {\r
-    // Spawnflags :\r
-    // 1: nonlinear\r
-    // 2: angle\r
-\r
-    // set default flags\r
-    iLightFlags = LIGHT_WOLF_DEFAULT;\r
-\r
-    // inverse distance squared attenuation?\r
-    if (iSpawnFlags & 1) {\r
-      iLightFlags &= ~LIGHT_ATTEN_LINEAR;\r
-      iLightFlags |= LIGHT_ATTEN_ANGLE;\r
-    }\r
-    // angle attenuate\r
-    if (iSpawnFlags & 2)\r
-      iLightFlags |= LIGHT_ATTEN_ANGLE;\r
-  } else {\r
-    // Spawnflags :\r
-    // 1: linear\r
-    // 2: no angle\r
-\r
-    // set default flags\r
-    iLightFlags = LIGHT_Q3A_DEFAULT;\r
-\r
-    // linear attenuation?\r
-    if (iSpawnFlags & 1) {\r
-      iLightFlags |= LIGHT_ATTEN_LINEAR;\r
-      iLightFlags &= ~LIGHT_ATTEN_ANGLE;\r
-    }\r
-    // no angle attenuate?\r
-    if (iSpawnFlags & 2)\r
-      iLightFlags &= ~LIGHT_ATTEN_ANGLE;\r
-  }\r
-\r
-  // set fade key (from wolf)\r
-  if (iLightFlags & LIGHT_ATTEN_LINEAR) {\r
-    fFade = FloatForKey(e, "fade");\r
-    if (fFade <= 0.f)\r
-      fFade = 1.f;\r
-  }\r
-  // set light intensity\r
-  fIntensity = FloatForKey(e, "_light");\r
-  if (fIntensity == 0.f)\r
-    fIntensity = FloatForKey(e, "light");\r
-  if (fIntensity == 0.f)\r
-    fIntensity = 300.f;\r
-\r
-  // set light scale (sof2)\r
-  fScale = FloatForKey(e, "scale");\r
-  if (fScale <= 0.f)\r
-    fScale = 1.f;\r
-  fIntensity *= fScale;\r
-\r
-  // amount of photons\r
-  fPhotons = fIntensity * fPointScale;\r
-\r
-  // calculate envelope\r
-\r
-  // solve distance for non-distance lights\r
-  if (!(iLightFlags & LIGHT_ATTEN_DISTANCE))\r
-    //!\todo (spog) can't access global objects in a module - globals are EVIL - solution: API for querying global settings.\r
-    fEnvelope = 131072/*g_MaxWorldCoord * 2.f*/;\r
-  // solve distance for linear lights\r
-  else if (iLightFlags & LIGHT_ATTEN_LINEAR)\r
-    fEnvelope = ((fPhotons * fLinearScale) - fFalloffTolerance) / fFade;\r
-  // solve for inverse square falloff\r
-  else\r
-    fEnvelope = sqrt(fPhotons / fFalloffTolerance) /* + fRadius */ ;  // Arnout radius is always 0, only for area lights\r
-\r
-  return fEnvelope;\r
-}\r
-\r
-float CalculateLightRadius(entity_t * e, bool outer)\r
-{\r
-  float fEnvelope = 0.f;\r
-  int iSpawnFlags = atoi(ValueForKey(e, "spawnflags"));\r
-  float fIntensity;\r
-  float fScale;\r
-  const char *gameFile = g_FuncTable.m_pfnGetGameFile();\r
-\r
-  fIntensity = FloatForKey(e, "light");\r
-  if (fIntensity == 0.f)\r
-    fIntensity = 300.f;\r
-\r
-  // Arnout: HACK for per-game radii - really need to move this to a per-game module\r
-  if( !strcmp( gameFile, "sof2.game" ) || !strcmp( gameFile, "jk2.game" ) || !strcmp( gameFile, "ja.game" )) {\r
-    // Spawnflags :\r
-    // 1: linear\r
-    // 2: noincidence\r
-\r
-    if (!outer) {\r
-      if (iSpawnFlags & 2)\r
-        fIntensity *= .9;\r
-      else\r
-        fIntensity *= .25f;\r
-    }\r
-    // set light scale (sof2)\r
-    fScale = FloatForKey(e, "scale");\r
-    if (fScale <= 0.f)\r
-      fScale = 1.f;\r
-    fIntensity *= fScale;\r
-\r
-    fEnvelope = fIntensity;\r
-  } else {\r
-    float fPointScale = 7500.f;\r
-\r
-    if (outer)\r
-      fEnvelope = sqrt(fIntensity * fPointScale / 48.f);\r
-    else\r
-      fEnvelope = sqrt(fIntensity * fPointScale / 255.f);\r
-  }\r
-\r
-  return fEnvelope;\r
-}\r
-\r
-void Light_OnIntensityChanged(entity_t* e)\r
-{\r
-  e->fLightEnvelope1[0] = CalculateEnvelopeForLight(e, 1.f);\r
-  e->fLightEnvelope1[1] = CalculateEnvelopeForLight(e, 48.f);\r
-  e->fLightEnvelope1[2] = CalculateEnvelopeForLight(e, 255.f);\r
-\r
-  e->fLightEnvelope2[0] = CalculateLightRadius(e, TRUE);\r
-  e->fLightEnvelope2[1] = CalculateLightRadius(e, FALSE);\r
-}\r
-\r
-void Light_OnKeyValueChanged(entity_t *e, const char *key, const char* value)\r
-{\r
-  if(strcmp(key,"_color") == 0)\r
-  {\r
-    if (sscanf(ValueForKey(e, "_color"),"%f %f %f",\r
-      &e->color[0], &e->color[1], &e->color[2]) != 3)\r
-      VectorSet(e->color, 1, 1, 1);\r
-  }\r
-  else if(strcmp(key,"spawnflags") == 0 ||\r
-          strcmp(key,"fade") == 0 ||\r
-          strcmp(key,"_light") == 0 ||\r
-          strcmp(key,"light") == 0 ||\r
-          strcmp(key,"scale") == 0)\r
-  {\r
-    Light_OnIntensityChanged(e);\r
-  }\r
-}\r
-\r
-bool Entity_IsLight(entity_t *e)\r
-{\r
-  return e->eclass != NULL && e->eclass->nShowFlags & ECLASS_LIGHT;//strncmp(ValueforKey(e, "classname"), "light") == 0\r
-}\r
-\r
-static void DrawLightSphere(entity_t * e, int nGLState, int pref)\r
-{\r
-  const char *target = ValueForKey(e, "target");\r
-  bool bIsSpotLight = !!target[0];\r
-  //!\todo Write an API for modules to register preference settings, and make this preference module-specific.\r
-  int nPasses = pref == 1 ? 3 : 2;\r
-\r
-  g_QglTable.m_pfn_qglPushAttrib(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);\r
-  g_QglTable.m_pfn_qglDepthMask(GL_FALSE);\r
-  g_QglTable.m_pfn_qglEnable(GL_BLEND);\r
-  g_QglTable.m_pfn_qglBlendFunc(GL_ONE, GL_ONE);\r
-\r
-  // Arnout: TODO: spotlight rendering\r
-  if (!(bIsSpotLight))\r
-  {\r
-    switch(pref)\r
-    {\r
-    case 1:\r
-      g_QglTable.m_pfn_qglColor3f(e->color[0] * .05f,\r
-        e->color[1] * .05f,\r
-        e->color[2] * .05f);\r
-      DrawSphere(e->origin, e->fLightEnvelope1[0], 16, nGLState);\r
-      DrawSphere(e->origin, e->fLightEnvelope1[1], 16, nGLState);\r
-      DrawSphere(e->origin, e->fLightEnvelope1[2], 16, nGLState);\r
-      break;\r
-    case 2:\r
-      g_QglTable.m_pfn_qglColor3f(e->color[0] * .15f * .95f,\r
-        e->color[1] * .15f * .95f,\r
-        e->color[2] * .15f * .95f);\r
-      DrawSphere(e->origin, e->fLightEnvelope2[0], 16, nGLState);\r
-      DrawSphere(e->origin, e->fLightEnvelope2[1], 16, nGLState);\r
-      break;\r
-\r
-    }\r
-  }\r
-\r
-  g_QglTable.m_pfn_qglPopAttrib();\r
-}\r
-\r
-float F = 0.70710678f;\r
-// North, East, South, West\r
-vec3_t normals[8] = { { 0, F, F }, { F, 0, F }, { 0,-F, F }, {-F, 0, F },\r
-                                                                                       { 0, F,-F }, { F, 0,-F }, { 0,-F,-F }, {-F, 0,-F } };\r
-\r
-unsigned short indices[24] = { 0, 2, 3, 0, 3, 4, 0, 4, 5, 0, 5, 2,\r
-                               1, 2, 5, 1, 5, 4, 1, 4, 3, 1, 3, 2 };\r
-\r
-void DrawLight(entity_t* e, int nGLState, int pref, int nViewType)\r
-{\r
-  int i;\r
-  // top, bottom, tleft, tright, bright, bleft\r
-  vec3_t points[6];\r
-  vec3_t vMid, vMin, vMax;\r
-  VectorAdd(e->origin, e->eclass->mins, vMin);\r
-  VectorAdd(e->origin, e->eclass->maxs, vMax);\r
-  vMid[0] = (vMin[0] + vMax[0]) * 0.5;\r
-  vMid[1] = (vMin[1] + vMax[1]) * 0.5;\r
-  vMid[2] = (vMin[2] + vMax[2]) * 0.5;\r
-\r
-  VectorSet(points[0], vMid[0], vMid[1], vMax[2]);\r
-  VectorSet(points[1], vMid[0], vMid[1], vMin[2]);\r
-  VectorSet(points[2], vMin[0], vMax[1], vMid[2]);\r
-  VectorSet(points[3], vMax[0], vMax[1], vMid[2]);\r
-  VectorSet(points[4], vMax[0], vMin[1], vMid[2]);\r
-  VectorSet(points[5], vMin[0], vMin[1], vMid[2]);\r
-\r
-  if (nGLState & DRAW_GL_LIGHTING)// && g_PrefsDlg.m_bGLLighting)\r
-  {\r
-    g_QglTable.m_pfn_qglBegin(GL_TRIANGLES);// NOTE: comment to use gl_triangle_fan instead\r
-         //g_QglTable.m_pfn_qglBegin(GL_TRIANGLE_FAN);\r
-    g_QglTable.m_pfn_qglVertex3fv(points[0]);\r
-    g_QglTable.m_pfn_qglVertex3fv(points[2]);\r
-         g_QglTable.m_pfn_qglNormal3fv(normals[0]);\r
-         g_QglTable.m_pfn_qglVertex3fv(points[3]);\r
-\r
-         g_QglTable.m_pfn_qglVertex3fv(points[0]);//\r
-    g_QglTable.m_pfn_qglVertex3fv(points[3]);//\r
-         g_QglTable.m_pfn_qglNormal3fv(normals[1]);\r
-         g_QglTable.m_pfn_qglVertex3fv(points[4]);\r
-\r
-         g_QglTable.m_pfn_qglVertex3fv(points[0]);//\r
-    g_QglTable.m_pfn_qglVertex3fv(points[4]);//\r
-         g_QglTable.m_pfn_qglNormal3fv(normals[2]);\r
-         g_QglTable.m_pfn_qglVertex3fv(points[5]);\r
-\r
-         g_QglTable.m_pfn_qglVertex3fv(points[0]);//\r
-    g_QglTable.m_pfn_qglVertex3fv(points[5]);//\r
-         g_QglTable.m_pfn_qglNormal3fv(normals[3]);\r
-         g_QglTable.m_pfn_qglVertex3fv(points[2]);\r
-\r
-         //g_QglTable.m_pfn_qglEnd();\r
-         //g_QglTable.m_pfn_qglBegin(GL_TRIANGLE_FAN);\r
-\r
-         g_QglTable.m_pfn_qglVertex3fv(points[1]);\r
-         g_QglTable.m_pfn_qglVertex3fv(points[2]);\r
-    g_QglTable.m_pfn_qglNormal3fv(normals[7]);\r
-         g_QglTable.m_pfn_qglVertex3fv(points[5]);\r
-\r
-         g_QglTable.m_pfn_qglVertex3fv(points[1]);//\r
-         g_QglTable.m_pfn_qglVertex3fv(points[5]);//\r
-    g_QglTable.m_pfn_qglNormal3fv(normals[6]);\r
-         g_QglTable.m_pfn_qglVertex3fv(points[4]);\r
-\r
-         g_QglTable.m_pfn_qglVertex3fv(points[1]);//\r
-         g_QglTable.m_pfn_qglVertex3fv(points[4]);//\r
-    g_QglTable.m_pfn_qglNormal3fv(normals[5]);\r
-         g_QglTable.m_pfn_qglVertex3fv(points[3]);\r
-\r
-         g_QglTable.m_pfn_qglVertex3fv(points[1]);//\r
-         g_QglTable.m_pfn_qglVertex3fv(points[3]);//\r
-    g_QglTable.m_pfn_qglNormal3fv(normals[4]);\r
-         g_QglTable.m_pfn_qglVertex3fv(points[2]);\r
-\r
-    g_QglTable.m_pfn_qglEnd();\r
-  }\r
-  else if (nGLState & DRAW_GL_FILL)\r
-  {\r
-    vec3_t colors[4];\r
-    VectorScale(e->color, 0.95, colors[0]);\r
-    VectorScale(colors[0], 0.95, colors[1]);\r
-    VectorScale(colors[1], 0.95, colors[2]);\r
-    VectorScale(colors[2], 0.95, colors[3]);\r
-    g_QglTable.m_pfn_qglBegin(GL_TRIANGLES);// NOTE: comment to use gl_triangle_fan instead\r
-         //g_QglTable.m_pfn_qglBegin(GL_TRIANGLE_FAN);\r
-    g_QglTable.m_pfn_qglColor3fv(colors[0]);\r
-    g_QglTable.m_pfn_qglVertex3fv(points[0]);\r
-    g_QglTable.m_pfn_qglVertex3fv(points[2]);\r
-         g_QglTable.m_pfn_qglVertex3fv(points[3]);\r
-\r
-    g_QglTable.m_pfn_qglColor3fv(colors[1]);\r
-         g_QglTable.m_pfn_qglVertex3fv(points[0]);//\r
-    g_QglTable.m_pfn_qglVertex3fv(points[3]);//\r
-         g_QglTable.m_pfn_qglVertex3fv(points[4]);\r
-\r
-    g_QglTable.m_pfn_qglColor3fv(colors[2]);\r
-         g_QglTable.m_pfn_qglVertex3fv(points[0]);//\r
-    g_QglTable.m_pfn_qglVertex3fv(points[4]);//\r
-         g_QglTable.m_pfn_qglVertex3fv(points[5]);\r
-\r
-    g_QglTable.m_pfn_qglColor3fv(colors[3]);\r
-         g_QglTable.m_pfn_qglVertex3fv(points[0]);//\r
-    g_QglTable.m_pfn_qglVertex3fv(points[5]);//\r
-         g_QglTable.m_pfn_qglVertex3fv(points[2]);\r
-\r
-         //g_QglTable.m_pfn_qglEnd();\r
-         //g_QglTable.m_pfn_qglBegin(GL_TRIANGLE_FAN);\r
-\r
-    g_QglTable.m_pfn_qglColor3fv(colors[0]);\r
-         g_QglTable.m_pfn_qglVertex3fv(points[1]);\r
-         g_QglTable.m_pfn_qglVertex3fv(points[2]);\r
-         g_QglTable.m_pfn_qglVertex3fv(points[5]);\r
-\r
-    g_QglTable.m_pfn_qglColor3fv(colors[1]);\r
-         g_QglTable.m_pfn_qglVertex3fv(points[1]);//\r
-         g_QglTable.m_pfn_qglVertex3fv(points[5]);//\r
-         g_QglTable.m_pfn_qglVertex3fv(points[4]);\r
-\r
-    g_QglTable.m_pfn_qglColor3fv(colors[2]);\r
-         g_QglTable.m_pfn_qglVertex3fv(points[1]);//\r
-         g_QglTable.m_pfn_qglVertex3fv(points[4]);//\r
-         g_QglTable.m_pfn_qglVertex3fv(points[3]);\r
-\r
-    g_QglTable.m_pfn_qglColor3fv(colors[3]);\r
-         g_QglTable.m_pfn_qglVertex3fv(points[1]);//\r
-         g_QglTable.m_pfn_qglVertex3fv(points[3]);//\r
-         g_QglTable.m_pfn_qglVertex3fv(points[2]);\r
-\r
-    g_QglTable.m_pfn_qglEnd();\r
-  }\r
-  else\r
-  {\r
-         g_QglTable.m_pfn_qglVertexPointer(3, GL_FLOAT, 0, points);\r
-         g_QglTable.m_pfn_qglDrawElements(GL_TRIANGLES, 24, GL_UNSIGNED_SHORT, indices);\r
-  }\r
-\r
-\r
-  // NOTE: prolly not relevant until some time..\r
-  // check for DOOM lights\r
-  if (strlen(ValueForKey(e, "light_right")) > 0) {\r
-    vec3_t vRight, vUp, vTarget, vTemp;\r
-    GetVectorForKey (e, "light_right", vRight);\r
-    GetVectorForKey (e, "light_up", vUp);\r
-    GetVectorForKey (e, "light_target", vTarget);\r
-\r
-    g_QglTable.m_pfn_qglColor3f(0, 1, 0);\r
-               g_QglTable.m_pfn_qglBegin(GL_LINE_LOOP);\r
-    VectorAdd(vTarget, e->origin, vTemp);\r
-    VectorAdd(vTemp, vRight, vTemp);\r
-    VectorAdd(vTemp, vUp, vTemp);\r
-    g_QglTable.m_pfn_qglVertex3fv(e->origin);\r
-    g_QglTable.m_pfn_qglVertex3fv(vTemp);\r
-    VectorAdd(vTarget, e->origin, vTemp);\r
-    VectorAdd(vTemp, vUp, vTemp);\r
-    VectorSubtract(vTemp, vRight, vTemp);\r
-    g_QglTable.m_pfn_qglVertex3fv(e->origin);\r
-    g_QglTable.m_pfn_qglVertex3fv(vTemp);\r
-    VectorAdd(vTarget, e->origin, vTemp);\r
-    VectorAdd(vTemp, vRight, vTemp);\r
-    VectorSubtract(vTemp, vUp, vTemp);\r
-    g_QglTable.m_pfn_qglVertex3fv(e->origin);\r
-    g_QglTable.m_pfn_qglVertex3fv(vTemp);\r
-    VectorAdd(vTarget, e->origin, vTemp);\r
-    VectorSubtract(vTemp, vUp, vTemp);\r
-    VectorSubtract(vTemp, vRight, vTemp);\r
-    g_QglTable.m_pfn_qglVertex3fv(e->origin);\r
-    g_QglTable.m_pfn_qglVertex3fv(vTemp);\r
-    g_QglTable.m_pfn_qglEnd();\r
-\r
-  }\r
-\r
-  if(nGLState & DRAW_GL_FILL)\r
-  {\r
-    DrawLightSphere(e, nGLState, pref);\r
-  }\r
-  else\r
-  {\r
-    // Arnout: FIXME: clean this up a bit\r
-    // now draw lighting radius stuff...\r
-    if (pref)\r
-    {\r
-      bool bDrawSpotlightArc = false;\r
-      int nPasses = pref == 1 ? 3 : 2;\r
-\r
-      const char *target = ValueForKey(e, "target");\r
-      bool bIsSpotLight = !!target[0];\r
-\r
-      /*!\todo Spotlight..\r
-      if (bIsSpotLight)\r
-      {\r
-        // find the origin of the target...\r
-        entity_t *e = FindEntity("targetname", target);\r
-\r
-        if (e)\r
-          bDrawSpotlightArc = true;\r
-      }\r
-      */\r
-\r
-      g_QglTable.m_pfn_qglPushAttrib(GL_LINE_BIT);\r
-      g_QglTable.m_pfn_qglLineStipple(8, 0xAAAA);\r
-      g_QglTable.m_pfn_qglEnable(GL_LINE_STIPPLE);\r
-\r
-      float* envelope = (pref == 1) ? e->fLightEnvelope1 : e->fLightEnvelope2; \r
-      for (int iPass = 0; iPass < nPasses; iPass++)\r
-      {\r
-        float fRadius = envelope[iPass];\r
-\r
-        g_QglTable.m_pfn_qglBegin(GL_LINE_LOOP);\r
-\r
-        if (bIsSpotLight)\r
-        {\r
-          if (bDrawSpotlightArc)\r
-          {\r
-            // I give up on this, it's beyond me\r
-          }\r
-        }\r
-        else\r
-        {\r
-          if (fRadius > 0)\r
-          {\r
-            int i;\r
-            float ds, dc;\r
-\r
-            for (i = 0; i <= 24; i++)\r
-            {\r
-              ds = sin((i * 2 * Q_PI) / 24);\r
-              dc = cos((i * 2 * Q_PI) / 24);\r
-\r
-              switch (nViewType)\r
-              {\r
-              case 2:\r
-                g_QglTable.m_pfn_qglVertex3f(e->origin[0] + fRadius * dc,\r
-                  e->origin[1] + fRadius * ds,\r
-                  e->origin[2]);\r
-                break;\r
-              case 1:\r
-                g_QglTable.m_pfn_qglVertex3f(e->origin[0] + fRadius * dc,\r
-                   e->origin[1],\r
-                  e->origin[2] + fRadius * ds);\r
-                break;\r
-              case 0:\r
-                g_QglTable.m_pfn_qglVertex3f(e->origin[0],\r
-                  e->origin[1] + fRadius * dc,\r
-                  e->origin[2] + fRadius * ds);\r
-                break;\r
-              }\r
-            }\r
-          }\r
-        }\r
-        g_QglTable.m_pfn_qglEnd();\r
-      }\r
-      g_QglTable.m_pfn_qglPopAttrib();\r
-    }\r
-  }\r
-}\r
-\r
-\r
+
+#include "plugin.h"
+#include "entity.h"
+#include "light.h"
+
+void DrawSphere(vec3_t center, float radius, int sides, int nGLState)
+{
+  int i, j;
+  float dt = (float) (2 * Q_PI / (float) sides);
+  float dp = (float) (Q_PI / (float) sides);
+  float t, p;
+  vec3_t v;
+
+  if (radius <= 0)
+    return;
+
+  g_QglTable.m_pfn_qglBegin(GL_TRIANGLES);
+  for (i = 0; i <= sides - 1; i++) {
+    for (j = 0; j <= sides - 2; j++) {
+      t = i * dt;
+      p = (float) ((j * dp) - (Q_PI / 2));
+
+      VectorPolar(v, radius, t, p);
+      VectorAdd(v, center, v);
+      g_QglTable.m_pfn_qglVertex3fv(v);
+
+      VectorPolar(v, radius, t, p + dp);
+      VectorAdd(v, center, v);
+      g_QglTable.m_pfn_qglVertex3fv(v);
+
+      VectorPolar(v, radius, t + dt, p + dp);
+      VectorAdd(v, center, v);
+      g_QglTable.m_pfn_qglVertex3fv(v);
+
+      VectorPolar(v, radius, t, p);
+      VectorAdd(v, center, v);
+      g_QglTable.m_pfn_qglVertex3fv(v);
+
+      VectorPolar(v, radius, t + dt, p + dp);
+      VectorAdd(v, center, v);
+      g_QglTable.m_pfn_qglVertex3fv(v);
+
+      VectorPolar(v, radius, t + dt, p);
+      VectorAdd(v, center, v);
+      g_QglTable.m_pfn_qglVertex3fv(v);
+    }
+  }
+
+  p = (float) ((sides - 1) * dp - (Q_PI / 2));
+  for (i = 0; i <= sides - 1; i++) {
+    t = i * dt;
+
+    VectorPolar(v, radius, t, p);
+    VectorAdd(v, center, v);
+    g_QglTable.m_pfn_qglVertex3fv(v);
+
+    VectorPolar(v, radius, t + dt, p + dp);
+    VectorAdd(v, center, v);
+    g_QglTable.m_pfn_qglVertex3fv(v);
+
+    VectorPolar(v, radius, t + dt, p);
+    VectorAdd(v, center, v);
+    g_QglTable.m_pfn_qglVertex3fv(v);
+  }
+  g_QglTable.m_pfn_qglEnd();
+}
+
+#define LIGHT_ATTEN_LINEAR     1
+#define LIGHT_ATTEN_ANGLE              2
+#define LIGHT_ATTEN_DISTANCE   4
+
+#define LIGHT_Q3A_DEFAULT              (LIGHT_ATTEN_ANGLE | LIGHT_ATTEN_DISTANCE)
+#define LIGHT_WOLF_DEFAULT     (LIGHT_ATTEN_LINEAR | LIGHT_ATTEN_DISTANCE)
+
+float CalculateEnvelopeForLight(entity_t * e, float fFalloffTolerance)
+{
+  float fEnvelope = 0.f;
+  int iSpawnFlags = atoi(ValueForKey(e, "spawnflags"));
+  int iLightFlags = 0;
+  float fFade = 1.f;
+  float fIntensity, fPhotons;
+  float fScale;
+  const char *gameFile = g_FuncTable.m_pfnGetGameFile();
+
+  // These variables are tweakable on the q3map2 console, setting to q3map2
+  // default here as there is no way to find out what the user actually uses
+  // right now. Maybe move them to worldspawn?
+  float fPointScale = 7500.f;
+  float fLinearScale = 1.f / 8000.f;
+  //float fFalloffTolerance = 1.f;  // Need it as parameter
+
+  // Arnout: HACK for per-game radii - really need to move this to a per-game module?
+  if( !strcmp( gameFile, "wolf.game" ) || !strcmp( gameFile, "et.game" ) ) {
+    // Spawnflags :
+    // 1: nonlinear
+    // 2: angle
+
+    // set default flags
+    iLightFlags = LIGHT_WOLF_DEFAULT;
+
+    // inverse distance squared attenuation?
+    if (iSpawnFlags & 1) {
+      iLightFlags &= ~LIGHT_ATTEN_LINEAR;
+      iLightFlags |= LIGHT_ATTEN_ANGLE;
+    }
+    // angle attenuate
+    if (iSpawnFlags & 2)
+      iLightFlags |= LIGHT_ATTEN_ANGLE;
+  } else {
+    // Spawnflags :
+    // 1: linear
+    // 2: no angle
+
+    // set default flags
+    iLightFlags = LIGHT_Q3A_DEFAULT;
+
+    // linear attenuation?
+    if (iSpawnFlags & 1) {
+      iLightFlags |= LIGHT_ATTEN_LINEAR;
+      iLightFlags &= ~LIGHT_ATTEN_ANGLE;
+    }
+    // no angle attenuate?
+    if (iSpawnFlags & 2)
+      iLightFlags &= ~LIGHT_ATTEN_ANGLE;
+  }
+
+  // set fade key (from wolf)
+  if (iLightFlags & LIGHT_ATTEN_LINEAR) {
+    fFade = FloatForKey(e, "fade");
+    if (fFade <= 0.f)
+      fFade = 1.f;
+  }
+  // set light intensity
+  fIntensity = FloatForKey(e, "_light");
+  if (fIntensity == 0.f)
+    fIntensity = FloatForKey(e, "light");
+  if (fIntensity == 0.f)
+    fIntensity = 300.f;
+
+  // set light scale (sof2)
+  fScale = FloatForKey(e, "scale");
+  if (fScale <= 0.f)
+    fScale = 1.f;
+  fIntensity *= fScale;
+
+  // amount of photons
+  fPhotons = fIntensity * fPointScale;
+
+  // calculate envelope
+
+  // solve distance for non-distance lights
+  if (!(iLightFlags & LIGHT_ATTEN_DISTANCE))
+    //!\todo (spog) can't access global objects in a module - globals are EVIL - solution: API for querying global settings.
+    fEnvelope = 131072/*g_MaxWorldCoord * 2.f*/;
+  // solve distance for linear lights
+  else if (iLightFlags & LIGHT_ATTEN_LINEAR)
+    fEnvelope = ((fPhotons * fLinearScale) - fFalloffTolerance) / fFade;
+  // solve for inverse square falloff
+  else
+    fEnvelope = sqrt(fPhotons / fFalloffTolerance) /* + fRadius */ ;  // Arnout radius is always 0, only for area lights
+
+  return fEnvelope;
+}
+
+float CalculateLightRadius(entity_t * e, bool outer)
+{
+  float fEnvelope = 0.f;
+  int iSpawnFlags = atoi(ValueForKey(e, "spawnflags"));
+  float fIntensity;
+  float fScale;
+  const char *gameFile = g_FuncTable.m_pfnGetGameFile();
+
+  fIntensity = FloatForKey(e, "light");
+  if (fIntensity == 0.f)
+    fIntensity = 300.f;
+
+  // Arnout: HACK for per-game radii - really need to move this to a per-game module
+  if( !strcmp( gameFile, "sof2.game" ) || !strcmp( gameFile, "jk2.game" ) || !strcmp( gameFile, "ja.game" )) {
+    // Spawnflags :
+    // 1: linear
+    // 2: noincidence
+
+    if (!outer) {
+      if (iSpawnFlags & 2)
+        fIntensity *= .9;
+      else
+        fIntensity *= .25f;
+    }
+    // set light scale (sof2)
+    fScale = FloatForKey(e, "scale");
+    if (fScale <= 0.f)
+      fScale = 1.f;
+    fIntensity *= fScale;
+
+    fEnvelope = fIntensity;
+  } else {
+    float fPointScale = 7500.f;
+
+    if (outer)
+      fEnvelope = sqrt(fIntensity * fPointScale / 48.f);
+    else
+      fEnvelope = sqrt(fIntensity * fPointScale / 255.f);
+  }
+
+  return fEnvelope;
+}
+
+void Light_OnIntensityChanged(entity_t* e)
+{
+  e->fLightEnvelope1[0] = CalculateEnvelopeForLight(e, 1.f);
+  e->fLightEnvelope1[1] = CalculateEnvelopeForLight(e, 48.f);
+  e->fLightEnvelope1[2] = CalculateEnvelopeForLight(e, 255.f);
+
+  e->fLightEnvelope2[0] = CalculateLightRadius(e, TRUE);
+  e->fLightEnvelope2[1] = CalculateLightRadius(e, FALSE);
+}
+
+void Light_OnKeyValueChanged(entity_t *e, const char *key, const char* value)
+{
+  if(strcmp(key,"_color") == 0)
+  {
+    if (sscanf(ValueForKey(e, "_color"),"%f %f %f",
+      &e->color[0], &e->color[1], &e->color[2]) != 3)
+      VectorSet(e->color, 1, 1, 1);
+  }
+  else if(strcmp(key,"spawnflags") == 0 ||
+          strcmp(key,"fade") == 0 ||
+          strcmp(key,"_light") == 0 ||
+          strcmp(key,"light") == 0 ||
+          strcmp(key,"scale") == 0)
+  {
+    Light_OnIntensityChanged(e);
+  }
+}
+
+bool Entity_IsLight(entity_t *e)
+{
+  return e->eclass != NULL && e->eclass->nShowFlags & ECLASS_LIGHT;//strncmp(ValueforKey(e, "classname"), "light") == 0
+}
+
+static void DrawLightSphere(entity_t * e, int nGLState, int pref)
+{
+  const char *target = ValueForKey(e, "target");
+  bool bIsSpotLight = !!target[0];
+  //!\todo Write an API for modules to register preference settings, and make this preference module-specific.
+  int nPasses = pref == 1 ? 3 : 2;
+
+  g_QglTable.m_pfn_qglPushAttrib(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
+  g_QglTable.m_pfn_qglDepthMask(GL_FALSE);
+  g_QglTable.m_pfn_qglEnable(GL_BLEND);
+  g_QglTable.m_pfn_qglBlendFunc(GL_ONE, GL_ONE);
+
+  // Arnout: TODO: spotlight rendering
+  if (!(bIsSpotLight))
+  {
+    switch(pref)
+    {
+    case 1:
+      g_QglTable.m_pfn_qglColor3f(e->color[0] * .05f,
+        e->color[1] * .05f,
+        e->color[2] * .05f);
+      DrawSphere(e->origin, e->fLightEnvelope1[0], 16, nGLState);
+      DrawSphere(e->origin, e->fLightEnvelope1[1], 16, nGLState);
+      DrawSphere(e->origin, e->fLightEnvelope1[2], 16, nGLState);
+      break;
+    case 2:
+      g_QglTable.m_pfn_qglColor3f(e->color[0] * .15f * .95f,
+        e->color[1] * .15f * .95f,
+        e->color[2] * .15f * .95f);
+      DrawSphere(e->origin, e->fLightEnvelope2[0], 16, nGLState);
+      DrawSphere(e->origin, e->fLightEnvelope2[1], 16, nGLState);
+      break;
+
+    }
+  }
+
+  g_QglTable.m_pfn_qglPopAttrib();
+}
+
+float F = 0.70710678f;
+// North, East, South, West
+vec3_t normals[8] = { { 0, F, F }, { F, 0, F }, { 0,-F, F }, {-F, 0, F },
+                                                                                       { 0, F,-F }, { F, 0,-F }, { 0,-F,-F }, {-F, 0,-F } };
+
+unsigned short indices[24] = { 0, 2, 3, 0, 3, 4, 0, 4, 5, 0, 5, 2,
+                               1, 2, 5, 1, 5, 4, 1, 4, 3, 1, 3, 2 };
+
+void DrawLight(entity_t* e, int nGLState, int pref, int nViewType)
+{
+  int i;
+  // top, bottom, tleft, tright, bright, bleft
+  vec3_t points[6];
+  vec3_t vMid, vMin, vMax;
+  VectorAdd(e->origin, e->eclass->mins, vMin);
+  VectorAdd(e->origin, e->eclass->maxs, vMax);
+  vMid[0] = (vMin[0] + vMax[0]) * 0.5;
+  vMid[1] = (vMin[1] + vMax[1]) * 0.5;
+  vMid[2] = (vMin[2] + vMax[2]) * 0.5;
+
+  VectorSet(points[0], vMid[0], vMid[1], vMax[2]);
+  VectorSet(points[1], vMid[0], vMid[1], vMin[2]);
+  VectorSet(points[2], vMin[0], vMax[1], vMid[2]);
+  VectorSet(points[3], vMax[0], vMax[1], vMid[2]);
+  VectorSet(points[4], vMax[0], vMin[1], vMid[2]);
+  VectorSet(points[5], vMin[0], vMin[1], vMid[2]);
+
+  if (nGLState & DRAW_GL_LIGHTING)// && g_PrefsDlg.m_bGLLighting)
+  {
+    g_QglTable.m_pfn_qglBegin(GL_TRIANGLES);// NOTE: comment to use gl_triangle_fan instead
+         //g_QglTable.m_pfn_qglBegin(GL_TRIANGLE_FAN);
+    g_QglTable.m_pfn_qglVertex3fv(points[0]);
+    g_QglTable.m_pfn_qglVertex3fv(points[2]);
+         g_QglTable.m_pfn_qglNormal3fv(normals[0]);
+         g_QglTable.m_pfn_qglVertex3fv(points[3]);
+
+         g_QglTable.m_pfn_qglVertex3fv(points[0]);//
+    g_QglTable.m_pfn_qglVertex3fv(points[3]);//
+         g_QglTable.m_pfn_qglNormal3fv(normals[1]);
+         g_QglTable.m_pfn_qglVertex3fv(points[4]);
+
+         g_QglTable.m_pfn_qglVertex3fv(points[0]);//
+    g_QglTable.m_pfn_qglVertex3fv(points[4]);//
+         g_QglTable.m_pfn_qglNormal3fv(normals[2]);
+         g_QglTable.m_pfn_qglVertex3fv(points[5]);
+
+         g_QglTable.m_pfn_qglVertex3fv(points[0]);//
+    g_QglTable.m_pfn_qglVertex3fv(points[5]);//
+         g_QglTable.m_pfn_qglNormal3fv(normals[3]);
+         g_QglTable.m_pfn_qglVertex3fv(points[2]);
+
+         //g_QglTable.m_pfn_qglEnd();
+         //g_QglTable.m_pfn_qglBegin(GL_TRIANGLE_FAN);
+
+         g_QglTable.m_pfn_qglVertex3fv(points[1]);
+         g_QglTable.m_pfn_qglVertex3fv(points[2]);
+    g_QglTable.m_pfn_qglNormal3fv(normals[7]);
+         g_QglTable.m_pfn_qglVertex3fv(points[5]);
+
+         g_QglTable.m_pfn_qglVertex3fv(points[1]);//
+         g_QglTable.m_pfn_qglVertex3fv(points[5]);//
+    g_QglTable.m_pfn_qglNormal3fv(normals[6]);
+         g_QglTable.m_pfn_qglVertex3fv(points[4]);
+
+         g_QglTable.m_pfn_qglVertex3fv(points[1]);//
+         g_QglTable.m_pfn_qglVertex3fv(points[4]);//
+    g_QglTable.m_pfn_qglNormal3fv(normals[5]);
+         g_QglTable.m_pfn_qglVertex3fv(points[3]);
+
+         g_QglTable.m_pfn_qglVertex3fv(points[1]);//
+         g_QglTable.m_pfn_qglVertex3fv(points[3]);//
+    g_QglTable.m_pfn_qglNormal3fv(normals[4]);
+         g_QglTable.m_pfn_qglVertex3fv(points[2]);
+
+    g_QglTable.m_pfn_qglEnd();
+  }
+  else if (nGLState & DRAW_GL_FILL)
+  {
+    vec3_t colors[4];
+    VectorScale(e->color, 0.95, colors[0]);
+    VectorScale(colors[0], 0.95, colors[1]);
+    VectorScale(colors[1], 0.95, colors[2]);
+    VectorScale(colors[2], 0.95, colors[3]);
+    g_QglTable.m_pfn_qglBegin(GL_TRIANGLES);// NOTE: comment to use gl_triangle_fan instead
+         //g_QglTable.m_pfn_qglBegin(GL_TRIANGLE_FAN);
+    g_QglTable.m_pfn_qglColor3fv(colors[0]);
+    g_QglTable.m_pfn_qglVertex3fv(points[0]);
+    g_QglTable.m_pfn_qglVertex3fv(points[2]);
+         g_QglTable.m_pfn_qglVertex3fv(points[3]);
+
+    g_QglTable.m_pfn_qglColor3fv(colors[1]);
+         g_QglTable.m_pfn_qglVertex3fv(points[0]);//
+    g_QglTable.m_pfn_qglVertex3fv(points[3]);//
+         g_QglTable.m_pfn_qglVertex3fv(points[4]);
+
+    g_QglTable.m_pfn_qglColor3fv(colors[2]);
+         g_QglTable.m_pfn_qglVertex3fv(points[0]);//
+    g_QglTable.m_pfn_qglVertex3fv(points[4]);//
+         g_QglTable.m_pfn_qglVertex3fv(points[5]);
+
+    g_QglTable.m_pfn_qglColor3fv(colors[3]);
+         g_QglTable.m_pfn_qglVertex3fv(points[0]);//
+    g_QglTable.m_pfn_qglVertex3fv(points[5]);//
+         g_QglTable.m_pfn_qglVertex3fv(points[2]);
+
+         //g_QglTable.m_pfn_qglEnd();
+         //g_QglTable.m_pfn_qglBegin(GL_TRIANGLE_FAN);
+
+    g_QglTable.m_pfn_qglColor3fv(colors[0]);
+         g_QglTable.m_pfn_qglVertex3fv(points[1]);
+         g_QglTable.m_pfn_qglVertex3fv(points[2]);
+         g_QglTable.m_pfn_qglVertex3fv(points[5]);
+
+    g_QglTable.m_pfn_qglColor3fv(colors[1]);
+         g_QglTable.m_pfn_qglVertex3fv(points[1]);//
+         g_QglTable.m_pfn_qglVertex3fv(points[5]);//
+         g_QglTable.m_pfn_qglVertex3fv(points[4]);
+
+    g_QglTable.m_pfn_qglColor3fv(colors[2]);
+         g_QglTable.m_pfn_qglVertex3fv(points[1]);//
+         g_QglTable.m_pfn_qglVertex3fv(points[4]);//
+         g_QglTable.m_pfn_qglVertex3fv(points[3]);
+
+    g_QglTable.m_pfn_qglColor3fv(colors[3]);
+         g_QglTable.m_pfn_qglVertex3fv(points[1]);//
+         g_QglTable.m_pfn_qglVertex3fv(points[3]);//
+         g_QglTable.m_pfn_qglVertex3fv(points[2]);
+
+    g_QglTable.m_pfn_qglEnd();
+  }
+  else
+  {
+         g_QglTable.m_pfn_qglVertexPointer(3, GL_FLOAT, 0, points);
+         g_QglTable.m_pfn_qglDrawElements(GL_TRIANGLES, 24, GL_UNSIGNED_SHORT, indices);
+  }
+
+
+  // NOTE: prolly not relevant until some time..
+  // check for DOOM lights
+  if (strlen(ValueForKey(e, "light_right")) > 0) {
+    vec3_t vRight, vUp, vTarget, vTemp;
+    GetVectorForKey (e, "light_right", vRight);
+    GetVectorForKey (e, "light_up", vUp);
+    GetVectorForKey (e, "light_target", vTarget);
+
+    g_QglTable.m_pfn_qglColor3f(0, 1, 0);
+               g_QglTable.m_pfn_qglBegin(GL_LINE_LOOP);
+    VectorAdd(vTarget, e->origin, vTemp);
+    VectorAdd(vTemp, vRight, vTemp);
+    VectorAdd(vTemp, vUp, vTemp);
+    g_QglTable.m_pfn_qglVertex3fv(e->origin);
+    g_QglTable.m_pfn_qglVertex3fv(vTemp);
+    VectorAdd(vTarget, e->origin, vTemp);
+    VectorAdd(vTemp, vUp, vTemp);
+    VectorSubtract(vTemp, vRight, vTemp);
+    g_QglTable.m_pfn_qglVertex3fv(e->origin);
+    g_QglTable.m_pfn_qglVertex3fv(vTemp);
+    VectorAdd(vTarget, e->origin, vTemp);
+    VectorAdd(vTemp, vRight, vTemp);
+    VectorSubtract(vTemp, vUp, vTemp);
+    g_QglTable.m_pfn_qglVertex3fv(e->origin);
+    g_QglTable.m_pfn_qglVertex3fv(vTemp);
+    VectorAdd(vTarget, e->origin, vTemp);
+    VectorSubtract(vTemp, vUp, vTemp);
+    VectorSubtract(vTemp, vRight, vTemp);
+    g_QglTable.m_pfn_qglVertex3fv(e->origin);
+    g_QglTable.m_pfn_qglVertex3fv(vTemp);
+    g_QglTable.m_pfn_qglEnd();
+
+  }
+
+  if(nGLState & DRAW_GL_FILL)
+  {
+    DrawLightSphere(e, nGLState, pref);
+  }
+  else
+  {
+    // Arnout: FIXME: clean this up a bit
+    // now draw lighting radius stuff...
+    if (pref)
+    {
+      bool bDrawSpotlightArc = false;
+      int nPasses = pref == 1 ? 3 : 2;
+
+      const char *target = ValueForKey(e, "target");
+      bool bIsSpotLight = !!target[0];
+
+      /*!\todo Spotlight..
+      if (bIsSpotLight)
+      {
+        // find the origin of the target...
+        entity_t *e = FindEntity("targetname", target);
+
+        if (e)
+          bDrawSpotlightArc = true;
+      }
+      */
+
+      g_QglTable.m_pfn_qglPushAttrib(GL_LINE_BIT);
+      g_QglTable.m_pfn_qglLineStipple(8, 0xAAAA);
+      g_QglTable.m_pfn_qglEnable(GL_LINE_STIPPLE);
+
+      float* envelope = (pref == 1) ? e->fLightEnvelope1 : e->fLightEnvelope2; 
+      for (int iPass = 0; iPass < nPasses; iPass++)
+      {
+        float fRadius = envelope[iPass];
+
+        g_QglTable.m_pfn_qglBegin(GL_LINE_LOOP);
+
+        if (bIsSpotLight)
+        {
+          if (bDrawSpotlightArc)
+          {
+            // I give up on this, it's beyond me
+          }
+        }
+        else
+        {
+          if (fRadius > 0)
+          {
+            int i;
+            float ds, dc;
+
+            for (i = 0; i <= 24; i++)
+            {
+              ds = sin((i * 2 * Q_PI) / 24);
+              dc = cos((i * 2 * Q_PI) / 24);
+
+              switch (nViewType)
+              {
+              case 2:
+                g_QglTable.m_pfn_qglVertex3f(e->origin[0] + fRadius * dc,
+                  e->origin[1] + fRadius * ds,
+                  e->origin[2]);
+                break;
+              case 1:
+                g_QglTable.m_pfn_qglVertex3f(e->origin[0] + fRadius * dc,
+                   e->origin[1],
+                  e->origin[2] + fRadius * ds);
+                break;
+              case 0:
+                g_QglTable.m_pfn_qglVertex3f(e->origin[0],
+                  e->origin[1] + fRadius * dc,
+                  e->origin[2] + fRadius * ds);
+                break;
+              }
+            }
+          }
+        }
+        g_QglTable.m_pfn_qglEnd();
+      }
+      g_QglTable.m_pfn_qglPopAttrib();
+    }
+  }
+}
+
+