home *** CD-ROM | disk | FTP | other *** search
/ Maximum CD 2007 September / maximum-cd-2007-09.iso / Assets / data / AssaultCube_v0.93.exe / source / src / rendergl.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2007-05-30  |  20.2 KB  |  719 lines

  1. // rendergl.cpp: core opengl rendering stuff
  2.  
  3. #include "cube.h"
  4. #include "bot/bot.h"
  5.  
  6. bool hasTE = false, hasMT = false, hasMDA = false;
  7.  
  8. // GL_ARB_multitexture
  9. PFNGLACTIVETEXTUREARBPROC       glActiveTexture_   = NULL;
  10. PFNGLCLIENTACTIVETEXTUREARBPROC glClientActiveTexture_ = NULL;
  11. PFNGLMULTITEXCOORD2FARBPROC     glMultiTexCoord2f_ = NULL;
  12. PFNGLMULTITEXCOORD3FARBPROC     glMultiTexCoord3f_ = NULL;
  13.  
  14. // GL_EXT_multi_draw_arrays
  15. PFNGLMULTIDRAWARRAYSEXTPROC glMultiDrawArrays_ = NULL;
  16.  
  17. void *getprocaddress(const char *name)
  18. {
  19.     return SDL_GL_GetProcAddress(name);
  20. }
  21.  
  22. void gl_init(int w, int h, int bpp, int depth, int fsaa)
  23. {
  24.     //#define fogvalues 0.5f, 0.6f, 0.7f, 1.0f
  25.  
  26.     glViewport(0, 0, w, h);
  27.     glClearDepth(1.0);
  28.     glDepthFunc(GL_LESS);
  29.     glEnable(GL_DEPTH_TEST);
  30.     glShadeModel(GL_SMOOTH);
  31.     
  32.     
  33.     glEnable(GL_FOG);
  34.     glFogi(GL_FOG_MODE, GL_LINEAR);
  35.     glFogf(GL_FOG_DENSITY, 0.25);
  36.     glHint(GL_FOG_HINT, GL_NICEST);
  37.     
  38.  
  39.     glEnable(GL_LINE_SMOOTH);
  40.     glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
  41.     glEnable(GL_POLYGON_OFFSET_LINE);
  42.     glPolygonOffset(-3.0, -3.0);
  43.  
  44.     glCullFace(GL_FRONT);
  45.     glEnable(GL_CULL_FACE);
  46.  
  47.     const char *vendor = (const char *)glGetString(GL_VENDOR);
  48.     const char *exts = (const char *)glGetString(GL_EXTENSIONS);
  49.     const char *renderer = (const char *)glGetString(GL_RENDERER);
  50.     const char *version = (const char *)glGetString(GL_VERSION);
  51.     conoutf("Renderer: %s (%s)", renderer, vendor);
  52.     conoutf("Driver: %s", version);
  53.  
  54.     if(strstr(exts, "GL_EXT_texture_env_combine") || strstr(exts, "GL_ARB_texture_env_combine")) hasTE = true;
  55.     else conoutf("WARNING: cannot use overbright lighting, using old lighting model!");
  56.  
  57.     if(strstr(exts, "GL_ARB_multitexture"))
  58.     {
  59.         glActiveTexture_       = (PFNGLACTIVETEXTUREARBPROC)      getprocaddress("glActiveTextureARB");
  60.         glClientActiveTexture_ = (PFNGLCLIENTACTIVETEXTUREARBPROC)getprocaddress("glClientActiveTextureARB");
  61.         glMultiTexCoord2f_     = (PFNGLMULTITEXCOORD2FARBPROC)    getprocaddress("glMultiTexCoord2fARB");
  62.         glMultiTexCoord3f_     = (PFNGLMULTITEXCOORD3FARBPROC)    getprocaddress("glMultiTexCoord3fARB");
  63.         hasMT = true;
  64.     }
  65.  
  66.     if(strstr(exts, "GL_EXT_multi_draw_arrays"))
  67.     {
  68.         glMultiDrawArrays_ = (PFNGLMULTIDRAWARRAYSEXTPROC)getprocaddress("glMultiDrawArraysEXT");
  69.         hasMDA = true;
  70.     }
  71.  
  72.     if(fsaa) glEnable(GL_MULTISAMPLE);
  73.  
  74.     inittmus();
  75.  
  76.     camera1 = player1;
  77. }
  78.  
  79. void cleangl()
  80. {
  81. }
  82.  
  83. void line(int x1, int y1, float z1, int x2, int y2, float z2)
  84. {
  85.     glBegin(GL_POLYGON);
  86.     glVertex3f((float)x1, (float)y1, z1);
  87.     glVertex3f((float)x1, y1+0.01f, z1);
  88.     glVertex3f((float)x2, y2+0.01f, z2);
  89.     glVertex3f((float)x2, (float)y2, z2);
  90.     glEnd();
  91.     xtraverts += 4;
  92. }
  93.  
  94. void linestyle(float width, int r, int g, int b)
  95. {   
  96.     glLineWidth(width);
  97.     glColor3ub(r,g,b);
  98. }   
  99.     
  100. void box(block &b, float z1, float z2, float z3, float z4)
  101. {   
  102.     glBegin(GL_POLYGON);
  103.     glVertex3f((float)b.x,      (float)b.y,      z1);
  104.     glVertex3f((float)b.x+b.xs, (float)b.y,      z2);
  105.     glVertex3f((float)b.x+b.xs, (float)b.y+b.ys, z3);
  106.     glVertex3f((float)b.x,      (float)b.y+b.ys, z4);
  107.     glEnd();
  108.     xtraverts += 4;
  109. }   
  110.  
  111. void quad(GLuint tex, float x, float y, float s, float tx, float ty, float tsx, float tsy)
  112. {
  113.     if(!tsy) tsy = tsx;
  114.     glBindTexture(GL_TEXTURE_2D, tex);
  115.     glBegin(GL_QUADS);
  116.     glTexCoord2f(tx,     ty);     glVertex2f(x,   y);
  117.     glTexCoord2f(tx+tsx, ty);     glVertex2f(x+s, y);
  118.     glTexCoord2f(tx+tsx, ty+tsy); glVertex2f(x+s, y+s);
  119.     glTexCoord2f(tx,     ty+tsy); glVertex2f(x,   y+s);
  120.     glEnd();
  121.     xtraverts += 4;
  122. }
  123.  
  124. void circle(GLuint tex, float x, float y, float r, float tx, float ty, float tr, int subdiv)
  125. {
  126.     glBindTexture(GL_TEXTURE_2D, tex);
  127.     glBegin(GL_TRIANGLE_FAN);
  128.     glTexCoord2f(tx, ty); 
  129.     glVertex2f(x, y);
  130.     loopi(subdiv+1)
  131.     {
  132.         float c = cosf(2*M_PI*i/float(subdiv)), s = sinf(2*M_PI*i/float(subdiv));
  133.         glTexCoord2f(tx + tr*c, ty + tr*s);
  134.         glVertex2f(x + r*c, y + r*s);
  135.     }
  136.     glEnd();
  137.     xtraverts += subdiv+2;
  138. }
  139.  
  140. void dot(int x, int y, float z)
  141. {
  142.     const float DOF = 0.1f;
  143.     glBegin(GL_POLYGON);
  144.     glVertex3f(x-DOF, y-DOF, z);
  145.     glVertex3f(x+DOF, y-DOF, z);
  146.     glVertex3f(x+DOF, y+DOF, z);
  147.     glVertex3f(x-DOF, y+DOF, z);
  148.     glEnd();
  149.     xtraverts += 4;
  150. }
  151.  
  152. void blendbox(int x1, int y1, int x2, int y2, bool border, int tex)
  153. {   
  154.     glDepthMask(GL_FALSE);
  155.     glDisable(GL_TEXTURE_2D);
  156.     if(tex>=0)
  157.     {
  158.         glBindTexture(GL_TEXTURE_2D, tex);
  159.         glEnable(GL_TEXTURE_2D);
  160.         glDisable(GL_BLEND);
  161.         glColor3f(1, 1, 1);
  162.  
  163.         int texw = 512;
  164.         int texh = texw;
  165.         int cols = (int)((x2-x1)/texw+1);
  166.         int rows = (int)((y2-y1)/texh+1);
  167.         xtraverts += cols*rows*4;
  168.             
  169.         loopj(rows)
  170.         {
  171.             float ytexcut = 0.0f;
  172.             float yboxcut = 0.0f;
  173.             if((j+1)*texh>y2-y1) // cut last row to match the box height
  174.             {
  175.                 yboxcut = (float)(((j+1)*texh)-(y2-y1));
  176.                 ytexcut = (float)(((j+1)*texh)-(y2-y1))/texh;
  177.             }
  178.  
  179.             loopi(cols)
  180.             {
  181.                 float xtexcut = 0.0f;
  182.                 float xboxcut = 0.0f;
  183.                 if((i+1)*texw>x2-x1)
  184.                 {
  185.                     xboxcut = (float)(((i+1)*texw)-(x2-x1));
  186.                     xtexcut = (float)(((i+1)*texw)-(x2-x1))/texw;
  187.                 }
  188.  
  189.                 glBegin(GL_QUADS);
  190.                 glTexCoord2f(0, 0);                 glVertex2f((float)x1+texw*i, (float)y1+texh*j);
  191.                 glTexCoord2f(1-xtexcut, 0);         glVertex2f(x1+texw*(i+1)-xboxcut, (float)y1+texh*j);
  192.                 glTexCoord2f(1-xtexcut, 1-ytexcut); glVertex2f(x1+texw*(i+1)-xboxcut, (float)y1+texh*(j+1)-yboxcut);
  193.                 glTexCoord2f(0, 1-ytexcut);         glVertex2f((float)x1+texw*i, y1+texh*(j+1)-yboxcut);
  194.                 glEnd();
  195.             }
  196.         }
  197.     }
  198.     else
  199.     {
  200.         if(border) glColor3f(0.7f, 0.7f, 0.7f); //glColor3d(0.5, 0.3, 0.4); 
  201.         else glColor3f(1, 1, 1);
  202.         glBlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
  203.         glBegin(GL_QUADS);
  204.         glTexCoord2f(0, 0); glVertex2i(x1, y1);
  205.         glTexCoord2f(1, 0); glVertex2i(x2, y1);
  206.         glTexCoord2f(1, 1); glVertex2i(x2, y2);
  207.         glTexCoord2f(0, 1); glVertex2i(x1, y2);
  208.         glEnd();
  209.         xtraverts += 4;
  210.     }
  211.  
  212.     glDisable(GL_BLEND);
  213.     if(tex>=0) glDisable(GL_TEXTURE_2D);
  214.     glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
  215.     glBegin(GL_POLYGON);
  216.     glColor3f(0.6f, 0.6f, 0.6f); //glColor3d(0.2, 0.7, 0.4);
  217.     glVertex2i(x1, y1);
  218.     glVertex2i(x2, y1); 
  219.     glVertex2i(x2, y2);
  220.     glVertex2i(x1, y2);
  221.     glEnd();
  222.     glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
  223.     glEnable(GL_BLEND); 
  224.     glEnable(GL_TEXTURE_2D);
  225.     glDepthMask(GL_TRUE);
  226. }
  227.  
  228. VARP(fov, 90, 100, 120);
  229. VAR(fog, 64, 180, 1024);
  230. VAR(fogcolour, 0, 0x8099B3, 0xFFFFFF);
  231.  
  232. physent *camera1 = NULL;
  233.  
  234. void trypitch(int i) { camera1->pitch = (float)i; }
  235. COMMAND(trypitch, ARG_1INT);
  236.  
  237. void recomputecamera()
  238. {
  239.     if(demoplayback && demoplayer)
  240.     {
  241.         static physent democam; 
  242.         extern bool firstpersondemo;
  243.  
  244.         if(demoplayer == player1 && firstpersondemo)
  245.         {
  246.             democam = *(physent *)player1;
  247.         }
  248.         else
  249.         {
  250.             static playerent *lastplayer = NULL;
  251.             if(lastplayer != demoplayer)
  252.             {
  253.                 lastplayer = demoplayer;
  254.                 democam = *(physent *)demoplayer;
  255.                 democam.type = ENT_CAMERA;
  256.                 democam.reset();
  257.                 democam.roll = 0;
  258.                 democam.move = -1;
  259.                 camera1 = &democam;
  260.             }
  261.             democam.o = demoplayer->o;
  262.             democam.o.x -= (float)(cosf(RAD*(demoplayer->yaw-90)))*demoplayer->radius*1.5f;
  263.             democam.o.y -= (float)(sinf(RAD*(demoplayer->yaw-90)))*demoplayer->radius*1.5f;
  264.             democam.o.z += demoplayer->eyeheight/3.0f;
  265.             if(!demopaused) democam.yaw = demoplayer->yaw;
  266.         }        
  267.     }
  268.     else if(editmode || player1->state!=CS_DEAD)
  269.     {
  270.         camera1 = player1;
  271.     }
  272.     else
  273.     {
  274.         static physent deathcam;
  275.         if(camera1==&deathcam) return;
  276.         deathcam = *(physent *)player1;
  277.         deathcam.reset();
  278.         deathcam.type = ENT_CAMERA;
  279.         deathcam.roll = 0;
  280.         deathcam.move = -1;
  281.         camera1 = &deathcam;
  282.  
  283.         loopi(10) moveplayer(camera1, 10, true, 50);
  284.     }
  285. }
  286.  
  287. void transplayer()
  288. {
  289.     glLoadIdentity();
  290.    
  291.     glRotatef(camera1->roll, 0, 0, 1);
  292.     glRotatef(camera1->pitch, -1, 0, 0);
  293.     glRotatef(camera1->yaw, 0, 1, 0);
  294.  
  295.     // move from RH to Z-up LH quake style worldspace
  296.     glRotatef(-90, 1, 0, 0);
  297.     glScalef(1, -1, 1);
  298.  
  299.     glTranslatef(-camera1->o.x, -camera1->o.y, -camera1->o.z); 
  300. }
  301.  
  302. void genclipmatrix(float a, float b, float c, float d, GLfloat matrix[16])
  303. {
  304.     // transform the clip plane into camera space
  305.     GLdouble clip[4] = {a, b, c, d};
  306.     glClipPlane(GL_CLIP_PLANE0, clip);
  307.     glGetClipPlane(GL_CLIP_PLANE0, clip);
  308.  
  309.     glGetFloatv(GL_PROJECTION_MATRIX, matrix);
  310.     float x = ((clip[0]<0 ? -1 : (clip[0]>0 ? 1 : 0)) + matrix[8]) / matrix[0],
  311.           y = ((clip[1]<0 ? -1 : (clip[1]>0 ? 1 : 0)) + matrix[9]) / matrix[5],
  312.           w = (1 + matrix[10]) / matrix[14],
  313.           scale = 2 / (x*clip[0] + y*clip[1] - clip[2] + w*clip[3]);
  314.     matrix[2] = clip[0]*scale;
  315.     matrix[6] = clip[1]*scale;
  316.     matrix[10] = clip[2]*scale + 1.0f;
  317.     matrix[14] = clip[3]*scale;
  318. }
  319.  
  320. bool reflecting = false, refracting = false;
  321. GLuint reflecttex = 0, refracttex = 0;
  322. int reflectlastsize = 0;
  323.  
  324. VARP(reflectres, 6, 8, 10);
  325. VAR(reflectclip, 0, 3, 100);
  326. VARP(waterreflect, 0, 1, 1);
  327. VARP(waterrefract, 0, 0, 1);
  328.  
  329. void drawreflection(float hf, int w, int h, float changelod, bool refract)
  330. {
  331.     reflecting = true;
  332.     refracting = refract;
  333.  
  334.     int size = 1<<reflectres;
  335.     while(size > w || size > h) size /= 2;
  336.     if(size!=reflectlastsize)
  337.     {
  338.         if(reflecttex) glDeleteTextures(1, &reflecttex);
  339.         if(refracttex) glDeleteTextures(1, &refracttex);
  340.         reflecttex = refracttex = 0;
  341.     }
  342.     if(!reflecttex || (waterrefract && !refracttex))
  343.     {
  344.         if(!reflecttex)
  345.         {
  346.             glGenTextures(1, &reflecttex);
  347.             createtexture(reflecttex, size, size, NULL, 3, false, GL_RGB);
  348.         }
  349.         if(!refracttex)
  350.         {
  351.             glGenTextures(1, &refracttex);
  352.             createtexture(refracttex, size, size, NULL, 3, false, GL_RGB);
  353.         }
  354.         reflectlastsize = size;
  355.     }
  356.  
  357.     resetcubes();
  358.  
  359.     render_world(camera1->o.x, camera1->o.y, refract ? camera1->o.z : hf, changelod,
  360.             (int)camera1->yaw, (refract ? 1 : -1)*(int)camera1->pitch, (float)fov, size, size);
  361.  
  362.     setupstrips();
  363.  
  364.     if(!refract) glCullFace(GL_BACK);
  365.     glViewport(0, 0, size, size);
  366.     glClear(GL_DEPTH_BUFFER_BIT);
  367.  
  368.     glEnable(GL_TEXTURE_2D);
  369.  
  370.     transplayer();
  371.     if(!refract)
  372.     {
  373.         glTranslatef(0, 0, 2*hf);
  374.         glScalef(1, 1, -1);
  375.     }
  376.  
  377.     GLfloat clipmat[16];
  378.     genclipmatrix(0, 0, refract ? -1 : 1, refract ? 0.1f*reflectclip+hf : 0.1f*reflectclip-hf, clipmat);
  379.     glMatrixMode(GL_PROJECTION);
  380.     glPushMatrix();
  381.     glLoadMatrixf(clipmat);
  382.     glMatrixMode(GL_MODELVIEW);
  383.  
  384.     renderstripssky();
  385.  
  386.     glPushMatrix();
  387.     glLoadIdentity();
  388.     glRotatef(camera1->pitch, -1, 0, 0);
  389.     glRotatef(camera1->yaw,   0, 1, 0);
  390.     glRotatef(90, 1, 0, 0);   
  391.     if(!refract) glScalef(1, 1, -1);
  392.     glColor3f(1, 1, 1); 
  393.     glDisable(GL_FOG);
  394.     glDepthFunc(GL_GREATER);
  395.     draw_envbox(fog*4/3);
  396.     glDepthFunc(GL_LESS);
  397.     glEnable(GL_FOG);
  398.     glPopMatrix();
  399.  
  400.     setuptmu(0, "T * P x 2");
  401.  
  402.     renderstrips();
  403.     renderentities();
  404.     renderclients();
  405.  
  406.     resettmu(0);
  407.  
  408.     render_particles(0);
  409.  
  410.     if(refract) glLoadIdentity();
  411.     glMatrixMode(GL_PROJECTION);
  412.     extern int mtwater;
  413.     if(refract && (!mtwater || maxtmus<2))
  414.     {
  415.         glLoadIdentity();
  416.         glOrtho(0, 1, 0, 1, -1, 1);
  417.         glDisable(GL_TEXTURE_2D);
  418.         glDisable(GL_DEPTH_TEST);
  419.         glEnable(GL_BLEND);
  420.         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  421.         glColor4ubv(hdr.watercolor);
  422.         glBegin(GL_QUADS);
  423.         glVertex2i(0, 1);
  424.         glVertex2i(1, 1);
  425.         glVertex2i(1, 0);
  426.         glVertex2i(0, 0);
  427.         glEnd();
  428.         glDisable(GL_BLEND);
  429.         glEnable(GL_TEXTURE_2D);
  430.         glEnable(GL_DEPTH_TEST);
  431.     }
  432.     glPopMatrix();
  433.     glMatrixMode(GL_MODELVIEW);
  434.  
  435.     if(!refract) glCullFace(GL_FRONT);
  436.     glViewport(0, 0, w, h);
  437.  
  438.     glBindTexture(GL_TEXTURE_2D, refract ? refracttex : reflecttex);
  439.     glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, size, size);
  440.  
  441.     glDisable(GL_TEXTURE_2D);
  442.  
  443.     reflecting = refracting = false;
  444. }
  445.  
  446. bool minimap = false, minimapdirty = true;
  447. int minimaplastsize = 0;
  448. GLuint minimaptex = 0;
  449.  
  450. void clearminimap()
  451. {
  452.     minimapdirty = true;
  453. }
  454.  
  455. COMMAND(clearminimap, ARG_NONE);
  456. VARFP(minimapres, 7, 9, 10, clearminimap());
  457.  
  458. void drawminimap(int w, int h)
  459. {
  460.     if(!minimapdirty) return;
  461.  
  462.     int size = 1<<minimapres;
  463.     while(size > w || size > h) size /= 2;
  464.     if(size!=minimaplastsize)
  465.     {
  466.         glDeleteTextures(1, &minimaptex);
  467.         minimaptex = 0;
  468.     }
  469.     if(!minimaptex)
  470.     {
  471.         glGenTextures(1, &minimaptex);
  472.         createtexture(minimaptex, size, size, NULL, 3, false, GL_RGB);
  473.         minimaplastsize = size;
  474.     }
  475.  
  476.     minimap = true;
  477.  
  478.     physent minicam;
  479.     camera1 = &minicam;
  480.     camera1->o.x = camera1->o.y = ssize/2;
  481.     camera1->o.z = 128;
  482.     camera1->pitch = -90;
  483.     camera1->yaw = 0;
  484.  
  485.     glViewport(0, 0, size, size);
  486.     glClearDepth(0.0);
  487.     glClearColor(0, 0, 0, 1);
  488.     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  489.  
  490.     glMatrixMode(GL_PROJECTION);
  491.     glLoadIdentity();
  492.     glOrtho(-ssize/2, ssize/2, -ssize/2, ssize/2, 0, 256);
  493.     glScalef(1, -1, 1);
  494.     glMatrixMode(GL_MODELVIEW);
  495.  
  496.     glCullFace(GL_BACK);
  497.     glDisable(GL_FOG);
  498.     glEnable(GL_TEXTURE_2D);
  499.    
  500.     transplayer();
  501.  
  502.     resetcubes();
  503.  
  504.     render_world(camera1->o.x, camera1->o.y, camera1->o.z, 1.0f,
  505.             (int)camera1->yaw, (int)camera1->pitch, 90.0f, size, size);
  506.  
  507.     setupstrips();
  508.  
  509.     setuptmu(0, "T * P x 2");
  510.     glDepthFunc(GL_ALWAYS);
  511.     renderstrips();
  512.     glDepthFunc(GL_LESS);
  513.     renderentities();
  514.     resettmu(0);
  515.  
  516.     float hf = hdr.waterlevel-0.3f;
  517.     renderwater(hf, 0, 0);
  518.  
  519.     minimap = false;
  520.  
  521.     glBindTexture(GL_TEXTURE_2D, minimaptex);
  522.     glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, size, size);
  523.     minimapdirty = false;
  524.  
  525.     glCullFace(GL_FRONT);
  526.     glEnable(GL_FOG);
  527.     glDisable(GL_TEXTURE_2D);
  528.  
  529.     glViewport(0, 0, w, h);
  530.     glClearDepth(1.0);
  531. }
  532.  
  533. int xtraverts;
  534.  
  535. void drawhudgun(int w, int h, float aspect, int farplane)
  536. {
  537.     if(scoped && player1->gunselect==GUN_SNIPER) return;
  538.     
  539.     glMatrixMode(GL_PROJECTION);
  540.     glLoadIdentity();
  541.     gluPerspective((float)100.0f*h/w, aspect, 0.3f, farplane); // fov fixed at 100┬░
  542.     glMatrixMode(GL_MODELVIEW);
  543.  
  544.     if(player1->state!=CS_DEAD && (!demoplayback || localdemoplayer1st())) renderhudgun();
  545.     rendermenumdl();
  546.  
  547.     glMatrixMode(GL_PROJECTION);
  548.     glLoadIdentity();
  549.     gluPerspective((float)fov*h/w, aspect, 0.15f, farplane);
  550.     glMatrixMode(GL_MODELVIEW);
  551. }
  552.  
  553. bool outsidemap(physent *pl)
  554. {
  555.     if(pl->o.x < 0 || pl->o.x >= ssize || pl->o.y <0 || pl->o.y > ssize) return true;
  556.     sqr *s = S((int)pl->o.x, (int)pl->o.y);
  557.     return SOLID(s)
  558.         || pl->o.z < s->floor - (s->type==FHF ? s->vdelta/4 : 0)
  559.         || pl->o.z > s->ceil  + (s->type==CHF ? s->vdelta/4 : 0);
  560. }
  561.  
  562. float cursordepth = 0.9f;
  563. GLint viewport[4];
  564. GLdouble mm[16], pm[16];
  565. vec worldpos, camup, camright;
  566.  
  567. void readmatrices()
  568. {
  569.     glGetIntegerv(GL_VIEWPORT, viewport);
  570.     glGetDoublev(GL_MODELVIEW_MATRIX, mm);
  571.     glGetDoublev(GL_PROJECTION_MATRIX, pm);
  572.     camright = vec(float(mm[0]), float(mm[4]), float(mm[8]));
  573.     camup = vec(float(mm[1]), float(mm[5]), float(mm[9]));
  574. }
  575.  
  576. // stupid function to cater for stupid ATI linux drivers that return incorrect depth values
  577.  
  578. float depthcorrect(float d)
  579. {
  580.     return (d<=1/256.0f) ? d*256 : d;
  581. }
  582.  
  583. // find out the 3d target of the crosshair in the world easily and very acurately.
  584. // sadly many very old cards and drivers appear to fuck up on glReadPixels() and give false
  585. // coordinates, making shooting and such impossible.
  586. // also hits map entities which is unwanted.
  587. // could be replaced by a more acurate version of monster.cpp los() if needed
  588.  
  589. void readdepth(int w, int h, vec &pos)
  590. {
  591.     glReadPixels(w/2, h/2, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &cursordepth);
  592.     double worldx = 0, worldy = 0, worldz = 0;
  593.     gluUnProject(w/2, h/2, depthcorrect(cursordepth), mm, pm, viewport, &worldx, &worldy, &worldz);
  594.     pos.x = (float)worldx;
  595.     pos.y = (float)worldy;
  596.     pos.z = (float)worldz;
  597. }
  598.  
  599. void gl_drawframe(int w, int h, float changelod, float curfps)
  600. {
  601.     drawminimap(w, h);
  602.  
  603.     recomputecamera();
  604.  
  605.     float hf = hdr.waterlevel-0.3f;
  606.     float fovy = (float)fov*h/w;
  607.     float aspect = w/(float)h;
  608.     bool underwater = camera1->o.z<hf;
  609.    
  610.     glFogi(GL_FOG_START, (fog+64)/8);
  611.     glFogi(GL_FOG_END, fog);
  612.     float fogc[4] = { (fogcolour>>16)/256.0f, ((fogcolour>>8)&255)/256.0f, (fogcolour&255)/256.0f, 1.0f };
  613.     glFogfv(GL_FOG_COLOR, fogc);
  614.     glClearColor(fogc[0], fogc[1], fogc[2], 1.0f);
  615.  
  616.     glMatrixMode(GL_PROJECTION);
  617.     glLoadIdentity();
  618.     int farplane = fog*5/2;
  619.     gluPerspective(fovy, aspect, 0.15f, farplane);
  620.     glMatrixMode(GL_MODELVIEW);
  621.  
  622.     if(underwater)
  623.     {
  624.         fovy += sinf(lastmillis/1000.0f)*2.0f;
  625.         aspect += sinf(lastmillis/1000.0f+PI)*0.1f;
  626.         float wfogc[4] = { hdr.watercolor[0]/255.0f, hdr.watercolor[1]/255.0f, hdr.watercolor[2]/255.0f, 1.0f };
  627.         glFogfv(GL_FOG_COLOR, wfogc);
  628.         glFogi(GL_FOG_START, 0);
  629.         glFogi(GL_FOG_END, (fog+96)/8);
  630.     }
  631.     else if(waterreflect)
  632.     {
  633.         extern int wx1;
  634.         if(wx1>=0) 
  635.         {
  636.             drawreflection(hf, w, h, changelod, false);
  637.             if(waterrefract) drawreflection(hf, w, h, changelod, true);
  638.         }
  639.     }
  640.     
  641.     glClear((outsidemap(camera1) ? GL_COLOR_BUFFER_BIT : 0) | GL_DEPTH_BUFFER_BIT);
  642.  
  643.     transplayer();
  644.  
  645.     glEnable(GL_TEXTURE_2D);
  646.     
  647.     resetcubes();
  648.             
  649.     render_world(camera1->o.x, camera1->o.y, camera1->o.z, changelod,
  650.             (int)camera1->yaw, (int)camera1->pitch, (float)fov, w, h);
  651.  
  652.     setupstrips();
  653.  
  654.     renderstripssky();
  655.  
  656.     glLoadIdentity();
  657.     glRotatef(camera1->pitch, -1, 0, 0);
  658.     glRotatef(camera1->yaw,   0, 1, 0);
  659.     glRotatef(90, 1, 0, 0);
  660.     glColor3f(1, 1, 1);
  661.     glDisable(GL_FOG);
  662.     glDepthFunc(GL_GREATER);
  663.     draw_envbox(fog*4/3);
  664.     glDepthFunc(GL_LESS);
  665.     glEnable(GL_FOG);
  666.  
  667.     transplayer();
  668.  
  669.     setuptmu(0, "T * P x 2");
  670.     
  671.     renderstrips();
  672.  
  673.     xtraverts = 0;
  674.  
  675.     renderentities();
  676.  
  677.     readmatrices();
  678.     readdepth(w, h, worldpos);
  679.  
  680.     renderclients();
  681.  
  682.     if(player1->state==CS_ALIVE) readdepth(w, h, hitpos);
  683.  
  684.     renderbounceents();
  685.     
  686.     // Added by Rick: Need todo here because of drawing the waypoints
  687.     glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
  688.     WaypointClass.Think();
  689.     glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
  690.     // end add
  691.     
  692.     drawhudgun(w, h, aspect, farplane);
  693.  
  694.     resettmu(0);
  695.  
  696.     render_particles(curtime);
  697.  
  698.     glDisable(GL_CULL_FACE);
  699.     int nquads = renderwater(hf, !waterreflect || underwater ? 0 : reflecttex, !waterreflect || !waterrefract || underwater ? 0 : refracttex);
  700.  
  701.     glDisable(GL_FOG);
  702.     glDisable(GL_TEXTURE_2D);
  703.  
  704.     if(editmode)
  705.     {
  706.         if(cursordepth==1.0f) worldpos = camera1->o;
  707.         glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
  708.         cursorupdate();
  709.         glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
  710.     }
  711.  
  712.     extern vector<vertex> verts;
  713.     gl_drawhud(w, h, (int)curfps, nquads, verts.length(), underwater);
  714.  
  715.     glEnable(GL_CULL_FACE);
  716.     glEnable(GL_FOG);
  717. }
  718.  
  719.