1 /* $Id: gl_mesh.c,v 1.3 2002/09/25 13:22:55 bburns Exp $
2 *
3 * triangle model functions
4 *
5 * Copyright (C) 1997-2001 Id Software, Inc.
6 * Copyright (c) 2002 The Quakeforge Project.
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16 *
17 * See the GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 */
23
24 #include "gl_local.h"
25
26 /*
27 =============================================================
28
29 ALIAS MODELS
30
31 =============================================================
32 */
33
34 #define NUMVERTEXNORMALS 162
35
36 float r_avertexnormals[NUMVERTEXNORMALS][3] = {
37 #include "anorms.h"
38 };
39
40 typedef float vec4_t[4];
41
42 static vec4_t s_lerped[MAX_VERTS];
43 //static vec3_t lerped[MAX_VERTS];
44
45 vec3_t shadevector;
46 float shadelight[3];
47
48 // precalculated dot products for quantized angles
49 #define SHADEDOT_QUANT 16
50 float r_avertexnormal_dots[SHADEDOT_QUANT][256] =
51 #include "anormtab.h"
52 ;
53
54 float *shadedots = r_avertexnormal_dots[0];
55
GL_LerpVerts(int nverts,dtrivertx_t * v,dtrivertx_t * ov,dtrivertx_t * verts,float * lerp,float move[3],float frontv[3],float backv[3])56 void GL_LerpVerts( int nverts, dtrivertx_t *v, dtrivertx_t *ov, dtrivertx_t *verts, float *lerp, float move[3], float frontv[3], float backv[3] )
57 {
58 int i;
59
60 //PMM -- added RF_SHELL_DOUBLE, RF_SHELL_HALF_DAM
61 if ( currententity->flags & ( RF_SHELL_RED | RF_SHELL_GREEN | RF_SHELL_BLUE | RF_SHELL_DOUBLE | RF_SHELL_HALF_DAM) )
62 {
63 for (i=0 ; i < nverts; i++, v++, ov++, lerp+=4 )
64 {
65 float *normal = r_avertexnormals[verts[i].lightnormalindex];
66
67 lerp[0] = move[0] + ov->v[0]*backv[0] + v->v[0]*frontv[0] + normal[0] * POWERSUIT_SCALE;
68 lerp[1] = move[1] + ov->v[1]*backv[1] + v->v[1]*frontv[1] + normal[1] * POWERSUIT_SCALE;
69 lerp[2] = move[2] + ov->v[2]*backv[2] + v->v[2]*frontv[2] + normal[2] * POWERSUIT_SCALE;
70 }
71 }
72 else
73 {
74 for (i=0 ; i < nverts; i++, v++, ov++, lerp+=4)
75 {
76 lerp[0] = move[0] + ov->v[0]*backv[0] + v->v[0]*frontv[0];
77 lerp[1] = move[1] + ov->v[1]*backv[1] + v->v[1]*frontv[1];
78 lerp[2] = move[2] + ov->v[2]*backv[2] + v->v[2]*frontv[2];
79 }
80 }
81
82 }
83
84 /*
85 =============
86 GL_DrawAliasFrameLerp
87
88 interpolates between two frames and origins
89 FIXME: batch lerp all vertexes
90 =============
91 */
GL_DrawAliasFrameLerp(dmdl_t * paliashdr,float backlerp)92 void GL_DrawAliasFrameLerp (dmdl_t *paliashdr, float backlerp)
93 {
94 float l;
95 daliasframe_t *frame, *oldframe;
96 dtrivertx_t *v, *ov, *verts;
97 int *order;
98 int count;
99 float frontlerp;
100 float alpha;
101 vec3_t move, delta, vectors[3];
102 vec3_t frontv, backv;
103 int i;
104 int index_xyz;
105 float *lerp;
106
107 frame = (daliasframe_t *)((byte *)paliashdr + paliashdr->ofs_frames
108 + currententity->frame * paliashdr->framesize);
109 verts = v = frame->verts;
110
111 oldframe = (daliasframe_t *)((byte *)paliashdr + paliashdr->ofs_frames
112 + currententity->oldframe * paliashdr->framesize);
113 ov = oldframe->verts;
114
115 order = (int *)((byte *)paliashdr + paliashdr->ofs_glcmds);
116
117 // glTranslatef (frame->translate[0], frame->translate[1], frame->translate[2]);
118 // glScalef (frame->scale[0], frame->scale[1], frame->scale[2]);
119
120 if (currententity->flags & RF_TRANSLUCENT)
121 alpha = currententity->alpha;
122 else
123 alpha = 1.0;
124
125 // PMM - added double shell
126 if ( currententity->flags & ( RF_SHELL_RED | RF_SHELL_GREEN | RF_SHELL_BLUE | RF_SHELL_DOUBLE | RF_SHELL_HALF_DAM) )
127 qglDisable( GL_TEXTURE_2D );
128
129 frontlerp = 1.0 - backlerp;
130
131 // move should be the delta back to the previous frame * backlerp
132 VectorSubtract (currententity->oldorigin, currententity->origin, delta);
133 AngleVectors (currententity->angles, vectors[0], vectors[1], vectors[2]);
134
135 move[0] = DotProduct (delta, vectors[0]); // forward
136 move[1] = -DotProduct (delta, vectors[1]); // left
137 move[2] = DotProduct (delta, vectors[2]); // up
138
139 VectorAdd (move, oldframe->translate, move);
140
141 for (i=0 ; i<3 ; i++)
142 {
143 move[i] = backlerp*move[i] + frontlerp*frame->translate[i];
144 }
145
146 for (i=0 ; i<3 ; i++)
147 {
148 frontv[i] = frontlerp*frame->scale[i];
149 backv[i] = backlerp*oldframe->scale[i];
150 }
151
152 lerp = s_lerped[0];
153
154 GL_LerpVerts( paliashdr->num_xyz, v, ov, verts, lerp, move, frontv, backv );
155
156 if ( gl_vertex_arrays->value )
157 {
158 float colorArray[MAX_VERTS*4];
159
160 qglEnableClientState( GL_VERTEX_ARRAY );
161 qglVertexPointer( 3, GL_FLOAT, 16, s_lerped ); // padded for SIMD
162
163 // if ( currententity->flags & ( RF_SHELL_RED | RF_SHELL_GREEN | RF_SHELL_BLUE ) )
164 // PMM - added double damage shell
165 if ( currententity->flags & ( RF_SHELL_RED | RF_SHELL_GREEN | RF_SHELL_BLUE | RF_SHELL_DOUBLE | RF_SHELL_HALF_DAM) )
166 {
167 qglColor4f( shadelight[0], shadelight[1], shadelight[2], alpha );
168 }
169 else
170 {
171 qglEnableClientState( GL_COLOR_ARRAY );
172 qglColorPointer( 3, GL_FLOAT, 0, colorArray );
173
174 //
175 // pre light everything
176 //
177 for ( i = 0; i < paliashdr->num_xyz; i++ )
178 {
179 float l = shadedots[verts[i].lightnormalindex];
180
181 colorArray[i*3+0] = l * shadelight[0];
182 colorArray[i*3+1] = l * shadelight[1];
183 colorArray[i*3+2] = l * shadelight[2];
184 }
185 }
186
187 if ( qglLockArraysEXT != 0 )
188 qglLockArraysEXT( 0, paliashdr->num_xyz );
189
190 while (1)
191 {
192 // get the vertex count and primitive type
193 count = *order++;
194 if (!count)
195 break; // done
196 if (count < 0)
197 {
198 count = -count;
199 qglBegin (GL_TRIANGLE_FAN);
200 }
201 else
202 {
203 qglBegin (GL_TRIANGLE_STRIP);
204 }
205
206 // PMM - added double damage shell
207 if ( currententity->flags & ( RF_SHELL_RED | RF_SHELL_GREEN | RF_SHELL_BLUE | RF_SHELL_DOUBLE | RF_SHELL_HALF_DAM) )
208 {
209 do
210 {
211 index_xyz = order[2];
212 order += 3;
213
214 qglVertex3fv( s_lerped[index_xyz] );
215
216 } while (--count);
217 }
218 else
219 {
220 do
221 {
222 // texture coordinates come from the draw list
223 qglTexCoord2f (((float *)order)[0], ((float *)order)[1]);
224 index_xyz = order[2];
225
226 order += 3;
227
228 // normals and vertexes come from the frame list
229 // l = shadedots[verts[index_xyz].lightnormalindex];
230
231 // qglColor4f (l* shadelight[0], l*shadelight[1], l*shadelight[2], alpha);
232 qglArrayElement( index_xyz );
233
234 } while (--count);
235 }
236 qglEnd ();
237 }
238
239 if ( qglUnlockArraysEXT != 0 )
240 qglUnlockArraysEXT();
241 }
242 else
243 {
244 while (1)
245 {
246 // get the vertex count and primitive type
247 count = *order++;
248 if (!count)
249 break; // done
250 if (count < 0)
251 {
252 count = -count;
253 qglBegin (GL_TRIANGLE_FAN);
254 }
255 else
256 {
257 qglBegin (GL_TRIANGLE_STRIP);
258 }
259
260 if ( currententity->flags & ( RF_SHELL_RED | RF_SHELL_GREEN | RF_SHELL_BLUE ) )
261 {
262 do
263 {
264 index_xyz = order[2];
265 order += 3;
266
267 qglColor4f( shadelight[0], shadelight[1], shadelight[2], alpha);
268 qglVertex3fv (s_lerped[index_xyz]);
269
270 } while (--count);
271 }
272 else
273 {
274 do
275 {
276 // texture coordinates come from the draw list
277 qglTexCoord2f (((float *)order)[0], ((float *)order)[1]);
278 index_xyz = order[2];
279 order += 3;
280
281 // normals and vertexes come from the frame list
282 l = shadedots[verts[index_xyz].lightnormalindex];
283
284 qglColor4f (l* shadelight[0], l*shadelight[1], l*shadelight[2], alpha);
285 qglVertex3fv (s_lerped[index_xyz]);
286 } while (--count);
287 }
288
289 qglEnd ();
290 }
291 }
292
293 // if ( currententity->flags & ( RF_SHELL_RED | RF_SHELL_GREEN | RF_SHELL_BLUE ) )
294 // PMM - added double damage shell
295 if ( currententity->flags & ( RF_SHELL_RED | RF_SHELL_GREEN | RF_SHELL_BLUE | RF_SHELL_DOUBLE | RF_SHELL_HALF_DAM) )
296 qglEnable( GL_TEXTURE_2D );
297 }
298
299
300 #if 1
301 /*
302 =============
303 GL_DrawAliasShadow
304 =============
305 */
306 extern vec3_t lightspot;
307 /* stencilbuffer shadows */
308 extern qboolean have_stencil;
309
GL_DrawAliasShadow(dmdl_t * paliashdr,int posenum)310 void GL_DrawAliasShadow (dmdl_t *paliashdr, int posenum)
311 {
312 dtrivertx_t *verts;
313 int *order;
314 vec3_t point;
315 float height, lheight;
316 int count;
317 daliasframe_t *frame;
318
319 lheight = currententity->origin[2] - lightspot[2];
320
321 frame = (daliasframe_t *)((byte *)paliashdr + paliashdr->ofs_frames
322 + currententity->frame * paliashdr->framesize);
323 verts = frame->verts;
324
325 height = 0;
326
327 order = (int *)((byte *)paliashdr + paliashdr->ofs_glcmds);
328
329 height = -lheight + 0.1f;
330
331 /* stencilbuffer shadows */
332 if (have_stencil && gl_stencilshadow->value) {
333 qglEnable(GL_STENCIL_TEST);
334 qglStencilFunc(GL_EQUAL, 1, 2);
335 qglStencilOp(GL_KEEP, GL_KEEP, GL_INCR);
336 }
337
338 while (1)
339 {
340 // get the vertex count and primitive type
341 count = *order++;
342 if (!count)
343 break; // done
344 if (count < 0)
345 {
346 count = -count;
347 qglBegin (GL_TRIANGLE_FAN);
348 }
349 else
350 qglBegin (GL_TRIANGLE_STRIP);
351
352 do
353 {
354 // normals and vertexes come from the frame list
355 /*
356 point[0] = verts[order[2]].v[0] * frame->scale[0] + frame->translate[0];
357 point[1] = verts[order[2]].v[1] * frame->scale[1] + frame->translate[1];
358 point[2] = verts[order[2]].v[2] * frame->scale[2] + frame->translate[2];
359 */
360
361 memcpy( point, s_lerped[order[2]], sizeof( point ) );
362
363 point[0] -= shadevector[0]*(point[2]+lheight);
364 point[1] -= shadevector[1]*(point[2]+lheight);
365 point[2] = height;
366 // height -= 0.001;
367 qglVertex3fv (point);
368
369 order += 3;
370
371 // verts++;
372
373 } while (--count);
374
375 qglEnd ();
376 }
377
378 /* stencilbuffer shadows */
379 if (have_stencil && gl_stencilshadow->value)
380 qglDisable(GL_STENCIL_TEST);
381 }
382
383 #endif
384
385 /*
386 ** R_CullAliasModel
387 */
R_CullAliasModel(vec3_t bbox[8],entity_t * e)388 static qboolean R_CullAliasModel( vec3_t bbox[8], entity_t *e )
389 {
390 int i;
391 vec3_t mins, maxs;
392 dmdl_t *paliashdr;
393 vec3_t vectors[3];
394 vec3_t thismins, oldmins, thismaxs, oldmaxs;
395 daliasframe_t *pframe, *poldframe;
396 vec3_t angles;
397
398 paliashdr = (dmdl_t *)currentmodel->extradata;
399
400 if ( ( e->frame >= paliashdr->num_frames ) || ( e->frame < 0 ) )
401 {
402 ri.Con_Printf (PRINT_ALL, "R_CullAliasModel %s: no such frame %d\n",
403 currentmodel->name, e->frame);
404 e->frame = 0;
405 }
406 if ( ( e->oldframe >= paliashdr->num_frames ) || ( e->oldframe < 0 ) )
407 {
408 ri.Con_Printf (PRINT_ALL, "R_CullAliasModel %s: no such oldframe %d\n",
409 currentmodel->name, e->oldframe);
410 e->oldframe = 0;
411 }
412
413 pframe = ( daliasframe_t * ) ( ( byte * ) paliashdr +
414 paliashdr->ofs_frames +
415 e->frame * paliashdr->framesize);
416
417 poldframe = ( daliasframe_t * ) ( ( byte * ) paliashdr +
418 paliashdr->ofs_frames +
419 e->oldframe * paliashdr->framesize);
420
421 /*
422 ** compute axially aligned mins and maxs
423 */
424 if ( pframe == poldframe )
425 {
426 for ( i = 0; i < 3; i++ )
427 {
428 mins[i] = pframe->translate[i];
429 maxs[i] = mins[i] + pframe->scale[i]*255;
430 }
431 }
432 else
433 {
434 for ( i = 0; i < 3; i++ )
435 {
436 thismins[i] = pframe->translate[i];
437 thismaxs[i] = thismins[i] + pframe->scale[i]*255;
438
439 oldmins[i] = poldframe->translate[i];
440 oldmaxs[i] = oldmins[i] + poldframe->scale[i]*255;
441
442 if ( thismins[i] < oldmins[i] )
443 mins[i] = thismins[i];
444 else
445 mins[i] = oldmins[i];
446
447 if ( thismaxs[i] > oldmaxs[i] )
448 maxs[i] = thismaxs[i];
449 else
450 maxs[i] = oldmaxs[i];
451 }
452 }
453
454 /*
455 ** compute a full bounding box
456 */
457 for ( i = 0; i < 8; i++ )
458 {
459 vec3_t tmp;
460
461 if ( i & 1 )
462 tmp[0] = mins[0];
463 else
464 tmp[0] = maxs[0];
465
466 if ( i & 2 )
467 tmp[1] = mins[1];
468 else
469 tmp[1] = maxs[1];
470
471 if ( i & 4 )
472 tmp[2] = mins[2];
473 else
474 tmp[2] = maxs[2];
475
476 VectorCopy( tmp, bbox[i] );
477 }
478
479 /*
480 ** rotate the bounding box
481 */
482 VectorCopy( e->angles, angles );
483 angles[YAW] = -angles[YAW];
484 AngleVectors( angles, vectors[0], vectors[1], vectors[2] );
485
486 for ( i = 0; i < 8; i++ )
487 {
488 vec3_t tmp;
489
490 VectorCopy( bbox[i], tmp );
491
492 bbox[i][0] = DotProduct( vectors[0], tmp );
493 bbox[i][1] = -DotProduct( vectors[1], tmp );
494 bbox[i][2] = DotProduct( vectors[2], tmp );
495
496 VectorAdd( e->origin, bbox[i], bbox[i] );
497 }
498
499 {
500 int p, f, aggregatemask = ~0;
501
502 for ( p = 0; p < 8; p++ )
503 {
504 int mask = 0;
505
506 for ( f = 0; f < 4; f++ )
507 {
508 float dp = DotProduct( frustum[f].normal, bbox[p] );
509
510 if ( ( dp - frustum[f].dist ) < 0 )
511 {
512 mask |= ( 1 << f );
513 }
514 }
515
516 aggregatemask &= mask;
517 }
518
519 if ( aggregatemask )
520 {
521 return true;
522 }
523
524 return false;
525 }
526 }
527
528 /*
529 =================
530 R_DrawAliasModel
531
532 =================
533 */
R_DrawAliasModel(entity_t * e)534 void R_DrawAliasModel (entity_t *e)
535 {
536 int i;
537 dmdl_t *paliashdr;
538 float an;
539 vec3_t bbox[8];
540 image_t *skin;
541
542 if ( !( e->flags & RF_WEAPONMODEL ) )
543 {
544 if ( R_CullAliasModel( bbox, e ) )
545 return;
546 }
547
548 if ( e->flags & RF_WEAPONMODEL )
549 {
550 if ( r_lefthand->value == 2 )
551 return;
552 }
553
554 paliashdr = (dmdl_t *)currentmodel->extradata;
555
556 //
557 // get lighting information
558 //
559 // PMM - rewrote, reordered to handle new shells & mixing
560 // PMM - 3.20 code .. replaced with original way of doing it to keep mod authors happy
561 //
562 if ( currententity->flags & ( RF_SHELL_HALF_DAM | RF_SHELL_GREEN | RF_SHELL_RED | RF_SHELL_BLUE | RF_SHELL_DOUBLE ) )
563 {
564 VectorClear (shadelight);
565 if (currententity->flags & RF_SHELL_HALF_DAM)
566 {
567 shadelight[0] = 0.56;
568 shadelight[1] = 0.59;
569 shadelight[2] = 0.45;
570 }
571 if ( currententity->flags & RF_SHELL_DOUBLE )
572 {
573 shadelight[0] = 0.9;
574 shadelight[1] = 0.7;
575 }
576 if ( currententity->flags & RF_SHELL_RED )
577 shadelight[0] = 1.0;
578 if ( currententity->flags & RF_SHELL_GREEN )
579 shadelight[1] = 1.0;
580 if ( currententity->flags & RF_SHELL_BLUE )
581 shadelight[2] = 1.0;
582 }
583 /*
584 // PMM -special case for godmode
585 if ( (currententity->flags & RF_SHELL_RED) &&
586 (currententity->flags & RF_SHELL_BLUE) &&
587 (currententity->flags & RF_SHELL_GREEN) )
588 {
589 for (i=0 ; i<3 ; i++)
590 shadelight[i] = 1.0;
591 }
592 else if ( currententity->flags & ( RF_SHELL_RED | RF_SHELL_BLUE | RF_SHELL_DOUBLE ) )
593 {
594 VectorClear (shadelight);
595
596 if ( currententity->flags & RF_SHELL_RED )
597 {
598 shadelight[0] = 1.0;
599 if (currententity->flags & (RF_SHELL_BLUE|RF_SHELL_DOUBLE) )
600 shadelight[2] = 1.0;
601 }
602 else if ( currententity->flags & RF_SHELL_BLUE )
603 {
604 if ( currententity->flags & RF_SHELL_DOUBLE )
605 {
606 shadelight[1] = 1.0;
607 shadelight[2] = 1.0;
608 }
609 else
610 {
611 shadelight[2] = 1.0;
612 }
613 }
614 else if ( currententity->flags & RF_SHELL_DOUBLE )
615 {
616 shadelight[0] = 0.9;
617 shadelight[1] = 0.7;
618 }
619 }
620 else if ( currententity->flags & ( RF_SHELL_HALF_DAM | RF_SHELL_GREEN ) )
621 {
622 VectorClear (shadelight);
623 // PMM - new colors
624 if ( currententity->flags & RF_SHELL_HALF_DAM )
625 {
626 shadelight[0] = 0.56;
627 shadelight[1] = 0.59;
628 shadelight[2] = 0.45;
629 }
630 if ( currententity->flags & RF_SHELL_GREEN )
631 {
632 shadelight[1] = 1.0;
633 }
634 }
635 }
636 //PMM - ok, now flatten these down to range from 0 to 1.0.
637 // max_shell_val = max(shadelight[0], max(shadelight[1], shadelight[2]));
638 // if (max_shell_val > 0)
639 // {
640 // for (i=0; i<3; i++)
641 // {
642 // shadelight[i] = shadelight[i] / max_shell_val;
643 // }
644 // }
645 // pmm
646 */
647 else if ( currententity->flags & RF_FULLBRIGHT )
648 {
649 for (i=0 ; i<3 ; i++)
650 shadelight[i] = 1.0;
651 }
652 else
653 {
654 R_LightPoint (currententity->origin, shadelight);
655
656 // player lighting hack for communication back to server
657 // big hack!
658 if ( currententity->flags & RF_WEAPONMODEL )
659 {
660 // pick the greatest component, which should be the same
661 // as the mono value returned by software
662 if (shadelight[0] > shadelight[1])
663 {
664 if (shadelight[0] > shadelight[2])
665 r_lightlevel->value = 150*shadelight[0];
666 else
667 r_lightlevel->value = 150*shadelight[2];
668 }
669 else
670 {
671 if (shadelight[1] > shadelight[2])
672 r_lightlevel->value = 150*shadelight[1];
673 else
674 r_lightlevel->value = 150*shadelight[2];
675 }
676
677 }
678
679 if ( gl_monolightmap->string[0] != '0' )
680 {
681 float s = shadelight[0];
682
683 if ( s < shadelight[1] )
684 s = shadelight[1];
685 if ( s < shadelight[2] )
686 s = shadelight[2];
687
688 shadelight[0] = s;
689 shadelight[1] = s;
690 shadelight[2] = s;
691 }
692 }
693
694 if ( currententity->flags & RF_MINLIGHT )
695 {
696 for (i=0 ; i<3 ; i++)
697 if (shadelight[i] > 0.1)
698 break;
699 if (i == 3)
700 {
701 shadelight[0] = 0.1;
702 shadelight[1] = 0.1;
703 shadelight[2] = 0.1;
704 }
705 }
706
707 if ( currententity->flags & RF_GLOW )
708 { // bonus items will pulse with time
709 float scale;
710 float min;
711
712 scale = 0.1 * sin(r_newrefdef.time*7);
713 for (i=0 ; i<3 ; i++)
714 {
715 min = shadelight[i] * 0.8;
716 shadelight[i] += scale;
717 if (shadelight[i] < min)
718 shadelight[i] = min;
719 }
720 }
721
722 // =================
723 // PGM ir goggles color override
724 if ( r_newrefdef.rdflags & RDF_IRGOGGLES && currententity->flags & RF_IR_VISIBLE)
725 {
726 shadelight[0] = 1.0;
727 shadelight[1] = 0.0;
728 shadelight[2] = 0.0;
729 }
730 // PGM
731 // =================
732
733 shadedots = r_avertexnormal_dots[((int)(currententity->angles[1] * (SHADEDOT_QUANT / 360.0))) & (SHADEDOT_QUANT - 1)];
734
735 an = currententity->angles[1]/180*M_PI;
736 shadevector[0] = cos(-an);
737 shadevector[1] = sin(-an);
738 shadevector[2] = 1;
739 VectorNormalize (shadevector);
740
741 //
742 // locate the proper data
743 //
744
745 c_alias_polys += paliashdr->num_tris;
746
747 //
748 // draw all the triangles
749 //
750 if (currententity->flags & RF_DEPTHHACK) // hack the depth range to prevent view model from poking into walls
751 qglDepthRange (gldepthmin, gldepthmin + 0.3*(gldepthmax-gldepthmin));
752
753 if ( ( currententity->flags & RF_WEAPONMODEL ) && ( r_lefthand->value == 1.0F ) )
754 {
755 extern void MYgluPerspective( GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar );
756
757 qglMatrixMode( GL_PROJECTION );
758 qglPushMatrix();
759 qglLoadIdentity();
760 qglScalef( -1, 1, 1 );
761 MYgluPerspective( r_newrefdef.fov_y, ( float ) r_newrefdef.width / r_newrefdef.height, 4, 4096);
762 qglMatrixMode( GL_MODELVIEW );
763
764 qglCullFace( GL_BACK );
765 }
766
767 qglPushMatrix ();
768 e->angles[PITCH] = -e->angles[PITCH]; // sigh.
769 R_RotateForEntity (e);
770 e->angles[PITCH] = -e->angles[PITCH]; // sigh.
771
772 // select skin
773 if (currententity->skin)
774 skin = currententity->skin; // custom player skin
775 else
776 {
777 if (currententity->skinnum >= MAX_MD2SKINS)
778 skin = currentmodel->skins[0];
779 else
780 {
781 skin = currentmodel->skins[currententity->skinnum];
782 if (!skin)
783 skin = currentmodel->skins[0];
784 }
785 }
786 if (!skin)
787 skin = r_notexture; // fallback...
788 GL_Bind(skin->texnum);
789
790 // draw it
791
792 qglShadeModel (GL_SMOOTH);
793
794 GL_TexEnv( GL_MODULATE );
795 if ( currententity->flags & RF_TRANSLUCENT )
796 {
797 qglEnable (GL_BLEND);
798 }
799
800
801 if ( (currententity->frame >= paliashdr->num_frames)
802 || (currententity->frame < 0) )
803 {
804 ri.Con_Printf (PRINT_ALL, "R_DrawAliasModel %s: no such frame %d\n",
805 currentmodel->name, currententity->frame);
806 currententity->frame = 0;
807 currententity->oldframe = 0;
808 }
809
810 if ( (currententity->oldframe >= paliashdr->num_frames)
811 || (currententity->oldframe < 0))
812 {
813 ri.Con_Printf (PRINT_ALL, "R_DrawAliasModel %s: no such oldframe %d\n",
814 currentmodel->name, currententity->oldframe);
815 currententity->frame = 0;
816 currententity->oldframe = 0;
817 }
818
819 if ( !r_lerpmodels->value )
820 currententity->backlerp = 0;
821 GL_DrawAliasFrameLerp (paliashdr, currententity->backlerp);
822
823 GL_TexEnv( GL_REPLACE );
824 qglShadeModel (GL_FLAT);
825
826 qglPopMatrix ();
827
828 #if 0
829 qglDisable( GL_CULL_FACE );
830 qglPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
831 qglDisable( GL_TEXTURE_2D );
832 qglBegin( GL_TRIANGLE_STRIP );
833 for ( i = 0; i < 8; i++ )
834 {
835 qglVertex3fv( bbox[i] );
836 }
837 qglEnd();
838 qglEnable( GL_TEXTURE_2D );
839 qglPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
840 qglEnable( GL_CULL_FACE );
841 #endif
842
843 if ( ( currententity->flags & RF_WEAPONMODEL ) && ( r_lefthand->value == 1.0F ) )
844 {
845 qglMatrixMode( GL_PROJECTION );
846 qglPopMatrix();
847 qglMatrixMode( GL_MODELVIEW );
848 qglCullFace( GL_FRONT );
849 }
850
851 if ( currententity->flags & RF_TRANSLUCENT )
852 {
853 qglDisable (GL_BLEND);
854 }
855
856 if (currententity->flags & RF_DEPTHHACK)
857 qglDepthRange (gldepthmin, gldepthmax);
858
859 //#if 1
860 if (gl_shadows->value &&
861 !(currententity->flags & (RF_TRANSLUCENT|RF_WEAPONMODEL|RF_NOSHADOW))) {
862 qglPushMatrix ();
863
864 /* don't rotate shadows on ungodly axes */
865 qglTranslatef(e->origin[0], e->origin[1], e->origin[2]);
866 qglRotatef(e->angles[1], 0, 0, 1);
867
868 qglDisable (GL_TEXTURE_2D);
869 qglEnable (GL_BLEND);
870 qglColor4f (0,0,0,0.5);
871 GL_DrawAliasShadow (paliashdr, currententity->frame );
872 qglEnable (GL_TEXTURE_2D);
873 qglDisable (GL_BLEND);
874 qglPopMatrix ();
875 }
876 //#endif
877 qglColor4f (1,1,1,1);
878 }
879
880
881