1 //-----------------------------------------------------------------------------
2 // Render
3 //-----------------------------------------------------------------------------
4 
5 #include "render.h"
6 #include "commands.h"
7 #include "console.h"
8 #include "logfile.h"
9 #include "overlay.h"
10 #include "camera.h"
11 #include "client.h"
12 #include "timer.h"
13 #include "vars.h"
14 #include "math.h"
15 #include "surfaceflags.h"
16 #include "mem.h"
17 #include "system.h"
18 #include <assert.h>
19 
20 #include "glsetup/glutils.h"
21 #ifdef WIN32
22   #include "glsetup/glext.h"
23 #else
24   #define GLX_GLXEXT_LEGACY
25   #include <GL/glx.h>
26   #include <GL/glext.h>
27 #endif
28 
29 PFNGLLOCKARRAYSEXTPROC            glLockArraysEXT;
30 PFNGLUNLOCKARRAYSEXTPROC          glUnlockArraysEXT;
31 
32 #ifdef WIN32
33   PFNGLACTIVETEXTUREARBPROC       glActiveTextureARB;
34   PFNGLCLIENTACTIVETEXTUREARBPROC     glClientActiveTextureARB;
35   #define lglGetProcAddress(p)      wglGetProcAddress(p)
36 
37   // size of float may change from one platform to one other
38   #define XYZ_OFFSET            16    // 4 * sizeof(float)
39 #else
40   #define lglGetProcAddress(p)    glXGetProcAddressARB((byte*) p);
41 
42   // size of float may change from one platform to one other
43   #define XYZ_OFFSET            16    // 4 * sizeof(float)
44 #endif
45 
46 Var gl_vendor("gl_vendor", "", VF_SYSTEM);
47 Var gl_renderer("gl_renderer", "", VF_SYSTEM);
48 Var gl_version("gl_version", "", VF_SYSTEM);
49 Var gl_extensions("gl_extensions", "", VF_SYSTEM);
50 Var gl_maxTextureSize("gl_maxTextureSize", 0, VF_SYSTEM);
51 Var gl_maxTextureUnits("gl_maxTextureUnits", 0, VF_SYSTEM);
52 Var r_ext_compiledVertexArray("r_ext_compiled_vertex_array", 0, VF_SYSTEM);
53 Var r_ext_multitexture("r_ext_multitexture", 0, VF_SYSTEM);
54 Var r_ext_texture_edge_clamp("r_ext_texture_edge_clamp", 0, VF_SYSTEM);
55 Var r_usedTextureUnits("r_usedTextureUnits", 0, VF_SYSTEM);
56 Var r_vertexLight("r_vertexLight", 0, VF_PERSISTENT);
57 Var r_texturebits("r_texturebits", 0);
58 Var r_clear("r_clear", 0, VF_PERSISTENT);
59 Var r_filter("r_filter", 1, VF_PERSISTENT);
60 Var r_quality("r_quality", 2, VF_PERSISTENT | VF_LATCH);
61 Var r_picmip("r_picmip", 0, VF_PERSISTENT | VF_LATCH);
62 Var gl_dither("gl_dither", 1, VF_PERSISTENT);
63 Var v_overbrightbits("v_overbrightbits", 3, VF_LATCH);
64 Var v_gamma("v_gamma", 1.3375f, VF_PERSISTENT | VF_LATCH | VF_SYSTEM);
65 Var r_nolightmap("r_nolightmap", 0);
66 Var r_noshader("r_noshader", 0);
67 Var r_novertexcolor("r_novertexcolor", 0);
68 Var r_nocull("r_nocull", 0);
69 Var r_nodeform("r_nodeform", 0);
70 Var r_nofog("r_nofog", 0);
71 Var v_fullscreen("v_fullscreen", 0, VF_PERSISTENT | VF_LATCH | VF_SYSTEM);
72 Var v_colorBits("v_colorBits", 32, VF_PERSISTENT | VF_LATCH | VF_SYSTEM);
73 Var v_hz("v_hz", 60, VF_PERSISTENT | VF_LATCH | VF_SYSTEM);
74 Var v_height("v_height", 480, VF_PERSISTENT | VF_LATCH | VF_SYSTEM);
75 Var v_width("v_width", 640, VF_PERSISTENT | VF_LATCH | VF_SYSTEM);
76 Var v_left("v_left", 0, VF_PERSISTENT | VF_LATCH | VF_SYSTEM);
77 Var v_top("v_top", 0, VF_PERSISTENT | VF_LATCH | VF_SYSTEM);
78 Var v_aspect("v_aspect", (float)4/3, VF_PERSISTENT | VF_LATCH | VF_SYSTEM);
79 Var v_depthBits("v_depthBits", 32, VF_PERSISTENT | VF_LATCH | VF_SYSTEM);
80 Var v_stencilBits("v_stencilBits", 0, VF_PERSISTENT | VF_LATCH | VF_SYSTEM);
81 Var v_lightness("v_lightness", 0.0f, VF_LATCH);
82 Var v_mode("v_mode", 0, VF_PERSISTENT | VF_LATCH | VF_SYSTEM);
83 Var r_subdivision("r_subdivision", 2, VF_LATCH | VF_PERSISTENT);
84 Var r_curvefactor("r_curvefactor", 6, VF_LATCH | VF_PERSISTENT);
85 Var wnd_handle("wnd_handle", 0);
86 Var sys_buffersize("sys_buffersize", 0, VF_SYSTEM); // size of dynamic buffer
87 Var sys_maxelems("sys_maxelems", 0, VF_SYSTEM);   // number of elements
88 Var v_camnear("v_camnear", 4);
89 Var v_camfar("v_camfar", 50000);
90 
cmd_setclearcolor(int argc,char * argv[])91 void cmd_setclearcolor(int argc, char *argv[])
92 {
93   if (argc > 4)
94   {
95     glClearColor((float) atof(argv[1]), (float) atof(argv[2]), (float) atof(argv[3]), (float) atof(argv[4]));
96   }
97   else gConsole->Insertln("usage: %s <value> <value> <value> <value>", argv[0]);
98 }
99 
100 Shader *  State::curr_shader = NULL;
101 Shader *  State::curr_effect = NULL;
102 int       State::curr_depthFunc = GL_LEQUAL;
103 int       State::curr_depthWrite = true;
104 int       State::curr_blenddst = GL_ONE;
105 int       State::curr_blendsrc = GL_ZERO;
106 int       State::curr_culling = CULL_NONE;
107 int       State::curr_alphaFunc;
108 int       State::curr_polygonmode = GL_FILL;
109 int       State::skipping = 0;
110 int       State::curr_texture[];
111 int       State::curr_lightmap = ~0;
112 int       State::pass = 0;
113 int       State::last_tcgen[MAX_TEXTURE_UNITS];
114 
115 GLboolean lighting, texture, depthtest;
116 int texture_unit;
117 
118 // buffer states
119 enum
120 {
121   BF_EMPTY,
122   BF_FILLING,
123   BF_LOCKED
124 };
125 
126 // Constructor
Render()127 Render::Render()
128 {
129   ready                 = 0;
130 
131   fogtexture.mem        = NULL;
132 
133   swapbuffersfunc       = NULL;
134 
135   gridpass              = 0;
136 
137   for (int i = 0; i < MAX_TEXTURE_UNITS; ++i)
138   {
139     buffer[i].st = NULL;
140     buffer[i].c = NULL;
141   }
142   input.c             = NULL;
143   input.elems         = NULL;
144   input.fog           = NULL;
145   input.lm_st         = NULL;
146   input.normal        = NULL;
147   input.numelems      = 0;
148   input.numverts      = 0;
149   input.tex_st        = NULL;
150   input.xyz           = NULL;
151 
152   current_camera      = NULL;
153 
154   // Registering variables
155   gVars->RegisterVar(gl_vendor);
156   gVars->RegisterVar(gl_renderer);
157   gVars->RegisterVar(gl_version);
158   gVars->RegisterVar(gl_extensions);
159   gVars->RegisterVar(gl_maxTextureSize);
160   gVars->RegisterVar(gl_maxTextureUnits);
161   gVars->RegisterVar(gl_dither);
162   gVars->RegisterVar(r_ext_compiledVertexArray);
163   gVars->RegisterVar(r_ext_multitexture);
164   gVars->RegisterVar(r_ext_texture_edge_clamp);
165   gVars->RegisterVar(r_usedTextureUnits);
166   gVars->RegisterVar(r_vertexLight);
167   gVars->RegisterVar(r_texturebits);
168   gVars->RegisterVar(r_quality);
169   gVars->RegisterVar(r_picmip);
170   gVars->RegisterVar(r_nolightmap);
171   gVars->RegisterVar(r_noshader);
172   gVars->RegisterVar(r_novertexcolor);
173   gVars->RegisterVar(r_filter);
174   gVars->RegisterVar(r_nocull);
175   gVars->RegisterVar(r_nofog);
176   gVars->RegisterVar(v_depthBits);
177   gVars->RegisterVar(v_stencilBits);
178   gVars->RegisterVar(v_mode);
179   gVars->RegisterVar(wnd_handle);
180   gVars->RegisterVar(v_overbrightbits);
181   gVars->RegisterVar(v_gamma);
182   gVars->RegisterVar(v_lightness);
183   gVars->RegisterVar(r_nodeform);
184   gVars->RegisterVar(r_clear);
185   gVars->RegisterVar(v_aspect);
186   gVars->RegisterVar(v_fullscreen);
187   gVars->RegisterVar(v_hz);
188   gVars->RegisterVar(v_colorBits);
189   gVars->RegisterVar(v_height);
190   gVars->RegisterVar(v_width);
191   gVars->RegisterVar(v_top);
192   gVars->RegisterVar(v_left);
193   gVars->RegisterVar(r_subdivision);
194   gVars->RegisterVar(r_curvefactor);
195   gVars->RegisterVar(sys_buffersize);
196   gVars->RegisterVar(sys_maxelems);
197   gVars->RegisterVar(v_camnear);
198   gVars->RegisterVar(v_camfar);
199 
200   gCommands->AddCommand("setclearcolor", cmd_setclearcolor, "Define the clear color (need to be enabled with r_clear variable).");
201 }
202 
203 // Destructor
~Render(void)204 Render::~Render(void)
205 {
206   for (int i = 0; i < MAX_TEXTURE_UNITS; ++i)
207   {
208     if (buffer[i].st) cake_free(buffer[i].st);
209     if (buffer[i].c) cake_free(buffer[i].c);
210   }
211   if (input.xyz)    cake_free(input.xyz); input.xyz = NULL;
212   if (input.tex_st) cake_free(input.tex_st); input.tex_st = NULL;
213   if (input.lm_st)  cake_free(input.lm_st); input.lm_st = NULL;
214   if (input.normal) cake_free(input.normal); input.normal = NULL;
215   if (input.c)      cake_free(input.c); input.c = NULL;
216   if (input.fog)    cake_free(input.fog); input.fog = NULL;
217   if (input.elems)  cake_free(input.elems); input.elems = NULL;
218 
219   sys_buffersize = 0;
220   sys_maxelems = 0;
221 
222   if (fogtexture.mem) delete [] fogtexture.mem;
223   fogtexture.mem = NULL;
224 
225   // Unregister variables
226   gVars->UnregisterVar(gl_vendor);
227   gVars->UnregisterVar(gl_renderer);
228   gVars->UnregisterVar(gl_version);
229   gVars->UnregisterVar(gl_extensions);
230   gVars->UnregisterVar(gl_maxTextureSize);
231   gVars->UnregisterVar(gl_maxTextureUnits);
232   gVars->UnregisterVar(gl_dither);
233   gVars->UnregisterVar(r_ext_compiledVertexArray);
234   gVars->UnregisterVar(r_ext_multitexture);
235   gVars->UnregisterVar(r_ext_texture_edge_clamp);
236   gVars->UnregisterVar(r_usedTextureUnits);
237   gVars->UnregisterVar(r_vertexLight);
238   gVars->UnregisterVar(r_texturebits);
239   gVars->UnregisterVar(r_clear);
240   gVars->UnregisterVar(r_quality);
241   gVars->UnregisterVar(r_picmip);
242   gVars->UnregisterVar(r_nolightmap);
243   gVars->UnregisterVar(r_noshader);
244   gVars->UnregisterVar(r_novertexcolor);
245   gVars->UnregisterVar(r_filter);
246   gVars->UnregisterVar(r_nocull);
247   gVars->UnregisterVar(r_nofog);
248   gVars->UnregisterVar(v_fullscreen);
249   gVars->UnregisterVar(v_width);
250   gVars->UnregisterVar(v_height);
251   gVars->UnregisterVar(v_top);
252   gVars->UnregisterVar(v_left);
253   gVars->UnregisterVar(v_aspect);
254   gVars->UnregisterVar(v_colorBits);
255   gVars->UnregisterVar(v_hz);
256   gVars->UnregisterVar(v_depthBits);
257   gVars->UnregisterVar(v_stencilBits);
258   gVars->UnregisterVar(v_gamma);
259   gVars->UnregisterVar(v_mode);
260   gVars->UnregisterVar(wnd_handle);
261   gVars->UnregisterVar(v_overbrightbits);
262   gVars->UnregisterVar(v_lightness);
263   gVars->UnregisterVar(r_nodeform);
264   gVars->UnregisterVar(r_subdivision);
265   gVars->UnregisterVar(r_curvefactor);
266   gVars->UnregisterVar(sys_buffersize);
267   gVars->UnregisterVar(sys_maxelems);
268   gVars->UnregisterVar(v_camnear);
269   gVars->UnregisterVar(v_camfar);
270   gCommands->RemoveCommand("setclearcolor");
271 }
272 
273 // Initialize the render
Init(swapcommand_t func)274 int Render::Init(swapcommand_t func)
275 {
276   // Initializing driver
277   int temp;
278 
279   swapbuffersfunc = func;
280 
281   gConsole->Insertln("<br/><b>^6----- Initializing driver -------------------------------------</b>");
282 
283   // Creates buffers
284   gConsole->Insertln("<b>Creating buffers...</b>");
285   IncreaseBuffer(BUFFER_SIZE_BLOC<<3);
286   IncreaseElems(ELEMS_BLOC<<2);
287   //IncreaseBuffer(1000000);
288   //IncreaseElems(4000000);
289 
290   // get driver infos
291   gVars->SetKeyValue("gl_vendor",     (char*)glGetString(GL_VENDOR));
292   gVars->SetKeyValue("gl_renderer",   (char*)glGetString(GL_RENDERER));
293   gVars->SetKeyValue("gl_version",    (char*)glGetString(GL_VERSION));
294   gVars->SetKeyValue("gl_extensions", (char*)glGetString(GL_EXTENSIONS));
295 
296   // Check float size
297   if (4*sizeof(float) != XYZ_OFFSET)
298     ThrowException(DEFAULT_EXCEPTION, "gRender->Init - float should be 4 bytes wide");
299 
300   // Report some infos
301   glGetIntegerv(GL_MAX_TEXTURE_SIZE, &temp);
302   CheckGLError(5);
303   gl_maxTextureSize = temp;
304 
305   // Initialize extensions:
306 
307   // compiled vertex array
308   if (CheckExtension("GL_EXT_compiled_vertex_array"))
309   {
310     glLockArraysEXT = (PFNGLLOCKARRAYSEXTPROC) lglGetProcAddress("glLockArraysEXT");
311     glUnlockArraysEXT = (PFNGLUNLOCKARRAYSEXTPROC) lglGetProcAddress("glUnlockArraysEXT");
312     r_ext_compiledVertexArray = 1;
313     CheckGLError(2);
314   }
315   else
316   {
317     r_ext_compiledVertexArray = 0;
318     gConsole->Insertln("^1Compiled vertex array extension (GL_EXT_compiled_vertex_array) not supported");
319   }
320 
321   // multitexture
322   if (CheckExtension("GL_ARB_multitexture"))
323   {
324     r_ext_multitexture = 1;
325 
326     #ifdef WIN32
327       glActiveTextureARB    = (PFNGLACTIVETEXTUREARBPROC) lglGetProcAddress("glActiveTextureARB");
328       glClientActiveTextureARB= (PFNGLCLIENTACTIVETEXTUREARBPROC) lglGetProcAddress("glClientActiveTextureARB");
329     #endif
330     glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &temp);
331     gl_maxTextureUnits = temp;
332     r_usedTextureUnits = min(temp, MAX_TEXTURE_UNITS);
333     CheckGLError(3);
334   }
335   else
336   {
337     r_ext_multitexture = 0;
338     gl_maxTextureUnits = 1;
339     r_usedTextureUnits = 1;
340     gConsole->Insertln("^1ARB multitexture extension (GL_ARB_multitexture) not supported");
341   }
342 
343   // texture clamp
344   if (CheckExtension("EXT_texture_edge_clamp"))
345   {
346     r_ext_texture_edge_clamp = 1;
347   }
348   else
349   {
350     r_ext_texture_edge_clamp = 0;
351     gConsole->Insertln("^1Texture edge clamp extension (EXT_texture_edge_clamp) not supported");
352   }
353 
354   // Display OpenGL infos
355   gConsole->Insertln("<b>OpenGL Driver Infos :</b>");
356   gConsole->Insertln("\tgl_vendor :");      gConsole->Insertln("\t\t%s", gl_vendor.svalue);
357   gConsole->Insertln("\tgl_renderer :");    gConsole->Insertln("\t\t%s", gl_renderer.svalue);
358   gConsole->Insertln("\tgl_version :");     gConsole->Insertln("\t\t%s", gl_version.svalue);
359   gConsole->Insertln("\tgl_extensions :");
360 
361   char *exts = gl_extensions.svalue;
362   char buffer[4096] = {'\0'};
363   char tmp[2] = {'\0'};
364   int lexts = (int) strlen(exts);
365   for (int i = 0; i < lexts; ++i)
366   {
367     if (exts[i] == ' ' && i != lexts-1)
368     {
369       gConsole->Insertln("\t\t%s", buffer);
370       memset(buffer, '\0', 4096);
371     }
372     else
373     {
374       tmp[0] = exts[i]; tmp[1] = '\0';
375       strcat(buffer, tmp);
376     }
377   }
378   gConsole->Insertln("\t\t%s", buffer);
379   gConsole->Insertln("\tgl_max_texture_size : %s", gVars->StringForKey("gl_maxTextureSize"));
380   gConsole->Insertln("\tgl_max_texture_units : %s (used : %s)",
381   gVars->StringForKey("gl_maxTextureUnits"), gVars->StringForKey("r_usedTextureUnits"));
382 
383   // Generate fog map
384   CreateFogTexture(&fogtexture);
385   //WriteBitmapFile("fogtexture.bmp", FOG_TEXTURE_WIDTH, FOG_TEXTURE_HEIGHT, FOG_TEXTURE_BPP, fogtexture.mem);
386 
387   // Initialize state
388   State::SetInitialState(r_ext_multitexture.ivalue);
389 
390   //_controlfp(_PC_24, _MCW_PC);
391   state = BF_EMPTY;
392   input.numverts = 0;
393   input.numelems = 0;
394 
395   ready = 1;
396 
397   return 1;
398 }
399 
Shut(void)400 void Render::Shut(void)
401 {
402   ready = 0;
403 
404   State::setDepthWrite(GL_TRUE);                // must be true before clearing!
405   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
406   CheckGLError();
407 
408   /** @test order? */
409   //wglMakeCurrent(0,0);  // -> generate an opengl error (0x502)
410   //HGLRC app_rc = wglGetCurrentContext();
411   //wglDeleteContext(app_rc);
412   //CheckGLError(3);
413 }
414 
IncreaseBuffer(unsigned int newsize)415 void Render::IncreaseBuffer(unsigned int newsize)
416 {
417   if (newsize <= (unsigned) sys_buffersize.ivalue) return;
418 
419   int i;
420 
421   if (sys_buffersize.ivalue)
422   {
423     for (i = 0; i < MAX_TEXTURE_UNITS; ++i)
424     {
425       buffer[i].st = (float*)   cake_realloc(buffer[i].st, (newsize<<1)*sizeof(float), "gRender->IncreaseBuffer.buffer.st");
426       buffer[i].c  = (byte*)    cake_realloc(buffer[i].c,  (newsize<<2)*sizeof(byte), "gRender->IncreaseBuffer.buffer.c");
427     }
428     input.xyz    = (float*)     cake_realloc(input.xyz,    (newsize<<2)*sizeof(float), "gRender->IncreaseBuffer.xyz");
429     input.tex_st = (float*)     cake_realloc(input.tex_st, (newsize<<1)*sizeof(float), "gRender->IncreaseBuffer.tex_st");
430     input.lm_st  = (float*)     cake_realloc(input.lm_st,  (newsize<<1)*sizeof(float), "gRender->IncreaseBuffer.lm_st");
431     input.normal = (float*)     cake_realloc(input.normal, (newsize<<2)*sizeof(float), "gRender->IncreaseBuffer.normal");
432     input.c      = (byte*)      cake_realloc(input.c,      (newsize<<2)*sizeof(byte), "gRender->IncreaseBuffer.c");
433 #if MODIF_FOG
434     input.fog    = (cplane_t**) cake_realloc(input.fog,    newsize*sizeof(cplane_t*), "gRender->IncreaseBuffer.fog");
435 #else
436     input.fog    = (float*)     cake_realloc(input.fog,    5*newsize*sizeof(float), "gRender->IncreaseBuffer.fog");
437 #endif
438   }
439   else
440   {
441     for (i = 0; i < MAX_TEXTURE_UNITS; ++i)
442     {
443       buffer[i].st = (float*)   cake_malloc((newsize<<1)*sizeof(float), "gRender->IncreaseBuffer.buffer.st");
444       buffer[i].c  = (byte*)    cake_malloc((newsize<<2)*sizeof(byte), "gRender->IncreaseBuffer.buffer.c");
445     }
446     input.xyz    = (float*)     cake_malloc((newsize<<2)*sizeof(float), "gRender->IncreaseBuffer.xyz");
447     input.tex_st = (float*)     cake_malloc((newsize<<1)*sizeof(float), "gRender->IncreaseBuffer.tex_st");
448     input.lm_st  = (float*)     cake_malloc((newsize<<1)*sizeof(float), "gRender->IncreaseBuffer.lm_st");
449     input.normal = (float*)     cake_malloc((newsize<<2)*sizeof(float), "gRender->IncreaseBuffer.normal");
450     input.c      = (byte*)      cake_malloc((newsize<<2)*sizeof(byte), "gRender->IncreaseBuffer.c");
451 #if MODIF_FOG
452     input.fog    = (cplane_t**) cake_malloc(newsize*sizeof(cplane_t*), "gRender->IncreaseBuffer.fog");
453 #else
454     input.fog    = (float*)     cake_malloc(5*newsize*sizeof(float), "gRender->IncreaseBuffer.fog");
455 #endif
456   }
457 
458   sys_buffersize = (int) newsize;
459 
460   // Check for memory fails
461   bool failed = false;
462   for (i = 0; i < MAX_TEXTURE_UNITS; ++i)
463     if (!buffer[i].st || !buffer[i].c)
464     {
465       failed = true;
466       break;
467     }
468 
469   failed = (!failed && (!input.xyz || !input.tex_st || !input.lm_st || !input.normal || !input.c || !input.fog));
470 
471   if (failed)
472   {
473     if (gConsole) gConsole->Insertln("^1gRender->IncreaseBuffer: Cannot allocate required size");
474     else if (gLogFile) gLogFile->Insert("^1gRender->IncreaseBuffer: Cannot allocate required size\n");
475   }
476   else if (gLogFile) gLogFile->Insert("\tInput buffer increased to %d.\n", newsize);
477 }
478 
IncreaseElems(unsigned int newsize)479 void Render::IncreaseElems(unsigned int newsize)
480 {
481   if (newsize <= (unsigned) sys_maxelems.ivalue) return;
482 
483   if (sys_maxelems.ivalue)
484     input.elems = (unsigned int*) cake_realloc(input.elems, newsize*sizeof(unsigned int), "gRender->IncreaseElems.elems");
485   else
486     input.elems = (unsigned int*) cake_malloc(newsize*sizeof(unsigned int), "gRender->IncreaseElems.elems");
487 
488   sys_maxelems = (int) newsize;
489 
490   if (!input.elems)
491   {
492     if (gConsole) gConsole->Insertln("^1gRender->IncreaseElems: Cannot allocate required size");
493     else if (gLogFile) gLogFile->Insert("^1gRender->IncreaseElems: Cannot allocate required size\n");
494   }
495   else if (gLogFile) gLogFile->Insert("\tElems buffer increased to %d.\n", newsize);
496 }
497 
SetWindowSettings(GLsizei w,GLsizei h,GLint c,GLint f)498 void Render::SetWindowSettings(GLsizei w, GLsizei h, GLint c, GLint f)
499 {
500   if (w > 0) v_width = w;
501   if (h > 0) v_height = h;
502   if (c > 0) v_colorBits = c;
503   if (f > 0) v_hz = f;
504 
505   gConsole->Resize(v_width.ivalue - 2*gConsole->GetLeft(), (int) (v_height.ivalue/2));
506 }
507 
GetWidth(void)508 int Render::GetWidth(void)
509 {
510   return v_width.ivalue;
511 }
512 
GetHeight(void)513 int Render::GetHeight(void)
514 {
515   return v_height.ivalue;
516 }
517 
GetTop(void)518 int Render::GetTop(void)
519 {
520   return v_top.ivalue;
521 }
522 
GetLeft(void)523 int Render::GetLeft(void)
524 {
525   return v_left.ivalue;
526 }
527 
CreateFogTexture(texinfo * t)528 void Render::CreateFogTexture(texinfo *t)
529 {
530   t->num = -1;
531   t->width = FOG_TEXTURE_WIDTH;
532   t->height = FOG_TEXTURE_HEIGHT;
533   t->bpp = FOG_TEXTURE_BPP;
534   t->mem = new byte[FOG_TEXTURE_WIDTH*FOG_TEXTURE_HEIGHT*FOG_TEXTURE_BPP];
535 
536   float tw = 1.0f / ((float)t->width - 1.0f);
537   float th = 1.0f / ((float)t->height - 1.0f);
538   float tx = 0.0f;
539   float ty = 0.0f;
540   float a;
541   for (int y = 1; y < t->height; ++y, ty += th)
542   {
543     tx = 0.0f;
544     for (int x = 0; x < t->width; ++x, tx += tw)
545     {
546       //a = tx * 255.0f;  // LINEAR
547       // squared fog-thickness proportional to linear distance seems to be best looking
548       a = sqrtf(tx) * 255.0f;  //SQUARE
549       if (a > 255.0f) a = 255.0f;
550       for (int i = 0; i < t->bpp; ++i)
551         t->mem[(y*t->width+x)*t->bpp+i] = (byte) a;
552     }
553   }
554 
555   for (int x = 0; x < t->width*t->bpp; ++x)
556   {
557     t->mem[x] = 0;
558   }
559 
560   RegisterTexInfo(t, LF_NOMIPMAP|LF_NOPICMIP|LF_CLAMP);
561 }
562 
563 
564 //-----------------------------------------------------------------------------
565 // Drawing
566 //-----------------------------------------------------------------------------
567 
568 //  Begin Frame
BeginFrame(void)569 int Render::BeginFrame(void)
570 {
571   State::setDepthWrite(GL_TRUE);                // must be true before clearing!
572 
573   if (r_clear.ivalue)
574     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
575   else
576     glClear(GL_DEPTH_BUFFER_BIT);
577 
578   State::setPolygonMode(GL_FILL);
579 
580   glEnable(GL_TEXTURE_2D);
581 
582   CheckGLError(3);
583 
584   state = BF_EMPTY;
585 
586   Timer::Refresh();                 // update the timer for the new frame
587 
588   // initialize counters
589   num_tris = 0;
590   num_flush = 0;
591   num_verts = 0;
592   num_apicalls = 0;
593 
594   return 1;
595 }
596 
597 //  Ends Frame
EndFrame(void)598 int Render::EndFrame(void)
599 {
600   // Flush all the buffers
601   if (state != BF_EMPTY) Flush();
602 
603   return 1;
604 }
605 
606 // Determine if an extension is supported, must be called after a valid
607 // context has been created
CheckExtension(char * extName)608 bool Render::CheckExtension(char *extName)
609 {
610   char *extensions = (char *) glGetString(GL_EXTENSIONS);
611   CheckGLError();
612   if (strstr(extensions, extName)) return true;
613   return false;
614 }
615 
616 // Register Texinfo by loading the texture into video memory
RegisterTexInfo(texinfo * tex,int flags)617 int Render::RegisterTexInfo(texinfo *tex, int flags)
618 {
619   int picmip = (flags & LF_NOPICMIP)?0:r_picmip.ivalue;
620   if (picmip < 0) picmip = 0;
621   int newwidth = (1 << Log2(tex->width)) >> picmip;
622   int newheight = (1 << Log2(tex->height)) >> picmip;
623   if (newwidth <= 0) newwidth = 1;
624   if (newheight <= 0) newheight = 1;
625   int format, outformat;
626   float fform;
627   byte *mem = tex->mem;
628 
629   if (tex->num != ~0) return 1;   // FIXME: �1?
630 
631   switch (tex->bpp)
632   {
633     case 1:
634       format = GL_ALPHA;
635       outformat = GL_ALPHA;
636       break;
637     case 2:
638       format = GL_LUMINANCE_ALPHA;    // do I support that??
639       outformat = GL_LUMINANCE_ALPHA;
640       break;
641     case 3:
642       format = GL_RGB;
643       fform = r_texturebits.fvalue;
644       switch ((int) fform)
645       {
646         // FIXME: float to int conversion !!!
647         case 16:
648           outformat = GL_RGB5;
649           break;
650         case 32:
651           outformat = GL_RGB8;
652           break;
653         default:
654           outformat = GL_RGB;
655           break;
656       }
657       break;
658     case 4:
659       format = GL_RGBA;
660       fform = r_texturebits.fvalue;
661       switch ((int)fform)
662       {
663         // FIXME: float to int conversion !!!
664         case 16:
665           outformat = GL_RGBA4;
666           break;
667         case 32:
668           outformat = GL_RGBA8;
669           break;
670         default:
671           outformat = GL_RGBA;
672           break;
673       }
674       break;
675     default:
676       format = GL_RGB;
677       outformat = GL_RGB;
678       break;
679   }
680 
681   if (newheight > gl_maxTextureSize.ivalue) newheight = gl_maxTextureSize.ivalue;
682   if (newwidth > gl_maxTextureSize.ivalue) newwidth = gl_maxTextureSize.ivalue;
683 
684   if (tex->height != newheight || tex->width != newwidth)
685   {
686     mem = (byte *) cake_malloc(newheight*newwidth*tex->bpp, "gRender->RegisterTexInfo.mem");
687     ScaleImage(format, tex->width, tex->height, tex->mem, newwidth, newheight, mem);
688   }
689 
690   glGenTextures(1, (GLuint*) &tex->num);
691   glBindTexture(GL_TEXTURE_2D, tex->num);
692   CheckGLError(2);
693 
694   if (flags & LF_NOMIPMAP)
695   {
696     glTexImage2D(GL_TEXTURE_2D, 0, outformat, newwidth, newheight, 0, format, GL_UNSIGNED_BYTE, mem);
697     CheckGLError();
698   }
699   else
700     BuildMipmaps(outformat, newwidth, newheight, format, mem);
701 
702   if (flags & LF_CLAMP)
703   {
704     if (r_ext_texture_edge_clamp.ivalue)
705     {
706       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
707       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
708     }
709     else
710     {
711       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
712       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
713     }
714   }
715   else
716   {
717     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
718     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
719   }
720   CheckGLError(2);
721 
722   //float filter = Import.cvars->ValueForKey("gl_filter");
723 
724   if (r_filter.ivalue == 0)
725   {
726     // nearest
727     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
728     if (flags & LF_NOMIPMAP)
729       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
730     else
731       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
732     CheckGLError(2);
733   }
734   else if (r_filter.ivalue == 2)
735   {
736     // trilinear
737     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
738     if (flags & LF_NOMIPMAP)
739       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
740     else
741       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
742     CheckGLError(2);
743   }
744   else /*if (r_filter.ivalue == 1)*/
745   {
746     // bilinear
747     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
748     if (flags & LF_NOMIPMAP)
749       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
750     else
751       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
752     CheckGLError(2);
753   }
754 
755   glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); CheckGLError();
756   //glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); CheckGLError();
757 
758   if (mem != tex->mem) cake_free(mem);
759   return 1;
760 }
761 
762 // Deletes texture memory
UnregisterTexInfo(texinfo * tex)763 void Render::UnregisterTexInfo(texinfo *tex)
764 {
765   glDeleteTextures(1, (GLuint*) &tex->num);
766   CheckGLError();
767 }
768 
769 // Sets the given render state
SetRenderState(Shader * s,int lightmap,Shader * e)770 void Render::SetRenderState(Shader *s, int lightmap, Shader *e)
771 {
772   // FIXME: If State::curr_shader is NULL, State::skipping will be true. Then this
773   // will have as consequence that Flushing will be aborted and reported to next
774   // time where State::curr_shader is not NULL and faces that are already in input
775   // struct may have wrong shader when rendered. So what is better ? Render them
776   // with wrong shader or not render them at all ?
777   if (state != BF_EMPTY) Flush();
778 
779   State::curr_shader = s;
780 
781   if (r_nolightmap.ivalue) State::curr_lightmap = ~0;
782   else State::curr_lightmap = lightmap;
783 
784   State::curr_effect = e;
785 
786   State::skipping = (!s || s->surface_flags & SURF_SKIP || s->surface_flags & SURF_NODRAW);
787 }
788 
InitializeViewPort(void)789 void Render::InitializeViewPort(void)
790 {
791   if (state != BF_EMPTY) Flush();
792 
793   glViewport(0, 0, v_width.ivalue, v_height.ivalue);
794   glScissor(0, 0, v_width.ivalue, v_height.ivalue);
795 
796   glMatrixMode(GL_MODELVIEW);
797   glLoadIdentity();
798   glMatrixMode(GL_PROJECTION);
799   glLoadIdentity();
800 
801   glOrtho(0, v_width.ivalue, v_height.ivalue, 0, 0.0f, 1.0f);
802 
803   CheckGLError(7);
804 
805   // Initializing state
806   State::setBlend(GL_ONE, GL_ZERO);
807   State::setAlphaFunc(GL_ALWAYS, 0);
808   State::setDepthFunc(GL_LEQUAL);
809   State::setDepthWrite(GL_TRUE);
810   State::setCulling(CULL_NONE);
811 }
812 
813 // Write vertexes in the input, Flush when full
PushTriangles(Surface * surf,int * visible)814 void Render::PushTriangles(Surface *surf, int *visible)
815 {
816   if (!surf) return;
817   if (State::skipping) return;
818 
819   int level = surf->currentlevel;
820   if (level < 0 || level >= surf->levels)
821   {
822     gConsole->Insertln("^1ERROR: Invalid surface level !");
823     return;
824   }
825   if (surf->numelems[level] == 0 || surf->numverts[level] == 0) return;
826 
827   // Force flushing before resizing buffer to avoid problems
828   if (input.numverts + surf->numverts[level] >= sys_buffersize.ivalue ||
829 	  input.numelems + surf->numelems[level] >= sys_maxelems.ivalue)
830 	ForceFlush();
831 
832   // Check buffers overflow
833   while (input.numverts + surf->numverts[level] >= sys_buffersize.ivalue)
834     IncreaseBuffer(input.numverts + surf->numverts[level] + BUFFER_SIZE_BLOC);
835 
836   while (input.numelems + surf->numelems[level] >= sys_maxelems.ivalue)
837     IncreaseElems(input.numelems + surf->numelems[level] + ELEMS_BLOC);
838 
839   float * xyz;
840   float * st;
841   vertex_t * v;
842   int i;
843 
844   state = BF_FILLING; // filling the buffer
845 
846   // adding elements to input data
847   if (visible)
848   {
849     for (i = 0; i < surf->numelems[level]; ++i)
850       if (visible[i])
851         input.elems[input.numelems++] = input.numverts + surf->firstelem[level][i];
852   }
853   else
854   {
855     for (i = 0; i < surf->numelems[level]; ++i)
856       input.elems[input.numelems++] = input.numverts + surf->firstelem[level][i];
857   }
858 
859   // vertices
860   xyz = &input.xyz[input.numverts<<2];
861   v = surf->firstvert[level], i = surf->numverts[level];
862   do
863   {
864     VectorCopy(v->v_point, xyz);
865     xyz += 4; // 4 coordinates for a vertex
866     ++v;
867   } while (--i);
868 
869   // texture coordinates
870   st = &input.tex_st[input.numverts<<1];
871   v = surf->firstvert[level], i = surf->numverts[level];
872   do
873   {
874     TexcoordCopy(v->tex_st, st);
875     st += 2;  // 2 coordinates s & t
876     ++v;
877   } while (--i);
878 
879   if (State::curr_shader->flags & SF_HASLIGHTMAP)
880   {
881     st = &input.lm_st[input.numverts<<1];
882     v = surf->firstvert[level], i = surf->numverts[level];
883     do
884     {
885       TexcoordCopy(v->lm_st, st);
886       st += 2;
887       ++v;
888     } while (--i);
889   }
890 
891   if (State::curr_shader->flags & SF_USENORMALS)
892   {
893     float *n = &input.normal[input.numverts<<2];
894     v = surf->firstvert[level], i = surf->numverts[level];
895     do
896     {
897       VectorCopy(v->v_norm, n);
898       n += 4;
899       ++v;
900     } while (--i);
901   }
902 
903   if (State::curr_shader->flags & SF_HASCOLORS)
904   {
905     byte *c = &input.c[input.numverts<<2];
906     v = surf->firstvert[level], i = surf->numverts[level];
907     do
908     {
909       ColorCopy(v->colour, c);
910       c += 4;
911       ++v;
912     } while (--i);
913   }
914 
915   SetVertexCoords(surf, level); // Apply vertex coordinates transformations for the surface
916 
917 #if MODIF_FOG
918   // Get fog plane pointer
919   //if (surf->fogplane)
920   {
921     cplane_t** f = &input.fog[input.numverts];
922     i = surf->numverts[level];
923     do
924     {
925       *f++ = surf->fogplane;
926     } while(--i);
927   }
928 #else
929   // Store triangle normal and distance in input data (for fog)
930   float *f = &input.fog[input.numverts * 5];
931   i = surf->numverts[level];
932   do
933   {
934     memcpy(f, surf->fog, 5*sizeof(float));
935     f += 5;
936   } while (--i);
937 #endif
938 
939   input.numverts += surf->numverts[level];
940 }
941 
942 // Flush a buffer setting the appropriate state
Flush(void)943 void Render::Flush(void)
944 {
945   Shader* s = State::curr_shader;
946 
947   if (!input.numelems /*|| !s->num_layers*/) return;
948   if (State::skipping) return;
949 
950   // set buffer states:
951   state = BF_LOCKED;
952   buffer[0].st_content = -1;    // the buffers are always dirty the first time.
953   buffer[1].st_content = -1;
954   buffer[0].c_content = -1;
955   buffer[1].c_content = -1;
956 
957   if (!gridpass)
958   {
959     State::SetupShader();
960 
961     // select render path
962     if (r_vertexLight.ivalue)
963       FlushVertexLit();
964     else if (r_ext_compiledVertexArray.ivalue)
965     {
966       if (r_ext_multitexture.ivalue && (s->flags & SF_MULTITEX))
967         FlushMtxCVA();
968       else if (s->num_layers == 1)
969         FlushSingleCVA();
970       else
971         FlushGenericCVA();
972     }
973     else
974     {
975       if (r_ext_multitexture.ivalue && (s->flags & SF_MULTITEX))
976         FlushMtx();
977       else if (s->num_layers == 1)
978         FlushSingle();
979       else
980         FlushGeneric();
981     }
982 
983     if (!r_nofog.ivalue &&
984         State::curr_effect &&
985         State::curr_effect->content_flags & CONTENTS_FOG)
986     {
987       // Render fog pass
988       Layer *l = State::curr_effect->fog_params.layer;
989       if (l)
990       {
991         glMatrixMode(GL_TEXTURE);
992         glPushMatrix();
993         SetTextureCoordinates(0, l);
994         SetVertexColors(0, l);
995         State::BindTexture(l, 0);
996         State::setState(l);
997     //  glVertexPointer(3, GL_FLOAT, XYZ_OFFSET, input.xyz);
998         if (r_ext_compiledVertexArray.ivalue)
999         {
1000           glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1001           glDisableClientState(GL_COLOR_ARRAY);
1002           glLockArraysEXT(0, input.numverts);
1003           glEnableClientState(GL_TEXTURE_COORD_ARRAY);
1004           glEnableClientState(GL_COLOR_ARRAY);
1005           glDrawElements(GL_TRIANGLES, input.numelems, GL_UNSIGNED_INT, input.elems);
1006           glUnlockArraysEXT();
1007           CheckGLError(7);
1008         }
1009         else
1010         {
1011           Stripmine(input.numelems, input.elems);
1012         }
1013         glPopMatrix();
1014         CheckGLError(3);
1015       }
1016     }
1017   }
1018   else
1019   {
1020     if (r_ext_compiledVertexArray.ivalue) FlushGridCVA();
1021     else FlushGrid();
1022   }
1023 
1024   // update counters
1025   num_tris += input.numelems/3;
1026   num_verts += input.numverts;
1027   ++num_flush;
1028 
1029   // clear buffer state:
1030   state = BF_EMPTY;
1031   input.numelems = 0;
1032   input.numverts = 0;
1033 }
1034 
ForceFlush(void)1035 void Render::ForceFlush(void)
1036 {
1037   if (state != BF_EMPTY) Flush();         // Flush all the buffers
1038 }
1039 
1040 // Flush multitexture faces using CVAs
FlushMtxCVA(void)1041 void Render::FlushMtxCVA(void)
1042 {
1043   glVertexPointer(3, GL_FLOAT, XYZ_OFFSET, input.xyz);
1044 
1045   glDisableClientState(GL_TEXTURE_COORD_ARRAY); // don't allow to cache this!
1046   glDisableClientState(GL_COLOR_ARRAY);
1047   glLockArraysEXT(0, input.numverts);
1048   glEnableClientState(GL_TEXTURE_COORD_ARRAY);
1049   glEnableClientState(GL_COLOR_ARRAY);
1050 
1051   Layer *l;
1052 
1053   for (State::pass = 0; State::pass < State::curr_shader->num_layers; ++State::pass)
1054   {
1055     l = State::curr_shader->layer[State::pass];
1056 
1057     SetTextureCoordinates(0, l);
1058     SetVertexColors(0, l);
1059 
1060     State::BindTexture(l, 0);
1061     State::setState(l);
1062 
1063     if (l->flags & LF_MULTITEX)
1064     {
1065       l = State::curr_shader->layer[++State::pass];
1066 
1067       glActiveTextureARB(GL_TEXTURE1_ARB);
1068       glClientActiveTextureARB(GL_TEXTURE1_ARB);
1069       glEnable(GL_TEXTURE_2D);
1070       glEnableClientState(GL_TEXTURE_COORD_ARRAY);
1071 
1072       SetTextureCoordinates(1, l);
1073 
1074       State::BindTexture(l, 1);
1075 
1076       glDrawElements(GL_TRIANGLES, input.numelems, GL_UNSIGNED_INT, input.elems);
1077 
1078       glDisable(GL_TEXTURE_2D);
1079       glActiveTextureARB(GL_TEXTURE0_ARB);
1080       glClientActiveTextureARB(GL_TEXTURE0_ARB);
1081       CheckGLError(8);
1082     }
1083     else
1084     {
1085       glDrawElements(GL_TRIANGLES, input.numelems, GL_UNSIGNED_INT, input.elems);
1086       CheckGLError();
1087     }
1088   }
1089 
1090   glUnlockArraysEXT();
1091   CheckGLError(7);
1092 }
1093 
1094 // Flush multitexture faces with lightmap
FlushMtx(void)1095 void Render::FlushMtx(void)
1096 {
1097   glVertexPointer(3, GL_FLOAT, XYZ_OFFSET, input.xyz);
1098   CheckGLError();
1099 
1100   Layer *l;
1101 
1102   for (State::pass = 0; State::pass < State::curr_shader->num_layers; ++State::pass)
1103   {
1104     l = State::curr_shader->layer[State::pass];
1105 
1106     SetTextureCoordinates(0, l);
1107     SetVertexColors(0, l);
1108 
1109     State::BindTexture(l, 0);
1110     State::setState(l);
1111     if (l->flags & LF_MULTITEX)
1112     {
1113       l = State::curr_shader->layer[++State::pass];
1114 
1115       glActiveTextureARB(GL_TEXTURE1_ARB);
1116       glClientActiveTextureARB(GL_TEXTURE1_ARB);
1117       glEnable(GL_TEXTURE_2D);
1118       glEnableClientState(GL_TEXTURE_COORD_ARRAY);
1119 
1120       SetTextureCoordinates(1, l);
1121 
1122       State::BindTexture(l, 1);
1123 
1124       glDrawElements(GL_TRIANGLES, input.numelems, GL_UNSIGNED_INT, input.elems);
1125 
1126       glDisable(GL_TEXTURE_2D);
1127       glActiveTextureARB(GL_TEXTURE0_ARB);
1128       glClientActiveTextureARB(GL_TEXTURE0_ARB);
1129       CheckGLError(8);
1130     }
1131     else
1132     {
1133       Stripmine(input.numelems, input.elems);
1134     }
1135   }
1136 }
1137 
1138 // Flush faces without lightmap using CVAs
FlushGenericCVA(void)1139 void Render::FlushGenericCVA(void)
1140 {
1141   glVertexPointer(3, GL_FLOAT, XYZ_OFFSET, input.xyz);
1142 
1143   glDisableClientState(GL_TEXTURE_COORD_ARRAY); // don't allow to cache this!
1144   glDisableClientState(GL_COLOR_ARRAY);
1145   glLockArraysEXT(0, input.numverts);
1146   glEnableClientState(GL_TEXTURE_COORD_ARRAY);
1147   glEnableClientState(GL_COLOR_ARRAY);
1148 
1149   Layer *l;
1150 
1151   for (State::pass = 0; State::pass < State::curr_shader->num_layers; ++State::pass)
1152   {
1153     l = State::curr_shader->layer[State::pass];
1154 
1155     SetTextureCoordinates(0, l);
1156     SetVertexColors(0, l);
1157 
1158     State::BindTexture(l, 0);
1159     State::setState(l);
1160     glDrawElements(GL_TRIANGLES, input.numelems, GL_UNSIGNED_INT, input.elems);
1161   }
1162 
1163   glUnlockArraysEXT();
1164   CheckGLError(7+State::curr_shader->num_layers);
1165 }
1166 
1167 // Flush faces without lightmap
FlushGeneric(void)1168 void Render::FlushGeneric(void)
1169 {
1170   glVertexPointer(3, GL_FLOAT, XYZ_OFFSET, input.xyz);
1171   CheckGLError();
1172 
1173   Layer *l;
1174 
1175   for (State::pass = 0; State::pass < State::curr_shader->num_layers; ++State::pass)
1176   {
1177     l = State::curr_shader->layer[State::pass];
1178 
1179     SetTextureCoordinates(0, l);
1180     SetVertexColors(0, l);
1181 
1182     State::BindTexture(l, 0);
1183     State::setState(l);
1184     Stripmine(input.numelems, input.elems);
1185   }
1186 }
1187 
1188 // Flush faces with a single layer using CVAs
FlushSingleCVA(void)1189 void Render::FlushSingleCVA(void)
1190 {
1191   glVertexPointer(3, GL_FLOAT, XYZ_OFFSET, input.xyz);
1192   glLockArraysEXT(0, input.numverts);
1193 
1194   State::pass = 0;
1195   Layer *l = State::curr_shader->layer[0];
1196 
1197   SetTextureCoordinates(0, l);
1198   SetVertexColors(0, l);
1199 
1200   State::BindTexture(l, 0);
1201   State::setState(l);
1202   glDrawElements(GL_TRIANGLES, input.numelems, GL_UNSIGNED_INT, input.elems);
1203   glUnlockArraysEXT();
1204   CheckGLError(4);
1205 }
1206 
1207 // Flush faces with a single layer without using CVAs
FlushSingle(void)1208 void Render::FlushSingle(void)
1209 {
1210   glVertexPointer(3, GL_FLOAT, XYZ_OFFSET, input.xyz);
1211   CheckGLError();
1212 
1213   State::pass = 0;
1214   Layer *l = State::curr_shader->layer[0];
1215 
1216   SetTextureCoordinates(0, l);
1217   SetVertexColors(0, l);
1218 
1219   State::BindTexture(l, 0);
1220   State::setState(l);
1221   Stripmine(input.numelems, input.elems);
1222 }
1223 
FlushGridCVA(void)1224 void Render::FlushGridCVA(void)
1225 {
1226   State::setBlend(GL_ONE, GL_ZERO);
1227   State::setAlphaFunc(GL_ALWAYS);
1228 
1229   glVertexPointer(3, GL_FLOAT, XYZ_OFFSET, input.xyz);
1230   glLockArraysEXT(0, input.numverts);
1231 
1232   glColorPointer(4, GL_UNSIGNED_BYTE, 0, buffer[0].c);
1233   memset(buffer[0].c, 255, (input.numverts<<2));
1234   glColor4f(1.f, 1.f, 1.f, 1.f);
1235 
1236   glGetBooleanv(GL_TEXTURE_2D, &texture);
1237   glGetBooleanv(GL_LIGHTING, &lighting);
1238   glGetBooleanv(GL_DEPTH_TEST, &depthtest);
1239 
1240   State::setPolygonMode(GL_LINE);
1241 
1242   glDisable(GL_TEXTURE_2D);
1243   glDisable(GL_LIGHTING);
1244   glDisable(GL_DEPTH_TEST);
1245 
1246   glDrawElements(GL_TRIANGLES, input.numelems, GL_UNSIGNED_INT, input.elems);
1247 
1248   if (texture) { glEnable(GL_TEXTURE_2D); CheckGLError(); }
1249   if (lighting) { glEnable(GL_LIGHTING); CheckGLError(); }
1250   if (depthtest) { glEnable(GL_DEPTH_TEST); CheckGLError(); }
1251 
1252   State::setPolygonMode(GL_FILL);
1253 
1254   glUnlockArraysEXT();
1255   CheckGLError(12);
1256 }
1257 
FlushGrid(void)1258 void Render::FlushGrid(void)
1259 {
1260   State::setBlend(GL_ONE, GL_ZERO);
1261   State::setAlphaFunc(GL_ALWAYS);
1262 
1263   glVertexPointer(3, GL_FLOAT, XYZ_OFFSET, input.xyz);
1264 
1265   glColorPointer(4, GL_UNSIGNED_BYTE, 0, buffer[0].c);
1266   memset(buffer[0].c, 255, (input.numverts<<2));
1267   glColor4f(1.f, 1.f, 1.f, 1.f);
1268 
1269   glGetBooleanv(GL_TEXTURE_2D, &texture);
1270   glGetBooleanv(GL_LIGHTING, &lighting);
1271   glGetBooleanv(GL_DEPTH_TEST, &depthtest);
1272 
1273   State::setPolygonMode(GL_LINE);
1274 
1275   glDisable(GL_TEXTURE_2D);
1276   glDisable(GL_LIGHTING);
1277   glDisable(GL_DEPTH_TEST);
1278 
1279   glDrawElements(GL_TRIANGLES, input.numelems, GL_UNSIGNED_INT, input.elems);
1280 
1281   if (texture) { glEnable(GL_TEXTURE_2D); CheckGLError(); }
1282   if (lighting) { glEnable(GL_LIGHTING); CheckGLError(); }
1283   if (depthtest) { glEnable(GL_DEPTH_TEST); CheckGLError(); }
1284 
1285   State::setPolygonMode(GL_FILL);
1286 
1287   CheckGLError(12);
1288 }
1289 
1290 // FIXME: this is only experimental
FlushVertexLit(void)1291 void Render::FlushVertexLit(void)
1292 {
1293   Layer *l;
1294 
1295   glVertexPointer(3, GL_FLOAT, XYZ_OFFSET, input.xyz);
1296   CheckGLError();
1297 
1298   State::pass = 0;
1299   if (State::curr_shader->layer[0]->flags & LF_LIGHTMAP)
1300   {
1301     l = State::curr_shader->layer[++State::pass];
1302 
1303     SetTextureCoordinates(0, l);
1304 
1305 //  glColorPointer(4, GL_UNSIGNED_BYTE, 0, &input.c); CheckGLError();
1306 
1307     State::BindTexture(l, 0);
1308 
1309     if (State::curr_blendsrc != GL_ONE || State::curr_blenddst != GL_ZERO)
1310     {
1311       glDisable(GL_BLEND);
1312       CheckGLError();
1313       State::curr_blenddst = l->blenddst;
1314       State::curr_blendsrc = l->blendsrc;
1315     }
1316 
1317     Stripmine(input.numelems, input.elems);
1318     ++State::pass;
1319   }
1320 
1321   for (; State::pass < State::curr_shader->num_layers; ++State::pass)
1322   {
1323     l = State::curr_shader->layer[State::pass];
1324     if (l->flags & LF_LIGHTMAP) continue;
1325 
1326     SetTextureCoordinates(0, l);
1327     SetVertexColors(0, l);
1328 
1329     State::BindTexture(l, 0);
1330     State::setState(l);
1331     Stripmine(input.numelems, input.elems);
1332   }
1333 }
1334 
SwapBuffers(void)1335 void Render::SwapBuffers(void)
1336 {
1337   if (state != BF_EMPTY) Flush();
1338 
1339   if (!swapbuffersfunc)
1340     ThrowException(NULL_POINTER, "Undefined swap function pointer for render.");
1341   swapbuffersfunc();
1342 }
1343 
1344 // that have been taken from aftershock:  (FIXME: can I use it?)
Stripmine(int numelems,unsigned int * elems)1345 void Render::Stripmine(int numelems, unsigned int *elems)
1346 {
1347   bool toggle;
1348   int elem = 0;
1349   unsigned int a, b;
1350 
1351   while (elem < numelems)
1352   {
1353     toggle = true;
1354     glBegin(GL_TRIANGLE_STRIP);
1355 
1356     glArrayElement(elems[elem++]);
1357     b = elems[elem++]; glArrayElement(b);
1358     a = elems[elem++]; glArrayElement(a);
1359 
1360     while (elem < numelems)
1361     {
1362       if (a != elems[elem] || b != elems[elem+1]) break;
1363       if (toggle) { b = elems[elem+2]; glArrayElement(b); }
1364       else        { a = elems[elem+2]; glArrayElement(a); }
1365       elem += 3;
1366       toggle = !toggle;
1367       CheckGLError(1);
1368     }
1369     glEnd();
1370     CheckGLError(5);
1371   }
1372 }
1373 
SetVertexCoords(Surface * surf,int level)1374 void Render::SetVertexCoords(Surface *surf, int level)
1375 {
1376   if (!State::curr_shader->num_deforms || r_nodeform.ivalue) return;
1377 
1378   float args[5], startoff = 0.f, off, wavesize = 1.f, inc;
1379   const float speed = 2;
1380 
1381   for (int i = 0; i < MAX_DEFORMS; ++i)
1382   {
1383     switch (State::curr_shader->deformVertexes[i].type)
1384     {
1385       case DEFORMVERTEXES_WAVE:
1386         {
1387           float *xyz = &input.xyz[input.numverts<<2];
1388           vertex_t *v = surf->firstvert[level];
1389           int nverts = surf->numverts[level];
1390           vec3_t p;
1391 
1392           args[0]  = State::curr_shader->deformVertexes[i].params[0]; // sin
1393           wavesize = State::curr_shader->deformVertexes[i].params[1];
1394           args[1]  = State::curr_shader->deformVertexes[i].params[2];
1395           args[2]  = State::curr_shader->deformVertexes[i].params[3];
1396           args[4]  = State::curr_shader->deformVertexes[i].params[5];
1397           startoff = State::curr_shader->deformVertexes[i].params[4];
1398 
1399           do
1400           {
1401             p[0] = *xyz; p[1] = *(xyz+1); p[2] = *(xyz+2);
1402             off = (p[0]+p[1]+p[2])/wavesize;
1403             args[3] = startoff + off;
1404             inc = State::Eval(&args[0]);
1405             *xyz     = p[0]+inc*v->v_norm[0];
1406             *(xyz+1) = p[1]+inc*v->v_norm[1];
1407             *(xyz+2) = p[2]+inc*v->v_norm[2];
1408             ++v;
1409             xyz += 4;
1410           } while (--nverts);
1411         }
1412         break;
1413       case DEFORMVERTEXES_NORMAL:
1414         {
1415           float *normal = &input.normal[input.numverts<<2];
1416           float *xyz = &input.xyz[input.numverts<<2];
1417           vertex_t *v = surf->firstvert[level];
1418           int nverts = surf->numverts[level];
1419           vec3_t p, n;
1420 
1421           args[0] = FUNC_SIN;
1422           args[2] = State::curr_shader->deformVertexes[i].params[0];
1423           args[4] = State::curr_shader->deformVertexes[i].params[1];
1424           float lat, lng, sinlng;
1425 
1426           do
1427           {
1428             p[0] = *xyz; p[1] = *(xyz+1); p[2] = *(xyz+2);
1429             n[0] = *normal; n[1] = *(normal+1); n[2] = *(normal+2);
1430 #if 1
1431             // diesel method
1432             args[1] = atan2f(p[2], -p[0]);
1433             args[3] = p[0]+p[1];
1434             lat = State::Eval(&args[0]);
1435 
1436             args[1] = acosf(n[1]);
1437             args[3] = p[2]+p[1];
1438             lng = State::Eval(&args[0]);
1439 
1440             sinlng = FastSin(lng);
1441             *(normal  ) = -FastCos(lat)*sinlng;
1442             *(normal+1) =  FastCos(lng);
1443             *(normal+2) =  FastSin(lat)*sinlng;
1444 #else
1445             // another method (real method is not known ;)
1446             off = (p[0]+p[1]+p[2])/(speed*wavesize);
1447             args[3] = startoff + off;
1448             inc = State::Eval(&args[0]);
1449             *(normal  ) = n[0]+inc*v->v_norm[0];
1450             *(normal+1) = n[1]+inc*v->v_norm[1];
1451             *(normal+2) = n[2]+inc*v->v_norm[2];
1452 #endif
1453             ++v;
1454             normal += 4;
1455             xyz += 4;
1456           } while (--nverts);
1457         }
1458         break;
1459       case DEFORMVERTEXES_BULGE:
1460         {
1461           if (surf->facetype != FACETYPE_PATCH) break;  // are bulge applied on other face types ?
1462           float *xyz = &input.xyz[input.numverts<<2];
1463           float *st = &input.tex_st[input.numverts<<1];
1464           vertex_t *v = surf->firstvert[level];
1465           int nverts = surf->numverts[level];
1466 
1467           args[0] = FUNC_SIN; // sin
1468           args[1] = 0;
1469           args[2] = State::curr_shader->deformVertexes[i].params[1];
1470           args[4] = 1/(speed*State::curr_shader->deformVertexes[i].params[0]);
1471 
1472           do
1473           {
1474             args[3] = *st*speed*State::curr_shader->deformVertexes[i].params[2];
1475             inc = State::Eval(&args[0]);
1476             *xyz     += inc*v->v_norm[0];
1477             *(xyz+1) += inc*v->v_norm[1];
1478             *(xyz+2) += inc*v->v_norm[2];
1479             ++v;
1480             xyz += 4;
1481             st += 2;
1482           } while (--nverts);
1483         }
1484         break;
1485       case DEFORMVERTEXES_MOVE:
1486         {
1487           float *xyz = &input.xyz[input.numverts<<2];
1488           vertex_t *v = surf->firstvert[level];
1489           int nverts = surf->numverts[level];
1490 
1491           args[0] = State::curr_shader->deformVertexes[i].params[0];  // sin
1492           args[1] = State::curr_shader->deformVertexes[i].params[4];
1493           args[2] = State::curr_shader->deformVertexes[i].params[5];
1494           args[3] = State::curr_shader->deformVertexes[i].params[6];
1495           args[4] = State::curr_shader->deformVertexes[i].params[7];
1496 
1497           do
1498           {
1499             inc = State::Eval(&args[0]);
1500             *xyz     += inc*State::curr_shader->deformVertexes[i].params[1];
1501             *(xyz+1) += inc*State::curr_shader->deformVertexes[i].params[2];
1502             *(xyz+2) += inc*State::curr_shader->deformVertexes[i].params[3];
1503             ++v;
1504             xyz += 4;
1505           } while (--nverts);
1506         }
1507         break;
1508       case DEFORMVERTEXES_AUTOSPRITE:
1509         {
1510           float *xyz = &input.xyz[input.numverts<<2], p[3], d[3], *xyzB;
1511           vertex_t *v = surf->firstvert[level], *vB;
1512           int nverts = surf->numverts[level], incr, nvertsB;
1513           vec3_t middle;
1514 
1515           while (nverts)
1516           {
1517             // Compute middle of quad
1518             incr = 4;
1519             xyzB = xyz;
1520             vB = v;
1521             nvertsB = nverts;
1522 
1523             middle[0] = middle[1] = middle[2] = 0.f;
1524 
1525             do
1526             {
1527               middle[0] += *xyz;
1528               middle[1] += *(xyz+1);
1529               middle[2] += *(xyz+2);
1530               ++v;
1531               xyz += 4;
1532             } while (--nverts && --incr);
1533             VectorScale(middle, 0.25f, middle);
1534 
1535             // Rotate each vertex
1536             incr = 4;
1537             xyz = xyzB;
1538             v = vB;
1539             nverts = nvertsB;
1540             do
1541             {
1542               p[0] = *xyz    -middle[0];
1543               p[2] = *(xyz+1)-middle[1];
1544               p[1] = *(xyz+2)-middle[2];
1545               MultVect3x3(current_camera->rotation, p, d);
1546               *xyz     = d[0]+middle[0];
1547               *(xyz+1) = d[1]+middle[1];
1548               *(xyz+2) = d[2]+middle[2];
1549               ++v;
1550               xyz += 4;
1551             } while (--nverts && --incr);
1552           }
1553         }
1554         break;
1555       case DEFORMVERTEXES_AUTOSPRITE2:
1556         {
1557           float *xyz = &input.xyz[input.numverts<<2], p[3], d[3], *xyzB;
1558           vertex_t *v = surf->firstvert[level], *vB;
1559           int nverts = surf->numverts[level], incr, nvertsB;
1560           vec3_t middle;
1561 
1562           float m[9], temp[16];
1563 
1564           while (nverts)
1565           {
1566             // Compute middle of quad
1567             incr = 4;
1568             xyzB = xyz;
1569             vB = v;
1570             nvertsB = nverts;
1571 
1572             middle[0] = middle[1] = middle[2] = 0.f;
1573 
1574             do
1575             {
1576               middle[0] += *xyz;
1577               middle[1] += *(xyz+1);
1578               middle[2] += *(xyz+2);
1579 
1580               ++v;
1581               xyz += 4;
1582             } while (--nverts && --incr);
1583             VectorScale(middle, 0.25f, middle);
1584 
1585             glMatrixMode(GL_MODELVIEW);
1586             glPushMatrix();
1587               glLoadIdentity();
1588               glRotatef(-90, 1, 0, 0);
1589               if (surf->autosprite2_axis == 0)
1590               {
1591                 // @todo Terminate this stuff
1592               }
1593               else if (surf->autosprite2_axis == 2)
1594               {
1595                 glRotatef(-current_camera->rot[1], 0, 0, 1);
1596                 CheckGLError();
1597               }
1598               glGetFloatv(GL_MODELVIEW_MATRIX, temp);
1599             glPopMatrix();
1600             CheckGLError(6);
1601 
1602             m[0] = temp[0];
1603             m[1] = temp[1];
1604             m[2] = temp[2];
1605             m[3] = temp[4];
1606             m[4] = temp[5];
1607             m[5] = temp[6];
1608             m[6] = temp[8];
1609             m[7] = temp[9];
1610             m[8] = temp[10];
1611 
1612             // Rotate each vertex
1613             incr = 4;
1614             xyz = xyzB;
1615             v = vB;
1616             nverts = nvertsB;
1617             do
1618             {
1619               p[0] = *xyz    -middle[0];
1620               p[2] = *(xyz+1)-middle[1];
1621               p[1] = *(xyz+2)-middle[2];
1622               MultVect3x3(m, p, d);
1623               *xyz     = d[0]+middle[0];
1624               *(xyz+1) = d[1]+middle[1];
1625               *(xyz+2) = d[2]+middle[2];
1626               ++v;
1627               xyz += 4;
1628             } while (--nverts && --incr);
1629           }
1630         }
1631         break;
1632     //  case DEFORMVERTEXES_NONE:
1633     //    break;
1634       default:
1635         break;
1636     }
1637   }
1638 }
1639 
SetTextureCoordinates(int tmu,Layer * l)1640 void Render::SetTextureCoordinates(int tmu, Layer *l)
1641 {
1642   glTexCoordPointer(2, GL_FLOAT, 0, buffer[tmu].st);
1643   CheckGLError();
1644 
1645   if (r_noshader.ivalue)
1646   {
1647     memcpy(buffer[tmu].st, input.lm_st, sizeof(float)*(input.numverts<<1));
1648     return;
1649   }
1650 
1651   // if the contents are the same, and the buffer isn't dirty don't fill it again.
1652   if (buffer[tmu].st_content != l->tcGen || buffer[tmu].st_content == -1)
1653   {
1654     buffer[tmu].st_content = l->tcGen;
1655 
1656     switch (l->tcGen)
1657     {
1658       case TCGEN_LIGHTMAP:
1659         memcpy(buffer[tmu].st, input.lm_st, sizeof(float)*(input.numverts<<1));
1660         break;
1661       case TCGEN_ENVIRONMENT:
1662         {
1663           vec3_t dir, pos;
1664           vec_t m[16];
1665           glMatrixMode(GL_MODELVIEW);
1666           glGetFloatv(GL_MODELVIEW_MATRIX, m);
1667           vec3_t trans;
1668           // Invert the matrix
1669           VectorCopy(&m[12], trans);
1670           m[12] = -DotProduct(trans, &m[0]);
1671           m[13] = -DotProduct(trans, &m[4]);
1672           m[14] = -DotProduct(trans, &m[8]);
1673           float t = m[1];
1674           m[1] = m[4];
1675           m[4] = t;
1676           t = m[2];
1677           m[2] = m[8];
1678           m[8] = t;
1679           t = m[9];
1680           m[9] = m[6];
1681           m[6] = t;
1682           VectorCopy(&m[12], pos);
1683           for (int i = 0; i < input.numverts; ++i)
1684           {
1685             VectorSub(pos, &input.xyz[i<<2], dir);
1686 
1687             FastNormVect3(dir);
1688 
1689             buffer[tmu].st[ i<<1   ] = dir[2]-input.normal[(i<<2)+2];
1690             buffer[tmu].st[(i<<1)+1] = dir[1]-input.normal[(i<<2)+1];
1691           }
1692         }
1693         break;
1694       case TCGEN_VECTOR:
1695       case TCGEN_BASE:
1696         memcpy(buffer[tmu].st, input.tex_st, sizeof(float)*(input.numverts<<1));
1697         break;
1698       case TCGEN_FOG:
1699 #if MODIF_FOG
1700         {
1701           cplane_t** f = input.fog;
1702           float *xyz = input.xyz;
1703           byte *c = input.c;
1704           float fogdistance, inormu, d1, d2, d3;
1705           byte r, g, b, a = 255;
1706           vec3_t d, u, v;
1707           cplane_t* fogplane = NULL;
1708 
1709           if (State::curr_effect)
1710           {
1711             // Get and set the fog parameters in effect shader
1712             r = (int)(255.f*State::curr_effect->fog_params.params[0]);
1713             g = (int)(255.f*State::curr_effect->fog_params.params[1]);
1714             b = (int)(255.f*State::curr_effect->fog_params.params[2]);
1715             fogdistance = State::curr_effect->fog_params.params[4];
1716           }
1717           else
1718           {
1719             // Get and set the fog parameters in current shader
1720             r = (int)(255.f*State::curr_shader->fog_params.params[0]);
1721             g = (int)(255.f*State::curr_shader->fog_params.params[1]);
1722             b = (int)(255.f*State::curr_shader->fog_params.params[2]);
1723             fogdistance = State::curr_shader->fog_params.params[4];
1724           }
1725 
1726           for (int i = 0; i < input.numverts; ++i, ++f, c += 4, xyz += 4)
1727           {
1728             if (*f) fogplane = *f;
1729             else __asm int 3;   // @bug Search why fogplane is NULL sometimes !!
1730             if (!fogplane) continue;
1731 
1732             v[0] = *(xyz+0);
1733             v[1] = *(xyz+1);
1734             v[2] = *(xyz+2);
1735 
1736             d[0] = v[0] - (current_camera->pos[0] + v_camnear.fvalue*current_camera->eyedir[0]);
1737             d[1] = v[1] - (current_camera->pos[1] + v_camnear.fvalue*current_camera->eyedir[1]);
1738             d[2] = v[2] - (current_camera->pos[2] + v_camnear.fvalue*current_camera->eyedir[2]);
1739             VectorCopy(current_camera->eyedir, u);
1740             inormu = InverseSqrt(u[0]*u[0]+u[1]*u[1]+u[2]*u[2]);
1741             VectorScale(u, inormu, u);
1742 
1743             d1 = PointDistance(current_camera->pos, fogplane);
1744 
1745             if (d1 < 0)
1746             {
1747               // the viewer is below the fog-surface (inside the fog volume)
1748               buffer[tmu].st[ i<<1   ] =  DotProduct(d, u);
1749               buffer[tmu].st[(i<<1)+1] = -PointDistance(v, fogplane);
1750             }
1751             else
1752             {
1753               d2 = PointDistance(v, fogplane);
1754               buffer[tmu].st[(i<<1)+1] = -d2;
1755               if (d2 < 0.0f)
1756               {
1757                 d3 = d2/(d2-d1);
1758                 d3 *= DotProduct(d, u);
1759                 buffer[tmu].st[i<<1] = d3;
1760               }
1761               else
1762               {
1763                 buffer[tmu].st[i<<1] = 0.0f;
1764               }
1765             }
1766 
1767             *(c+0) = r;
1768             *(c+1) = g;
1769             *(c+2) = b;
1770             *(c+3) = a;
1771           }
1772 
1773           glTranslatef(0, 1.5f/(float)FOG_TEXTURE_HEIGHT, 0);
1774           glScalef(1.0f/fogdistance, 1.0f/fogdistance, 1.0f); // map [0.0, fogdistance] to [0.0, 1.0]
1775           CheckGLError(2);
1776         }
1777 #else
1778         {
1779           float *f = input.fog;
1780           float *xyz = input.xyz;
1781           byte *c = input.c;
1782           cplane_t fogplane;
1783           float fogdistance, inormu, d1, d2, d3;
1784           byte r, g, b, a = 255;
1785           vec3_t d, u, v;
1786 
1787           // default plane
1788           fogplane.normal[0] = 0;
1789           fogplane.normal[1] = 0;
1790           fogplane.normal[2] = 1;
1791           fogplane.dist = 0;
1792           fogplane.type = 3;
1793 
1794           if (State::curr_effect)
1795           {
1796             // Get and set the fog parameters in effect shader
1797             r = (int)(255.f*State::curr_effect->fog_params.params[0]);
1798             g = (int)(255.f*State::curr_effect->fog_params.params[1]);
1799             b = (int)(255.f*State::curr_effect->fog_params.params[2]);
1800             fogdistance = State::curr_effect->fog_params.params[4];
1801           }
1802           else
1803           {
1804             // Get and set the fog parameters in current shader
1805             r = (int)(255.f*State::curr_shader->fog_params.params[0]);
1806             g = (int)(255.f*State::curr_shader->fog_params.params[1]);
1807             b = (int)(255.f*State::curr_shader->fog_params.params[2]);
1808             fogdistance = State::curr_shader->fog_params.params[4];
1809           }
1810 
1811           for (int i = 0; i < input.numverts; ++i)
1812           {
1813             if (fogplane.type < 4)
1814             {
1815               fogplane.normal[0] = *(f+0);
1816               fogplane.normal[1] = *(f+1);
1817               fogplane.normal[2] = *(f+2);
1818               fogplane.dist = *(f+3);
1819               fogplane.type = (unsigned int) *(f+4);
1820             }
1821             //else gConsole->Insertln("invalid vertex associated fog plane");
1822 
1823             v[0] = *(xyz+0);
1824             v[1] = *(xyz+1);
1825             v[2] = *(xyz+2);
1826 
1827             d[0] = v[0] - current_camera->pos[0];
1828             d[1] = v[1] - current_camera->pos[1];
1829             d[2] = v[2] - current_camera->pos[2];
1830             VectorCopy(current_camera->forward, u);
1831             inormu = 1.f / (float) sqrt(u[0]*u[0]+u[1]*u[1]+u[2]*u[2]);
1832             VectorScale(u, inormu, u);
1833 
1834             d1 = PointDistance(current_camera->pos, &fogplane);
1835 
1836             if (d1 < 0)
1837             {
1838               // the viewer is below the fog-surface (inside the fog volume)
1839               buffer[tmu].st[ i<<1   ] =  DotProduct(d, u);
1840               buffer[tmu].st[(i<<1)+1] = -PointDistance(v, &fogplane);
1841             }
1842             else
1843             {
1844               d2 = PointDistance(v, &fogplane);
1845               buffer[tmu].st[(i<<1)+1] = -d2;
1846               if (d2 < 0.0f)
1847               {
1848                 d3 = d2/(d2-d1);
1849                 d3 *= DotProduct(d, u);
1850                 buffer[tmu].st[i<<1] = d3;
1851               }
1852               else
1853               {
1854                 buffer[tmu].st[i<<1] = 0.0f;
1855               }
1856             }
1857 
1858             *(c+0) = r;
1859             *(c+1) = g;
1860             *(c+2) = b;
1861             *(c+3) = a;
1862 
1863             c += 4;
1864             f += 5;
1865             xyz += 4;
1866           }
1867 
1868           glTranslatef(0, 1.5f/(float)FOG_TEXTURE_HEIGHT, 0);
1869           glScalef(1.0f/fogdistance, 1.0f/fogdistance, 1.0f); // map [0.0, fogdistance] to [0.0, 1.0]
1870           CheckGLError(2);
1871         }
1872 #endif
1873         break;
1874         default:
1875           break;
1876     }
1877   }
1878 
1879   if (l->tcMod)
1880   {
1881     buffer[tmu].st_content = -1;  // texcoord transforms always destroy the content
1882 
1883     int i;
1884     float *st, t1, t2;
1885 
1886     for (funclist *f = l->tcMod; f; f = f->next)
1887     {
1888       st = buffer[tmu].st;
1889       switch (f->func)
1890       {
1891         case TCMOD_ROTATE:
1892           {
1893             float angulo = -f->p[0]*(float)Timer::fTime/M_180_PI;
1894             float sint = FastSin(angulo);
1895             float cost = FastCos(angulo);
1896             for (i = 0; i < input.numverts; ++i, st += 2)
1897             {
1898               t1 = cost * (st[0] - 0.5f) - sint * (st[1] - 0.5f) + 0.5f;
1899               t2 = cost * (st[1] - 0.5f) + sint * (st[0] - 0.5f) + 0.5f;
1900               st[0] = t1;
1901               st[1] = t2;
1902             }
1903           }
1904           break;
1905         case TCMOD_SCALE:
1906           {
1907             for (i = 0; i < input.numverts; ++i, st += 2)
1908             {
1909               st[0] = (st[0]/*-0.5f*/) * f->p[0]/* + 0.5f*/;
1910               st[1] = (st[1]/*-0.5f*/) * f->p[1]/* + 0.5f*/;
1911             }
1912           }
1913           break;
1914         case TCMOD_SCROLL:
1915           {
1916             t1 = f->p[0]*(float)Timer::fTime;
1917             t2 = f->p[1]*(float)Timer::fTime;
1918             t1 -= floorf(t1);
1919             t2 -= floorf(t2);
1920             for (i = 0; i < input.numverts; ++i, st += 2)
1921             {
1922               st[0] += t1;
1923               st[1] += t2;
1924             }
1925           }
1926           break;
1927         case TCMOD_STRETCH:
1928           {
1929             float factor = 1/State::Eval(f->p);
1930             for (i = 0; i < input.numverts; ++i, st += 2)
1931             {
1932               st[0] = (st[0] - 0.5f) * factor + 0.5f;
1933               st[1] = (st[1] - 0.5f) * factor + 0.5f;
1934             }
1935           }
1936           break;
1937         case TCMOD_TRANSFORM:
1938           {
1939             for (i = 0; i < input.numverts; ++i, st += 2)
1940             {
1941               t1 = st[0];
1942               t2 = st[1];
1943               st[0] = t1*f->p[0] + t2*f->p[2] + f->p[4];
1944               st[1] = t2*f->p[1] + t1*f->p[3] + f->p[5];
1945             }
1946           }
1947           break;
1948         case TCMOD_TURB:
1949           {
1950             t1 = f->p[2] + (float)Timer::fTime * f->p[3];
1951             t2 = f->p[1];
1952             for (i = 0; i < input.numverts; ++i, st += 2)
1953             {
1954               st[0] += FastSin(st[0]*t2+t1)*t2;
1955               st[1] += FastSin(st[1]*t2+t1)*t2;
1956             }
1957           }
1958           break;
1959         default:
1960           break;
1961       }
1962     }
1963   }
1964 }
1965 
SetVertexColors(int tmu,Layer * l)1966 void Render::SetVertexColors(int tmu, Layer *l)
1967 {
1968   if (r_novertexcolor.ivalue)
1969   {
1970     memset(buffer[tmu].c, 255, (input.numverts<<2));
1971     return;
1972   }
1973 
1974   if (State::curr_shader->num_layers)
1975   {
1976     glColorPointer(4, GL_UNSIGNED_BYTE, 0, buffer[tmu].c);
1977     CheckGLError();
1978 
1979 //    if (buffer[tmu].c_content == -1 || buffer[tmu].c_content != l->rgbGen)
1980 //    {
1981 //      buffer[tmu].c_content = l->rgbGen;
1982 
1983       switch (l->rgbGen)
1984       {
1985         case RGBGEN_NONE:
1986         case RGBGEN_IDENTITY:
1987           memset(buffer[tmu].c, 255, (input.numverts<<2));
1988           break;
1989         case RGBGEN_IDENTITY_LIGHTING:
1990           {
1991             for (int i = 0; i < input.numverts; ++i)
1992             {
1993               buffer[tmu].c[(i<<2)  ] = 127;
1994               buffer[tmu].c[(i<<2)+1] = 127;
1995               buffer[tmu].c[(i<<2)+2] = 127;
1996               buffer[tmu].c[(i<<2)+3] = 255;
1997             }
1998           }
1999           break;
2000         case RGBGEN_VERTEX:
2001         case RGBGEN_EXACTVERTEX:
2002           memcpy(buffer[tmu].c, input.c, input.numverts<<2);
2003           break;
2004         case RGBGEN_ONE_MINUS_VERTEX:
2005           {
2006             for (int i = 0; i < input.numverts; ++i)
2007             {
2008               buffer[tmu].c[(i<<2)  ] = 255 - input.c[(i<<2)];
2009               buffer[tmu].c[(i<<2)+1] = 255 - input.c[(i<<2)+1];
2010               buffer[tmu].c[(i<<2)+2] = 255 - input.c[(i<<2)+2];
2011               buffer[tmu].c[(i<<2)+3] = 255;
2012             }
2013           }
2014           break;
2015         case RGBGEN_LIGHTING_DIFFUSE:
2016           memcpy(buffer[tmu].c, input.c, input.numverts<<2);
2017           break;
2018         case RGBGEN_WAVE:
2019           {
2020             int c = (int) (255.0f*State::Eval(l->rgbGenParams));
2021             if (c < 0) c = 0;
2022             if (c > 255) c = 255;
2023             buffer[tmu].c_content = -1;
2024             for (int i = 0; i < input.numverts; ++i)
2025             {
2026               buffer[tmu].c[(i<<2)  ] = c;
2027               buffer[tmu].c[(i<<2)+1] = c;
2028               buffer[tmu].c[(i<<2)+2] = c;
2029               buffer[tmu].c[(i<<2)+3] = 255;
2030             }
2031           }
2032           break;
2033         case RGBGEN_FOG:
2034           memcpy(buffer[tmu].c, input.c, input.numverts<<2);
2035           break;
2036         default:  // TODO: finish other rgbgen types
2037           memcpy(buffer[tmu].c, input.c, input.numverts<<2);
2038           break;
2039       }
2040 
2041       switch (l->alphaGen)
2042       {
2043         case ALPHAGEN_IDENTITY:
2044           {
2045             for (int i = 0; i < input.numverts; ++i)
2046               buffer[tmu].c[(i<<2)+3] = 255;
2047           }
2048           break;
2049         case ALPHAGEN_CONST:
2050           {
2051             // TODO: implement const support
2052           }
2053           break;
2054         case ALPHAGEN_WAVE:
2055           {
2056             int c = (int) (255.0f*State::Eval(l->alphaGenParams));
2057             if (c < 0) c = 0;
2058             if (c > 255) c = 255;
2059             for (int i = 0; i < input.numverts; ++i)
2060               buffer[tmu].c[(i<<2)+3] = c;
2061           }
2062           break;
2063         case ALPHAGEN_PORTAL:
2064           {/*
2065             VectorAdd ( vertexArray[0], currententity->cam.pos, v );
2066             VectorSubtract ( r_origin, v, t );
2067             a = VectorLength ( t ) * (1.0 / 255.0);
2068             clamp ( a, 0.0f, 1.0f );
2069             b = FloatToByte ( a );
2070 
2071             for ( i = 0; i < numColors; i++, bArray += 4 ) {
2072               bArray[3] = b;
2073             }*/
2074           }
2075           break;
2076         case ALPHAGEN_VERTEX:
2077           {
2078             for (int i = 0; i < input.numverts; ++i)
2079               buffer[tmu].c[(i<<2)+3] = input.c[(i<<2)+3];
2080           }
2081           break;
2082 
2083         case ALPHAGEN_ENTITY:
2084           {/*
2085             for (int i = 0; i < input.numverts; ++i)
2086               buffer[tmu].c[(i<<2)+3] = currententity->color[3];
2087             }*/
2088           }
2089           break;
2090         case ALPHAGEN_SPECULAR:
2091           {/*
2092             VectorSubtract ( r_origin, currententity->cam.pos, t );
2093 
2094             if (!Matrix3_Compare (currententity->axis, axis_identity) ) {
2095               Matrix3_Multiply_Vec3 ( currententity->axis, t, v );
2096             } else {
2097               VectorCopy ( t, v );
2098             }
2099 
2100             for (i = 0; i < numColors; i++, bArray += 4 ) {
2101               VectorSubtract ( v, vertexArray[i], t );
2102               a = DotProduct( t, normalsArray[i] ) * rSqrt ( DotProduct(t,t) );
2103               a = a * a * a * a * a;
2104               bArray[3] = FloatToByte ( bound (0.0f, a, 1.0f) );
2105             }*/
2106           }
2107           break;
2108         default:
2109           break;
2110       }
2111 //    }
2112   }
2113   else
2114   {
2115     memcpy(buffer[tmu].c, input.c, input.numverts<<2);
2116   }
2117 }
2118 
Perspective(float fov,float aspect)2119 void Render::Perspective(float fov, float aspect)
2120 {
2121   float xmin, xmax, ymin, ymax;
2122   float one_deltax, one_deltay, one_deltaz, doubleznear;
2123   float m[16];
2124 
2125   xmax = v_camnear.fvalue * FastTan(fov/2.f);
2126   xmin = -xmax;
2127 
2128   ymax = xmax / aspect;
2129   ymin = -ymax;
2130 
2131   //glFrustum(xmin, xmax, ymin, ymax, zNear, zFar); CheckGLError();
2132 
2133   doubleznear = 2.f * v_camnear.fvalue;
2134   one_deltax = (xmax - xmin);
2135   one_deltay = (ymax - ymin);
2136   one_deltaz = (v_camfar.fvalue - v_camnear.fvalue);
2137 
2138   m[0] = (float) (doubleznear / one_deltax);
2139   m[1] = 0.f;
2140   m[2] = 0.f;
2141   m[3] = 0.f;
2142   m[4] = 0.f;
2143   m[5] = (float) (doubleznear / one_deltay);
2144   m[6] = 0.f;
2145   m[7] = 0.f;
2146   m[8] = (float) ((xmax + xmin) / one_deltax);
2147   m[9] = (float) ((ymax + ymin) / one_deltay);
2148   m[10] = (float) (-(v_camfar.fvalue + v_camnear.fvalue) / one_deltaz);
2149   m[11] = -1.f;
2150   m[12] = 0.f;
2151   m[13] = 0.f;
2152   m[14] = (float) (-(v_camfar.fvalue * doubleznear) / one_deltaz);
2153   m[15] = 0.f;
2154 
2155   glLoadMatrixf(m);
2156   CheckGLError();
2157 }
2158 
DumpGLState(void)2159 void Render::DumpGLState(void)
2160 {
2161   GLboolean bool_buffer;
2162   GLfloat float_buffer;
2163   GLint int_buffer;
2164 
2165   gLogFile->OpenFile();
2166 
2167   // blending
2168   gConsole->Insertln("State report:");
2169   glGetBooleanv(GL_BLEND, &bool_buffer);
2170   gConsole->Insertln("\tblending: %s", bool_buffer?"enabled":"disabled");
2171   glGetIntegerv(GL_BLEND_SRC, &int_buffer);
2172   gConsole->Insertln("\t\tblend src: 0x%x", int_buffer);
2173   if (int_buffer != State::curr_blendsrc) gConsole->Insertln("\t\t\t-> ^1state mismatch (%d)", State::curr_blendsrc);
2174   glGetIntegerv(GL_BLEND_DST, &int_buffer);
2175   gConsole->Insertln("\t\tblend dst: 0x%x", int_buffer);
2176   if (int_buffer != State::curr_blenddst) gConsole->Insertln("\t\t\t-> ^1state mismatch (%d)", State::curr_blenddst);
2177 
2178   // culling
2179   glGetBooleanv(GL_CULL_FACE, &bool_buffer);
2180   gConsole->Insertln("\tculling: %s", bool_buffer?"enabled":"disabled");
2181   if (State::curr_culling == CULL_NONE && bool_buffer) gConsole->Insertln("\t\t-> ^1state mismatch (%d)", State::curr_culling);
2182   glGetIntegerv(GL_CULL_FACE_MODE, &int_buffer);
2183   gConsole->Insertln("\t\tculling face mode: 0x%x", int_buffer);
2184   if (State::curr_culling != CULL_NONE &&
2185     ((State::curr_culling == CULL_FRONT && int_buffer != GL_FRONT) ||
2186      (State::curr_culling == CULL_BACK && int_buffer != GL_BACK)))
2187     gConsole->Insertln("\t\t\t-> ^1state mismatch (%d)", State::curr_culling);
2188 
2189   // depth
2190   glGetBooleanv(GL_DEPTH_TEST, &bool_buffer);
2191   gConsole->Insertln("\tdepth test: %s", bool_buffer?"enabled":"disabled");
2192   glGetBooleanv(GL_DEPTH_WRITEMASK, &bool_buffer);
2193   gConsole->Insertln("\t\tdepthwrite mask: %s", bool_buffer?"enabled":"disabled");
2194   if (bool_buffer != State::curr_depthWrite) gConsole->Insertln("\t\t-> ^1state mismatch (%s)", State::curr_depthWrite?"enabled":"disabled");
2195   glGetIntegerv(GL_DEPTH_FUNC, &int_buffer);
2196   gConsole->Insertln("\t\tdepth func: 0x%x", int_buffer);
2197   if (int_buffer != State::curr_depthFunc) gConsole->Insertln("\t\t\t-> ^1state mismatch (%d)", State::curr_depthFunc);
2198 
2199   // fog
2200   glGetBooleanv(GL_FOG, &bool_buffer);
2201   gConsole->Insertln("\tfog: %s", bool_buffer?"enabled":"disabled");
2202   glGetFloatv(GL_FOG_DENSITY, &float_buffer);
2203   gConsole->Insertln("\t\tfog density: %f", float_buffer);
2204   glGetFloatv(GL_FOG_START, &float_buffer);
2205   gConsole->Insertln("\t\tfog start: %f", float_buffer);
2206   glGetFloatv(GL_FOG_END, &float_buffer);
2207   gConsole->Insertln("\t\tfog end: %f", float_buffer);
2208   glGetIntegerv(GL_FOG_MODE, &int_buffer);
2209   gConsole->Insertln("\t\tfog mode: 0x%x", int_buffer);
2210 
2211   // lighting
2212   glGetBooleanv(GL_LIGHTING, &bool_buffer);
2213   gConsole->Insertln("\tlighting: %s", bool_buffer?"enabled":"disabled");
2214 
2215   // 1D texturing
2216   glGetBooleanv(GL_TEXTURE_1D, &bool_buffer);
2217   gConsole->Insertln("\t1D texturing: %s", bool_buffer?"enabled":"disabled");
2218 
2219   // 2D texturing
2220   glGetBooleanv(GL_TEXTURE_2D, &bool_buffer);
2221   gConsole->Insertln("\t2D texturing: %s", bool_buffer?"enabled":"disabled");
2222 
2223   // render mode
2224   glGetIntegerv(GL_RENDER_MODE, &int_buffer);
2225   gConsole->Insertln("\trendering mode: 0x%x", int_buffer);
2226 
2227   CheckGLError(18);
2228 
2229   gLogFile->CloseFile();
2230 }
2231 
CheckGLError(int ncalls)2232 void Render::CheckGLError(int ncalls)
2233 {
2234   // FIXME: Should we stop or throw an exception in release mode ?
2235   #ifdef _DEBUG
2236     GLenum glerr = glGetError();
2237     if (glerr)
2238     {
2239       /*
2240         GL_NO_ERROR                       0
2241         GL_INVALID_ENUM                   0x0500
2242         GL_INVALID_VALUE                  0x0501
2243         GL_INVALID_OPERATION              0x0502
2244         GL_STACK_OVERFLOW                 0x0503
2245         GL_STACK_UNDERFLOW                0x0504
2246         GL_OUT_OF_MEMORY                  0x0505
2247       */
2248       char errDescr[32] = { '\0' };
2249       switch (glerr)
2250       {
2251         case GL_INVALID_ENUM:       sprintf(errDescr, "GL_INVALID_ENUM"); break;
2252         case GL_INVALID_VALUE:      sprintf(errDescr, "GL_INVALID_VALUE"); break;
2253         case GL_INVALID_OPERATION:  sprintf(errDescr, "GL_INVALID_OPERATION"); break;
2254         case GL_STACK_OVERFLOW:     sprintf(errDescr, "GL_STACK_OVERFLOW"); break;
2255         case GL_STACK_UNDERFLOW:    sprintf(errDescr, "GL_STACK_UNDERFLOW"); break;
2256         case GL_OUT_OF_MEMORY:      sprintf(errDescr, "GL_OUT_OF_MEMORY"); break;
2257         default :                   sprintf(errDescr, "UNDEFINED_ERROR"); break;
2258       }
2259 
2260       gLogFile->Insert("^1OpenGL error detected: %s\n", errDescr);
2261 
2262       //__asm int 3;
2263     }
2264   #endif
2265   num_apicalls += ncalls;
2266 }
2267 
2268 //-----------------------------------------------------------------------------
2269 // State
2270 //-----------------------------------------------------------------------------
2271 
SetInitialState(int multitexture)2272 void State::SetInitialState(int multitexture)
2273 {
2274   // client state:
2275   glEnableClientState(GL_VERTEX_ARRAY);
2276   glEnableClientState(GL_TEXTURE_COORD_ARRAY);
2277 
2278   // texturing:
2279   glEnable(GL_TEXTURE_2D);
2280   curr_texture[0] = -1;
2281 
2282   // second texture unit
2283   if (multitexture)
2284   {
2285     glActiveTextureARB(GL_TEXTURE1_ARB);
2286     glClientActiveTextureARB(GL_TEXTURE1_ARB);
2287     glDisable(GL_TEXTURE_2D);
2288     glActiveTextureARB(GL_TEXTURE0_ARB);
2289     glClientActiveTextureARB(GL_TEXTURE0_ARB);
2290     curr_texture[1] = -1;
2291     gRender->CheckGLError(5);
2292   }
2293 
2294   // backface culling:
2295   glEnable(GL_CULL_FACE);
2296   glCullFace(GL_BACK);
2297   curr_culling = CULL_BACK;
2298 
2299   // color:
2300   glShadeModel(GL_SMOOTH);
2301   glEnableClientState(GL_COLOR_ARRAY);
2302 
2303   if (gl_dither.ivalue) glEnable(GL_DITHER);
2304   else glDisable(GL_DITHER);
2305 
2306   // blending:
2307   glDisable(GL_BLEND);
2308   curr_blendsrc = GL_ONE;
2309   curr_blenddst = GL_ZERO;
2310 
2311   // alpha func
2312   glDisable(GL_ALPHA_TEST);
2313   glAlphaFunc(GL_ALWAYS, 1.0f);
2314 
2315   // depth test:
2316   glEnable(GL_DEPTH_TEST);
2317   glDepthFunc(GL_LEQUAL);
2318   glDepthMask(GL_TRUE);
2319   curr_depthFunc = GL_LEQUAL;
2320   curr_depthWrite = true;
2321 
2322   glEnable(GL_SCISSOR_TEST);
2323   glDisable(GL_POLYGON_OFFSET_FILL);
2324   glPolygonOffset(-1.f, -2.f);
2325   State::setPolygonMode(GL_FILL);
2326 
2327   switch (r_quality.ivalue)
2328   {
2329     case 0:
2330       glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
2331       break;
2332     case 1:
2333       glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_DONT_CARE);
2334       break;
2335     case 2:
2336     default:
2337       glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
2338       break;
2339   }
2340 
2341   glReadBuffer(GL_BACK);
2342   glDrawBuffer(GL_BACK);
2343 
2344   // clearing:
2345   glClearColor(0.2f, 0.3f, 0.4f, 1.0f);
2346   glClearDepth(1.0f);
2347 
2348   gRender->CheckGLError(21);
2349 }
2350 
2351 // not done
SetDefaultState(void)2352 void State::SetDefaultState(void)
2353 {
2354   pass = 0;
2355 }
2356 
2357 // binds the texture of the given layer
BindTexture(Layer * l,int unit)2358 void State::BindTexture(Layer *l, int unit)
2359 {
2360   int num;
2361 
2362   if (l->flags & LF_LIGHTMAP || r_noshader.ivalue)
2363   {
2364     if (curr_lightmap != ~0) num = curr_lightmap;
2365     else return;
2366   }
2367   else if (!l->map) return; // FIXME: that happens???
2368   else if (l->num_maps > 1)
2369   {
2370     int frame = ((int) floor(Timer::fTime*l->anim_speed)) % l->num_maps;
2371     clamp(frame, 0, l->num_maps-1);
2372     num = l->map[frame]->num;
2373   }
2374   else if (l->map[0]) num = l->map[0]->num;
2375   else return;        // FIXME: that happens???
2376 
2377   if (State::curr_texture[unit] != num)
2378   {
2379     glBindTexture(GL_TEXTURE_2D, num);
2380     gRender->CheckGLError();
2381     State::curr_texture[unit] = num;
2382   }
2383 }
2384 
2385 // set the appropiate state to render the layer
setState(Layer * l)2386 void State::setState(Layer *l)
2387 {
2388   State::setBlend(l->blendsrc, l->blenddst);
2389 
2390   State::setAlphaFunc(l->alphafunc, l->alphafuncref);
2391 
2392   State::setDepthWrite(l->depthWrite);
2393   State::setDepthFunc(l->depthFunc);
2394 }
2395 
SetupShader(void)2396 void State::SetupShader(void)
2397 {
2398   State::setCulling(State::curr_shader->cull);
2399 
2400   if (State::curr_shader->flags & SF_POLYGONOFFSET)
2401     glEnable(GL_POLYGON_OFFSET_FILL);
2402   else
2403     glDisable(GL_POLYGON_OFFSET_FILL);
2404   gRender->CheckGLError();
2405 }
2406 
2407 // evaluates a deform function
Eval(float * p)2408 float State::Eval(float *p)
2409 {
2410     float x, y = 0;
2411 
2412     // Evaluate a number of time based periodic functions
2413     // y = p[1] + p[2] * func((time + p[3]) * p[4])
2414 
2415   x = ((float)Timer::fTime + p[3]) * p[4];  //x = (Timer::fTime) * p[4] + p[3];
2416   x -= floorf(x);   // normalized
2417 
2418     switch ((int) (p[0]))
2419   {
2420     case FUNC_SIN:
2421       y = FastSin(x * M_TWO_PI);
2422       break;
2423     case FUNC_SQUARE:
2424       if (x < 0.5f) y = 1.0f;
2425       else y = -1.0f;
2426       break;
2427     case FUNC_SAWTOOTH:
2428       y = x;
2429       break;
2430     case FUNC_INVERSESAWTOOTH:
2431       y = 1.0f - x;
2432       break;
2433     case FUNC_TRIANGLE:
2434       if (x < 0.5f) y = 4.0f * x - 1.0f;
2435         else y = -4.0f * x + 3.0f;
2436       break;
2437     case FUNC_NOISE:
2438       y = (((float)rand()+(float)rand())/2.f)/(float)RAND_MAX;
2439       break;
2440     default:
2441       break;
2442     }
2443 
2444     return y * p[2] + p[1];
2445 }
2446 
setDepthFunc(int val)2447 void State::setDepthFunc(int val)
2448 {
2449   if (State::curr_depthFunc != val)
2450   {
2451     if (val == GL_NEVER) glDisable(GL_DEPTH_TEST);
2452     else if (State::curr_depthFunc == GL_NEVER) glEnable(GL_DEPTH_TEST);
2453     glDepthFunc(val);
2454     gRender->CheckGLError(2);
2455     State::curr_depthFunc = val;
2456   }
2457 }
setDepthWrite(int val)2458 void State::setDepthWrite(int val)
2459 {
2460   if (State::curr_depthWrite != val)
2461   {
2462     glDepthMask(val);
2463     gRender->CheckGLError();
2464     State::curr_depthWrite = val;
2465   }
2466 }
2467 
setBlend(int src,int dst)2468 void State::setBlend(int src, int dst)
2469 {
2470   if (State::curr_blendsrc != src || State::curr_blenddst != dst)
2471   {
2472     if (src == GL_ONE && dst == GL_ZERO)
2473       glDisable(GL_BLEND);
2474     else
2475     {
2476       if (State::curr_blendsrc == GL_ONE && State::curr_blenddst == GL_ZERO)
2477       {
2478         glEnable(GL_BLEND);
2479         gRender->CheckGLError();
2480       }
2481       glBlendFunc(src, dst);
2482     }
2483     State::curr_blenddst = dst;
2484     State::curr_blendsrc = src;
2485     gRender->CheckGLError();
2486   }
2487 }
2488 
setCulling(int val)2489 void State::setCulling(int val)
2490 {
2491   if (r_nocull.ivalue)
2492   {
2493     if (State::curr_culling != CULL_NONE)
2494     {
2495       State::curr_culling = CULL_NONE;
2496       glDisable(GL_CULL_FACE);
2497       gRender->CheckGLError();
2498     }
2499   }
2500   else if (val != State::curr_culling)
2501   {
2502     if (val)
2503     {
2504       glEnable(GL_CULL_FACE);
2505       if (val < 0) glCullFace(GL_FRONT);
2506       else glCullFace(GL_BACK);
2507       gRender->CheckGLError(2);
2508     }
2509     else
2510     {
2511       glDisable(GL_CULL_FACE);
2512       gRender->CheckGLError();
2513     }
2514     State::curr_culling = val;
2515   }
2516 }
2517 
setAlphaFunc(int func,float funcref)2518 void State::setAlphaFunc(int func, float funcref)
2519 {
2520   if (func != State::curr_alphaFunc)
2521   {
2522     if (func == GL_ALWAYS)
2523     {
2524       glDisable(GL_ALPHA_TEST);
2525       gRender->CheckGLError();
2526     }
2527     else
2528     {
2529       glEnable(GL_ALPHA_TEST);
2530       glAlphaFunc(func, funcref);
2531       gRender->CheckGLError(2);
2532     }
2533     State::curr_alphaFunc = func;
2534   }
2535 }
2536 
setPolygonMode(int val)2537 void State::setPolygonMode(int val)
2538 {
2539   if (val != State::curr_polygonmode)
2540   {
2541     switch (val)
2542     {
2543       case GL_POINT:
2544         glEnable(GL_POLYGON_OFFSET_POINT);
2545         glDisable(GL_POLYGON_OFFSET_LINE);
2546         glDisable(GL_POLYGON_OFFSET_FILL);
2547         break;
2548       case GL_LINE:
2549         glDisable(GL_POLYGON_OFFSET_POINT);
2550         glEnable(GL_POLYGON_OFFSET_LINE);
2551         glDisable(GL_POLYGON_OFFSET_FILL);
2552         break;
2553       case GL_FILL:
2554         glDisable(GL_POLYGON_OFFSET_POINT);
2555         glDisable(GL_POLYGON_OFFSET_LINE);
2556         glEnable(GL_POLYGON_OFFSET_FILL);
2557         break;
2558       default:
2559         return;   // invalid enum
2560     }
2561 
2562     if (State::curr_culling == CULL_BACK)
2563       glPolygonMode(GL_BACK, val);
2564     else if (State::curr_culling == CULL_FRONT)
2565       glPolygonMode(GL_FRONT, val);
2566     else
2567       glPolygonMode(GL_FRONT_AND_BACK, val);
2568 
2569     gRender->CheckGLError();
2570     State::curr_polygonmode = val;
2571   }
2572 }
2573