]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_models.c
build 78
[xonotic/darkplaces.git] / gl_models.c
1
2 #include "quakedef.h"
3
4 // LordHavoc: vertex array
5 float *aliasvert;
6 float *aliasvertnorm;
7 byte *aliasvertcolor;
8 byte *aliasvertcolor2;
9
10 int chrometexture;
11
12 void makechrometexture()
13 {
14         int i;
15         byte noise[64*64];
16         byte data[64*64][4];
17
18         fractalnoise(noise, 64, 16);
19
20         // convert to RGBA data
21         for (i = 0;i < 64*64;i++)
22         {
23                 data[i][0] = data[i][1] = data[i][2] = noise[i];
24                 data[i][3] = 255;
25         }
26
27         chrometexture = GL_LoadTexture ("chrometexture", 64, 64, &data[0][0], true, false, 4);
28 }
29
30 void gl_models_start()
31 {
32         // allocate vertex processing arrays
33         aliasvert = malloc(sizeof(float[MD2MAX_VERTS][3]));
34         aliasvertnorm = malloc(sizeof(float[MD2MAX_VERTS][3]));
35         aliasvertcolor = malloc(sizeof(byte[MD2MAX_VERTS][4]));
36         aliasvertcolor2 = malloc(sizeof(byte[MD2MAX_VERTS][4])); // used temporarily for tinted coloring
37         makechrometexture();
38 }
39
40 void gl_models_shutdown()
41 {
42         free(aliasvert);
43         free(aliasvertnorm);
44         free(aliasvertcolor);
45         free(aliasvertcolor2);
46 }
47
48 void GL_Models_Init()
49 {
50         R_RegisterModule("GL_Models", gl_models_start, gl_models_shutdown);
51 }
52
53 extern vec3_t softwaretransform_x;
54 extern vec3_t softwaretransform_y;
55 extern vec3_t softwaretransform_z;
56 extern vec_t softwaretransform_scale;
57 extern vec3_t softwaretransform_offset;
58 void R_AliasLerpVerts(int vertcount, float lerp, trivert2 *verts1, vec3_t scale1, vec3_t translate1, trivert2 *verts2, vec3_t scale2, vec3_t translate2)
59 {
60         int i;
61         vec3_t point, matrix_x, matrix_y, matrix_z;
62         float *av, *avn;
63         av = aliasvert;
64         avn = aliasvertnorm;
65         VectorScale(softwaretransform_x, softwaretransform_scale, matrix_x);
66         VectorScale(softwaretransform_y, softwaretransform_scale, matrix_y);
67         VectorScale(softwaretransform_z, softwaretransform_scale, matrix_z);
68         if (lerp < 0) lerp = 0;
69         if (lerp > 1) lerp = 1;
70         if (lerp != 0)
71         {
72                 float ilerp, ilerp127, lerp127, scalex1, scalex2, translatex, scaley1, scaley2, translatey, scalez1, scalez2, translatez;
73                 ilerp = 1 - lerp;
74                 ilerp127 = ilerp * (1.0 / 127.0);
75                 lerp127 = lerp * (1.0 / 127.0);
76                 // calculate combined interpolation variables
77                 scalex1 = scale1[0] * ilerp;scalex2 = scale2[0] *  lerp;translatex = translate1[0] * ilerp + translate2[0] *  lerp;
78                 scaley1 = scale1[1] * ilerp;scaley2 = scale2[1] *  lerp;translatey = translate1[1] * ilerp + translate2[1] *  lerp;
79                 scalez1 = scale1[2] * ilerp;scalez2 = scale2[2] *  lerp;translatez = translate1[2] * ilerp + translate2[2] *  lerp;
80                 // generate vertices
81                 for (i = 0;i < vertcount;i++)
82                 {
83                         // rotate, scale, and translate the vertex locations
84                         point[0] = verts1->v[0] * scalex1 + verts2->v[0] * scalex2 + translatex;
85                         point[1] = verts1->v[1] * scaley1 + verts2->v[1] * scaley2 + translatey;
86                         point[2] = verts1->v[2] * scalez1 + verts2->v[2] * scalez2 + translatez;
87                         *av++ = point[0] * matrix_x[0] + point[1] * matrix_y[0] + point[2] * matrix_z[0] + softwaretransform_offset[0];
88                         *av++ = point[0] * matrix_x[1] + point[1] * matrix_y[1] + point[2] * matrix_z[1] + softwaretransform_offset[1];
89                         *av++ = point[0] * matrix_x[2] + point[1] * matrix_y[2] + point[2] * matrix_z[2] + softwaretransform_offset[2];
90                         // rotate the normals
91                         point[0] = verts1->n[0] * ilerp127 + verts2->n[0] * lerp127;
92                         point[1] = verts1->n[1] * ilerp127 + verts2->n[1] * lerp127;
93                         point[2] = verts1->n[2] * ilerp127 + verts2->n[2] * lerp127;
94                         *avn++ = point[0] * softwaretransform_x[0] + point[1] * softwaretransform_y[0] + point[2] * softwaretransform_z[0];
95                         *avn++ = point[0] * softwaretransform_x[1] + point[1] * softwaretransform_y[1] + point[2] * softwaretransform_z[1];
96                         *avn++ = point[0] * softwaretransform_x[2] + point[1] * softwaretransform_y[2] + point[2] * softwaretransform_z[2];
97                         verts1++;verts2++;
98                 }
99         }
100         else
101         {
102                 // generate vertices
103                 for (i = 0;i < vertcount;i++)
104                 {
105                         // rotate, scale, and translate the vertex locations
106                         point[0] = verts1->v[0] * scale1[0] + translate1[0];
107                         point[1] = verts1->v[1] * scale1[1] + translate1[1];
108                         point[2] = verts1->v[2] * scale1[2] + translate1[2];
109                         *av++ = point[0] * matrix_x[0] + point[1] * matrix_y[0] + point[2] * matrix_z[0] + softwaretransform_offset[0];
110                         *av++ = point[0] * matrix_x[1] + point[1] * matrix_y[1] + point[2] * matrix_z[1] + softwaretransform_offset[1];
111                         *av++ = point[0] * matrix_x[2] + point[1] * matrix_y[2] + point[2] * matrix_z[2] + softwaretransform_offset[2];
112                         // rotate the normals
113                         point[0] = verts1->n[0] * (1.0f / 127.0f);
114                         point[1] = verts1->n[1] * (1.0f / 127.0f);
115                         point[2] = verts1->n[2] * (1.0f / 127.0f);
116                         *avn++ = point[0] * softwaretransform_x[0] + point[1] * softwaretransform_y[0] + point[2] * softwaretransform_z[0];
117                         *avn++ = point[0] * softwaretransform_x[1] + point[1] * softwaretransform_y[1] + point[2] * softwaretransform_z[1];
118                         *avn++ = point[0] * softwaretransform_x[2] + point[1] * softwaretransform_y[2] + point[2] * softwaretransform_z[2];
119                         verts1++;
120                 }
121         }
122 }
123
124 float R_CalcAnimLerp(entity_t *ent, int pose, float lerpscale)
125 {
126         if (ent->draw_lastmodel == ent->model && ent->draw_lerpstart <= cl.time)
127         {
128                 if (pose != ent->draw_pose)
129                 {
130                         ent->draw_lastpose = ent->draw_pose;
131                         ent->draw_pose = pose;
132                         ent->draw_lerpstart = cl.time;
133                         return 0;
134                 }
135                 else
136                         return ((cl.time - ent->draw_lerpstart) * lerpscale);
137         }
138         else // uninitialized
139         {
140                 ent->draw_lastmodel = ent->model;
141                 ent->draw_lastpose = ent->draw_pose = pose;
142                 ent->draw_lerpstart = cl.time;
143                 return 0;
144         }
145 }
146
147 void GL_DrawModelMesh(int skin, byte *colors, maliashdr_t *maliashdr)
148 {
149         int i;
150         if (!r_render.value)
151                 return;
152         glBindTexture(GL_TEXTURE_2D, skin);
153         if (!colors)
154         {
155                 if (lighthalf)
156                         glColor3f(0.5f, 0.5f, 0.5f);
157                 else
158                         glColor3f(1.0f, 1.0f, 1.0f);
159         }
160         if (gl_vertexarrays.value)
161         {
162                 if (colors)
163                 {
164                         qglColorPointer(4, GL_UNSIGNED_BYTE, 0, colors);
165                         glEnableClientState(GL_COLOR_ARRAY);
166                 }
167
168                 qglTexCoordPointer(2, GL_FLOAT, 0, (void *)((int) maliashdr->texdata + (int) maliashdr));
169                 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
170
171                 qglDrawElements(GL_TRIANGLES, maliashdr->numtris * 3, GL_UNSIGNED_SHORT, (void *)((int) maliashdr + maliashdr->tridata));
172
173                 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
174
175                 if (colors)
176                         glDisableClientState(GL_COLOR_ARRAY);
177         }
178         else
179         {
180                 unsigned short *in, index;
181                 float *tex;
182                 in = (void *)((int) maliashdr + maliashdr->tridata);
183                 glBegin(GL_TRIANGLES);
184                 tex = (void *)((int) maliashdr + maliashdr->texdata);
185                 for (i = 0;i < maliashdr->numtris * 3;i++)
186                 {
187                         index = *in++;
188                         glTexCoord2f(tex[index*2], tex[index*2+1]);
189                         if (colors)
190                                 glColor4f(colors[index*4] * (1.0f / 255.0f), colors[index*4+1] * (1.0f / 255.0f), colors[index*4+2] * (1.0f / 255.0f), colors[index*4+3] * (1.0f / 255.0f));
191                         glVertex3fv(&aliasvert[index*3]);
192                 }
193                 glEnd();
194         }
195         // leave it in a state for additional passes
196         glDepthMask(0);
197         glEnable(GL_BLEND);
198         glBlendFunc(GL_SRC_ALPHA, GL_ONE); // additive
199 }
200
201 void R_TintModel(byte *in, byte *out, int verts, byte *color)
202 {
203         int i;
204         byte r = color[0];
205         byte g = color[1];
206         byte b = color[2];
207         for (i = 0;i < verts;i++)
208         {
209                 out[0] = (byte) ((in[0] * r) >> 8);
210                 out[1] = (byte) ((in[1] * g) >> 8);
211                 out[2] = (byte) ((in[2] * b) >> 8);
212                 out[3] =          in[3];
213                 in += 4;
214                 out += 4;
215         }
216 }
217
218 /*
219 =================
220 R_DrawAliasFrame
221
222 =================
223 */
224 extern vec3_t lightspot;
225 void R_LightModel(int numverts, vec3_t center, vec3_t basecolor);
226 void R_DrawAliasFrame (maliashdr_t *maliashdr, float alpha, vec3_t color, entity_t *ent, int shadow, vec3_t org, int frame, int *skin, int colormap, int effects, int flags)
227 {
228         int             i, pose;
229         float   lerpscale, lerp;
230         maliasframe_t *frameinfo;
231
232         softwaretransformforentity(ent);
233
234         if ((frame >= maliashdr->numframes) || (frame < 0))
235         {
236                 Con_DPrintf ("R_AliasSetupFrame: no such frame %d\n", frame);
237                 frame = 0;
238         }
239
240         frameinfo = ((maliasframe_t *)((int) maliashdr + maliashdr->framedata)) + frame;
241         pose = frameinfo->start;
242
243         if (frameinfo->length > 1)
244         {
245                 lerpscale = frameinfo->rate;
246                 pose += (int)(cl.time * frameinfo->rate) % frameinfo->length;
247         }
248         else
249                 lerpscale = 10.0f;
250
251         lerp = R_CalcAnimLerp(ent, pose, lerpscale);
252
253         R_AliasLerpVerts(maliashdr->numverts, lerp, (trivert2 *)((int) maliashdr + maliashdr->posedata) + ent->draw_lastpose * maliashdr->numverts, maliashdr->scale, maliashdr->scale_origin, (trivert2 *)((int) maliashdr + maliashdr->posedata) + ent->draw_pose * maliashdr->numverts, maliashdr->scale, maliashdr->scale_origin);
254
255         // prep the vertex array as early as possible
256         if (r_render.value)
257         {
258                 if (gl_vertexarrays.value)
259                 {
260                         qglVertexPointer(3, GL_FLOAT, 0, aliasvert);
261                         glEnableClientState(GL_VERTEX_ARRAY);
262                 }
263         }
264
265         R_LightModel(maliashdr->numverts, org, color);
266
267         if (!r_render.value)
268                 return;
269         glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
270         glShadeModel(GL_SMOOTH);
271         if (effects & EF_ADDITIVE)
272         {
273                 glBlendFunc(GL_SRC_ALPHA, GL_ONE); // additive rendering
274                 glEnable(GL_BLEND);
275                 glDepthMask(0);
276         }
277         else if (alpha != 1.0)
278         {
279                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
280                 glEnable(GL_BLEND);
281                 glDepthMask(0);
282         }
283         else
284         {
285                 glDisable(GL_BLEND);
286                 glDepthMask(1);
287         }
288
289         if (colormap >= 0)
290         {
291                 if (!skin[0] && !skin[1] && !skin[2] && !skin[3])
292                         GL_DrawModelMesh(0, NULL, maliashdr);
293                 else
294                 {
295                         int c;
296                         if (skin[0])
297                                 GL_DrawModelMesh(skin[0], aliasvertcolor, maliashdr);
298                         if (skin[1])
299                         {
300                                 c = (colormap & 0xF) << 4;c += (c >= 128 && c < 224) ? 4 : 12; // 128-224 are backwards ranges
301                                 R_TintModel(aliasvertcolor, aliasvertcolor2, maliashdr->numverts, (byte *) (&d_8to24table[c]));
302                                 GL_DrawModelMesh(skin[1], aliasvertcolor2, maliashdr);
303                         }
304                         if (skin[2])
305                         {
306                                 c = colormap & 0xF0      ;c += (c >= 128 && c < 224) ? 4 : 12; // 128-224 are backwards ranges
307                                 R_TintModel(aliasvertcolor, aliasvertcolor2, maliashdr->numverts, (byte *) (&d_8to24table[c]));
308                                 GL_DrawModelMesh(skin[2], aliasvertcolor2, maliashdr);
309                         }
310                         if (skin[3]) GL_DrawModelMesh(skin[3], NULL, maliashdr);
311                 }
312         }
313         else
314         {
315                 if (!skin[3] && !skin[4])
316                         GL_DrawModelMesh(0, NULL, maliashdr);
317                 else
318                 {
319                         if (skin[4]) GL_DrawModelMesh(skin[4], aliasvertcolor, maliashdr);
320                         if (skin[3]) GL_DrawModelMesh(skin[3], NULL, maliashdr);
321                 }
322         }
323
324         if (fogenabled)
325         {
326                 vec3_t diff;
327                 glDisable (GL_TEXTURE_2D);
328                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
329                 glEnable (GL_BLEND);
330                 glDepthMask(0); // disable zbuffer updates
331
332                 VectorSubtract(org, r_refdef.vieworg, diff);
333                 glColor4f(fogcolor[0], fogcolor[1], fogcolor[2], exp(fogdensity/DotProduct(diff,diff)));
334
335                 if (gl_vertexarrays.value)
336                 {
337                         qglDrawElements(GL_TRIANGLES, maliashdr->numtris * 3, GL_UNSIGNED_SHORT, (void *)((int) maliashdr + maliashdr->tridata));
338                 }
339                 else
340                 {
341                         unsigned short *in;
342                         in = (void *)((int) maliashdr + maliashdr->tridata);
343                         glBegin(GL_TRIANGLES);
344                         for (i = 0;i < maliashdr->numtris * 3;i++)
345                                 glVertex3fv(&aliasvert[*in++ * 3]);
346                         glEnd();
347                 }
348
349                 glEnable (GL_TEXTURE_2D);
350                 glColor3f (1,1,1);
351         }
352         if (gl_vertexarrays.value)
353                 glDisableClientState(GL_VERTEX_ARRAY);
354
355         if (!fogenabled && r_shadows.value && !(effects & EF_ADDITIVE) && shadow)
356         {
357                 // flatten it to make a shadow
358                 float *av = aliasvert + 2, l = lightspot[2] + 0.125;
359                 av = aliasvert + 2;
360                 for (i = 0;i < maliashdr->numverts;i++, av+=3)
361                         if (*av > l)
362                                 *av = l;
363                 glDisable (GL_TEXTURE_2D);
364                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
365                 glEnable (GL_BLEND);
366                 glDepthMask(0); // disable zbuffer updates
367                 glColor4f (0,0,0,0.5 * alpha);
368
369                 if (gl_vertexarrays.value)
370                 {
371                         qglVertexPointer(3, GL_FLOAT, 0, aliasvert);
372                         glEnableClientState(GL_VERTEX_ARRAY);
373                         qglDrawElements(GL_TRIANGLES, maliashdr->numtris * 3, GL_UNSIGNED_SHORT, (void *)((int) maliashdr + maliashdr->tridata));
374                         glDisableClientState(GL_VERTEX_ARRAY);
375                 }
376                 else
377                 {
378                         unsigned short *in;
379                         in = (void *)((int) maliashdr + maliashdr->tridata);
380                         glBegin(GL_TRIANGLES);
381                         for (i = 0;i < maliashdr->numtris * 3;i++)
382                                 glVertex3fv(&aliasvert[*in++ * 3]);
383                         glEnd();
384                 }
385
386                 glEnable (GL_TEXTURE_2D);
387                 glColor3f (1,1,1);
388         }
389
390         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
391         glEnable (GL_BLEND);
392         glDepthMask(1);
393 }
394
395 /*
396 =================
397 R_DrawQ2AliasFrame
398
399 =================
400 */
401 void R_DrawQ2AliasFrame (md2mem_t *pheader, float alpha, vec3_t color, entity_t *ent, int shadow, vec3_t org, int frame, int skin, int effects, int flags)
402 {
403         int *order, count;
404         float lerp;
405         md2memframe_t *frame1, *frame2;
406
407         if (r_render.value)
408                 glBindTexture(GL_TEXTURE_2D, skin);
409
410         softwaretransformforentity(ent);
411
412         if ((frame >= pheader->num_frames) || (frame < 0))
413         {
414                 Con_DPrintf ("R_SetupQ2AliasFrame: no such frame %d\n", frame);
415                 frame = 0;
416         }
417
418         lerp = R_CalcAnimLerp(ent, frame, 10);
419
420         frame1 = (void *)((int) pheader + pheader->ofs_frames + (pheader->framesize * ent->draw_lastpose));
421         frame2 = (void *)((int) pheader + pheader->ofs_frames + (pheader->framesize * ent->draw_pose));
422         R_AliasLerpVerts(pheader->num_xyz, lerp, frame1->verts, frame1->scale, frame1->translate, frame2->verts, frame2->scale, frame2->translate);
423
424         R_LightModel(pheader->num_xyz, org, color);
425
426         if (!r_render.value)
427                 return;
428         if (gl_vertexarrays.value)
429         {
430                 // LordHavoc: big mess...
431                 // using arrays only slightly, although it is enough to prevent duplicates
432                 // (saving half the transforms)
433                 qglVertexPointer(3, GL_FLOAT, 0, aliasvert);
434                 qglColorPointer(4, GL_UNSIGNED_BYTE, 0, aliasvertcolor);
435                 glEnableClientState(GL_VERTEX_ARRAY);
436                 glEnableClientState(GL_COLOR_ARRAY);
437
438                 order = (int *)((int)pheader + pheader->ofs_glcmds);
439                 while(1)
440                 {
441                         if (!(count = *order++))
442                                 break;
443                         if (count > 0)
444                                 glBegin(GL_TRIANGLE_STRIP);
445                         else
446                         {
447                                 glBegin(GL_TRIANGLE_FAN);
448                                 count = -count;
449                         }
450                         do
451                         {
452                                 glTexCoord2f(((float *)order)[0], ((float *)order)[1]);
453                                 qglArrayElement(order[2]);
454                                 order += 3;
455                         }
456                         while (count--);
457                 }
458
459                 glDisableClientState(GL_COLOR_ARRAY);
460                 glDisableClientState(GL_VERTEX_ARRAY);
461         }
462         else
463         {
464                 order = (int *)((int)pheader + pheader->ofs_glcmds);
465                 while(1)
466                 {
467                         if (!(count = *order++))
468                                 break;
469                         if (count > 0)
470                                 glBegin(GL_TRIANGLE_STRIP);
471                         else
472                         {
473                                 glBegin(GL_TRIANGLE_FAN);
474                                 count = -count;
475                         }
476                         do
477                         {
478                                 glTexCoord2f(((float *)order)[0], ((float *)order)[1]);
479                                 glColor4f(aliasvertcolor[order[2] * 4] * (1.0f / 255.0f), aliasvertcolor[order[2] * 4 + 1] * (1.0f / 255.0f), aliasvertcolor[order[2] * 4 + 2] * (1.0f / 255.0f), aliasvertcolor[order[2] * 4 + 3] * (1.0f / 255.0f));
480                                 glVertex3fv(&aliasvert[order[2] * 3]);
481                                 order += 3;
482                         }
483                         while (count--);
484                 }
485         }
486
487         if (fogenabled)
488         {
489                 glDisable (GL_TEXTURE_2D);
490                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
491                 glEnable (GL_BLEND);
492                 glDepthMask(0); // disable zbuffer updates
493                 {
494                         vec3_t diff;
495                         VectorSubtract(org, r_refdef.vieworg, diff);
496                         glColor4f(fogcolor[0], fogcolor[1], fogcolor[2], exp(fogdensity/DotProduct(diff,diff)));
497                 }
498
499                 if (gl_vertexarrays.value)
500                 {
501                         // LordHavoc: big mess...
502                         // using arrays only slightly, although it is enough to prevent duplicates
503                         // (saving half the transforms)
504                         qglVertexPointer(3, GL_FLOAT, 0, aliasvert);
505                         glEnableClientState(GL_VERTEX_ARRAY);
506
507                         order = (int *)((int)pheader + pheader->ofs_glcmds);
508                         while(1)
509                         {
510                                 if (!(count = *order++))
511                                         break;
512                                 if (count > 0)
513                                         glBegin(GL_TRIANGLE_STRIP);
514                                 else
515                                 {
516                                         glBegin(GL_TRIANGLE_FAN);
517                                         count = -count;
518                                 }
519                                 do
520                                 {
521                                         qglArrayElement(order[2]);
522                                         order += 3;
523                                 }
524                                 while (count--);
525                         }
526
527                         glDisableClientState(GL_VERTEX_ARRAY);
528                 }
529                 else
530                 {
531                         order = (int *)((int)pheader + pheader->ofs_glcmds);
532                         while(1)
533                         {
534                                 if (!(count = *order++))
535                                         break;
536                                 if (count > 0)
537                                         glBegin(GL_TRIANGLE_STRIP);
538                                 else
539                                 {
540                                         glBegin(GL_TRIANGLE_FAN);
541                                         count = -count;
542                                 }
543                                 do
544                                 {
545                                         glVertex3fv(&aliasvert[order[2] * 3]);
546                                         order += 3;
547                                 }
548                                 while (count--);
549                         }
550                 }
551
552                 glEnable (GL_TEXTURE_2D);
553                 glColor3f (1,1,1);
554         }
555
556         if (!fogenabled && r_shadows.value && !(effects & EF_ADDITIVE) && shadow)
557         {
558                 int i;
559                 float *av = aliasvert + 2, l = lightspot[2] + 0.125;
560                 av = aliasvert + 2;
561                 for (i = 0;i < pheader->num_xyz;i++, av+=3)
562                         if (*av > l)
563                                 *av = l;
564                 glDisable (GL_TEXTURE_2D);
565                 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
566                 glEnable (GL_BLEND);
567                 glDepthMask(0); // disable zbuffer updates
568                 glColor4f (0,0,0,0.5 * alpha);
569
570                 if (gl_vertexarrays.value)
571                 {
572                         qglVertexPointer(3, GL_FLOAT, 0, aliasvert);
573                         glEnableClientState(GL_VERTEX_ARRAY);
574                                                 
575                         while(1)
576                         {
577                                 if (!(count = *order++))
578                                         break;
579                                 if (count > 0)
580                                         glBegin(GL_TRIANGLE_STRIP);
581                                 else
582                                 {
583                                         glBegin(GL_TRIANGLE_FAN);
584                                         count = -count;
585                                 }
586                                 do
587                                 {
588                                         qglArrayElement(order[2]);
589                                         order += 3;
590                                 }
591                                 while (count--);
592                         }
593
594                         glDisableClientState(GL_VERTEX_ARRAY);
595                 }
596                 else
597                 {
598                         while(1)
599                         {
600                                 if (!(count = *order++))
601                                         break;
602                                 if (count > 0)
603                                         glBegin(GL_TRIANGLE_STRIP);
604                                 else
605                                 {
606                                         glBegin(GL_TRIANGLE_FAN);
607                                         count = -count;
608                                 }
609                                 do
610                                 {
611                                         glVertex3fv(&aliasvert[order[2] * 3]);
612                                         order += 3;
613                                 }
614                                 while (count--);
615                         }
616                 }
617
618                 glEnable (GL_TEXTURE_2D);
619                 glColor3f (1,1,1);
620         }
621
622         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
623         glEnable (GL_BLEND);
624         glDepthMask(1);
625 }
626
627 int modeldlightbits[8];
628 extern int r_dlightframecount;
629
630 /*
631 =================
632 R_DrawAliasModel
633
634 =================
635 */
636 void R_DrawAliasModel (entity_t *ent, int cull, float alpha, model_t *clmodel, int frame, int skin, vec3_t org, int effects, int flags, int colormap)
637 {
638         int                     i;
639         vec3_t          mins, maxs, color;
640         mleaf_t         *leaf;
641         void            *modelheader;
642         int                     *skinset;
643
644         if (alpha < (1.0 / 64.0))
645                 return; // basically completely transparent
646
647         VectorAdd (org, clmodel->mins, mins);
648         VectorAdd (org, clmodel->maxs, maxs);
649
650         if (cull && R_CullBox (mins, maxs))
651                 return;
652
653         leaf = Mod_PointInLeaf (org, cl.worldmodel);
654         if (leaf->dlightframe == r_dlightframecount)
655                 for (i = 0;i < 8;i++)
656                         modeldlightbits[i] = leaf->dlightbits[i];
657         else
658                 for (i = 0;i < 8;i++)
659                         modeldlightbits[i] = 0;
660
661         // get lighting information
662
663         if ((flags & EF_FULLBRIGHT) || (effects & EF_FULLBRIGHT))
664                 color[0] = color[1] = color[2] = 256;
665         else
666                 R_LightPoint (color, org);
667
668         if (r_render.value)
669                 glDisable(GL_ALPHA_TEST);
670
671         if (frame < 0 || frame >= clmodel->numframes)
672         {
673                 frame = 0;
674                 Con_DPrintf("invalid skin number %d for model %s\n", frame, clmodel->name);
675         }
676
677         if (skin < 0 || skin >= clmodel->numskins)
678         {
679                 skin = 0;
680                 Con_DPrintf("invalid skin number %d for model %s\n", skin, clmodel->name);
681         }
682
683         modelheader = Mod_Extradata (clmodel);
684
685         {
686 //              int *skinanimrange = (int *) (clmodel->skinanimrange + (int) modelheader) + skin * 2;
687 //              int *skinanim = (int *) (clmodel->skinanim + (int) modelheader);
688                 int *skinanimrange = clmodel->skinanimrange + skin * 2;
689                 int *skinanim = clmodel->skinanim;
690                 i = skinanimrange[0];
691                 if (skinanimrange[1] > 1) // animated
692                         i += ((int) (cl.time * 10) % skinanimrange[1]);
693                 skinset = skinanim + i*5;
694         }
695
696         if (r_render.value)
697                 glEnable (GL_TEXTURE_2D);
698
699         c_alias_polys += clmodel->numtris;
700         if (clmodel->aliastype == ALIASTYPE_MD2)
701                 R_DrawQ2AliasFrame (modelheader, alpha, color, ent, ent != &cl.viewent, org, frame, skinset[0], effects, flags);
702         else
703                 R_DrawAliasFrame (modelheader, alpha, color, ent, ent != &cl.viewent, org, frame, skinset, colormap, effects, flags);
704 }