Rev 298 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
342 | serge | 1 | // Emacs style mode select -*- C++ -*- |
2 | //----------------------------------------------------------------------------- |
||
3 | // |
||
4 | // $Id:$ |
||
5 | // |
||
6 | // Copyright (C) 1993-1996 by id Software, Inc. |
||
7 | // |
||
8 | // This source is available for distribution and/or modification |
||
9 | // only under the terms of the DOOM Source Code License as |
||
10 | // published by id Software. All rights reserved. |
||
11 | // |
||
12 | // The source is distributed in the hope that it will be useful, |
||
13 | // but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
14 | // FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License |
||
15 | // for more details. |
||
16 | // |
||
17 | // $Log:$ |
||
18 | // |
||
19 | // DESCRIPTION: |
||
20 | // Refresh of things, i.e. objects represented by sprites. |
||
21 | // |
||
22 | //----------------------------------------------------------------------------- |
||
23 | |||
24 | |||
25 | static const char |
||
26 | rcsid[] = "$Id: r_things.c,v 1.5 1997/02/03 16:47:56 b1 Exp $"; |
||
27 | |||
28 | |||
29 | #include |
||
30 | #include |
||
31 | |||
32 | #include "doomtype.h" |
||
33 | |||
34 | #include "doomdef.h" |
||
35 | #include "m_swap.h" |
||
36 | |||
37 | #include "i_system.h" |
||
38 | #include "z_zone.h" |
||
39 | #include "w_wad.h" |
||
40 | |||
41 | #include "r_local.h" |
||
42 | |||
43 | #include "doomstat.h" |
||
44 | |||
45 | |||
46 | |||
47 | #define MINZ (FRACUNIT*4) |
||
48 | #define BASEYCENTER 100 |
||
49 | |||
50 | //void R_DrawColumn (void); |
||
51 | //void R_DrawFuzzColumn (void); |
||
52 | |||
53 | |||
54 | |||
55 | typedef struct |
||
56 | { |
||
57 | int x1; |
||
58 | int x2; |
||
59 | |||
60 | int column; |
||
61 | int topclip; |
||
62 | int bottomclip; |
||
63 | |||
64 | } maskdraw_t; |
||
65 | |||
66 | |||
67 | |||
68 | // |
||
69 | // Sprite rotation 0 is facing the viewer, |
||
70 | // rotation 1 is one angle turn CLOCKWISE around the axis. |
||
71 | // This is not the same as the angle, |
||
72 | // which increases counter clockwise (protractor). |
||
73 | // There was a lot of stuff grabbed wrong, so I changed it... |
||
74 | // |
||
75 | fixed_t pspritescale; |
||
76 | fixed_t pspriteiscale; |
||
77 | |||
78 | lighttable_t** spritelights; |
||
79 | |||
80 | // constant arrays |
||
81 | // used for psprite clipping and initializing clipping |
||
82 | short negonearray[SCREENWIDTH]; |
||
83 | short screenheightarray[SCREENWIDTH]; |
||
84 | |||
85 | |||
86 | // |
||
87 | // INITIALIZATION FUNCTIONS |
||
88 | // |
||
89 | |||
90 | // variables used to look up |
||
91 | // and range check thing_t sprites patches |
||
92 | spritedef_t* sprites; |
||
93 | int numsprites; |
||
94 | |||
95 | spriteframe_t sprtemp[29]; |
||
96 | int maxframe; |
||
97 | char* spritename; |
||
98 | |||
99 | |||
100 | |||
101 | |||
102 | // |
||
103 | // R_InstallSpriteLump |
||
104 | // Local function for R_InitSprites. |
||
105 | // |
||
106 | void |
||
107 | R_InstallSpriteLump |
||
108 | ( int lump, |
||
109 | unsigned frame, |
||
110 | unsigned rotation, |
||
111 | boolean flipped ) |
||
112 | { |
||
113 | int r; |
||
114 | |||
115 | if (frame >= 29 || rotation > 8) |
||
116 | I_Error("R_InstallSpriteLump: " |
||
117 | "Bad frame characters in lump %i", lump); |
||
118 | |||
119 | if ((int)frame > maxframe) |
||
120 | maxframe = frame; |
||
121 | |||
122 | if (rotation == 0) |
||
123 | { |
||
124 | // the lump should be used for all rotations |
||
125 | if (sprtemp[frame].rotate == false) |
||
126 | I_Error ("R_InitSprites: Sprite %s frame %c has " |
||
127 | "multip rot=0 lump", spritename, 'A'+frame); |
||
128 | |||
129 | if (sprtemp[frame].rotate == true) |
||
130 | I_Error ("R_InitSprites: Sprite %s frame %c has rotations " |
||
131 | "and a rot=0 lump", spritename, 'A'+frame); |
||
132 | |||
133 | sprtemp[frame].rotate = false; |
||
134 | for (r=0 ; r<8 ; r++) |
||
135 | { |
||
136 | sprtemp[frame].lump[r] = lump - firstspritelump; |
||
137 | sprtemp[frame].flip[r] = (byte)flipped; |
||
138 | } |
||
139 | return; |
||
140 | } |
||
141 | |||
142 | // the lump is only used for one rotation |
||
143 | if (sprtemp[frame].rotate == false) |
||
144 | I_Error ("R_InitSprites: Sprite %s frame %c has rotations " |
||
145 | "and a rot=0 lump", spritename, 'A'+frame); |
||
146 | |||
147 | sprtemp[frame].rotate = true; |
||
148 | |||
149 | // make 0 based |
||
150 | rotation--; |
||
151 | if (sprtemp[frame].lump[rotation] != -1) |
||
152 | I_Error ("R_InitSprites: Sprite %s : %c : %c " |
||
153 | "has two lumps mapped to it", |
||
154 | spritename, 'A'+frame, '1'+rotation); |
||
155 | |||
156 | sprtemp[frame].lump[rotation] = lump - firstspritelump; |
||
157 | sprtemp[frame].flip[rotation] = (byte)flipped; |
||
158 | } |
||
159 | |||
160 | |||
161 | |||
162 | |||
163 | // |
||
164 | // R_InitSpriteDefs |
||
165 | // Pass a null terminated list of sprite names |
||
166 | // (4 chars exactly) to be used. |
||
167 | // Builds the sprite rotation matrixes to account |
||
168 | // for horizontally flipped sprites. |
||
169 | // Will report an error if the lumps are inconsistant. |
||
170 | // Only called at startup. |
||
171 | // |
||
172 | // Sprite lump names are 4 characters for the actor, |
||
173 | // a letter for the frame, and a number for the rotation. |
||
174 | // A sprite that is flippable will have an additional |
||
175 | // letter/number appended. |
||
176 | // The rotation character can be 0 to signify no rotations. |
||
177 | // |
||
178 | void R_InitSpriteDefs (char** namelist) |
||
179 | { |
||
180 | char** check; |
||
181 | int i; |
||
182 | int l; |
||
183 | int intname; |
||
184 | int frame; |
||
185 | int rotation; |
||
186 | int start; |
||
187 | int end; |
||
188 | int patched; |
||
189 | |||
190 | // count the number of sprite names |
||
191 | check = namelist; |
||
192 | while (*check != NULL) |
||
193 | check++; |
||
194 | |||
195 | numsprites = check-namelist; |
||
196 | |||
197 | if (!numsprites) |
||
198 | return; |
||
199 | |||
200 | sprites = Z_Malloc(numsprites *sizeof(*sprites), PU_STATIC, NULL); |
||
201 | |||
202 | start = firstspritelump-1; |
||
203 | end = lastspritelump+1; |
||
204 | |||
205 | // scan all the lump names for each of the names, |
||
206 | // noting the highest frame letter. |
||
207 | // Just compare 4 characters as ints |
||
208 | for (i=0 ; i |
||
209 | { |
||
210 | spritename = namelist[i]; |
||
211 | memset (sprtemp,-1, sizeof(sprtemp)); |
||
212 | |||
213 | maxframe = -1; |
||
214 | intname = *(int *)namelist[i]; |
||
215 | |||
216 | // scan the lumps, |
||
217 | // filling in the frames for whatever is found |
||
218 | for (l=start+1 ; l |
||
219 | { |
||
220 | if (*(int *)lumpinfo[l].name == intname) |
||
221 | { |
||
222 | frame = lumpinfo[l].name[4] - 'A'; |
||
223 | rotation = lumpinfo[l].name[5] - '0'; |
||
224 | |||
225 | if (modifiedgame) |
||
226 | patched = W_GetNumForName (lumpinfo[l].name); |
||
227 | else |
||
228 | patched = l; |
||
229 | |||
230 | R_InstallSpriteLump (patched, frame, rotation, false); |
||
231 | |||
232 | if (lumpinfo[l].name[6]) |
||
233 | { |
||
234 | frame = lumpinfo[l].name[6] - 'A'; |
||
235 | rotation = lumpinfo[l].name[7] - '0'; |
||
236 | R_InstallSpriteLump (l, frame, rotation, true); |
||
237 | } |
||
238 | } |
||
239 | } |
||
240 | |||
241 | // check the frames that were found for completeness |
||
242 | if (maxframe == -1) |
||
243 | { |
||
244 | sprites[i].numframes = 0; |
||
245 | continue; |
||
246 | } |
||
247 | |||
248 | maxframe++; |
||
249 | |||
250 | for (frame = 0 ; frame < maxframe ; frame++) |
||
251 | { |
||
252 | switch ((int)sprtemp[frame].rotate) |
||
253 | { |
||
254 | case -1: |
||
255 | // no rotations were found for that frame at all |
||
256 | I_Error ("R_InitSprites: No patches found " |
||
257 | "for %s frame %c", namelist[i], frame+'A'); |
||
258 | break; |
||
259 | |||
260 | case 0: |
||
261 | // only the first rotation is needed |
||
262 | break; |
||
263 | |||
264 | case 1: |
||
265 | // must have all 8 frames |
||
266 | for (rotation=0 ; rotation<8 ; rotation++) |
||
267 | if (sprtemp[frame].lump[rotation] == -1) |
||
268 | I_Error ("R_InitSprites: Sprite %s frame %c " |
||
269 | "is missing rotations", |
||
270 | namelist[i], frame+'A'); |
||
271 | break; |
||
272 | } |
||
273 | } |
||
274 | |||
275 | // allocate space for the frames present and copy sprtemp to it |
||
276 | sprites[i].numframes = maxframe; |
||
277 | sprites[i].spriteframes = |
||
278 | Z_Malloc (maxframe * sizeof(spriteframe_t), PU_STATIC, NULL); |
||
279 | memcpy (sprites[i].spriteframes, sprtemp, maxframe*sizeof(spriteframe_t)); |
||
280 | } |
||
281 | |||
282 | } |
||
283 | |||
284 | |||
285 | |||
286 | |||
287 | // |
||
288 | // GAME FUNCTIONS |
||
289 | // |
||
290 | vissprite_t vissprites[MAXVISSPRITES]; |
||
291 | vissprite_t* vissprite_p; |
||
292 | int newvissprite; |
||
293 | |||
294 | |||
295 | |||
296 | // |
||
297 | // R_InitSprites |
||
298 | // Called at program start. |
||
299 | // |
||
300 | void R_InitSprites (char** namelist) |
||
301 | { |
||
302 | int i; |
||
303 | |||
304 | for (i=0 ; i |
||
305 | { |
||
306 | negonearray[i] = -1; |
||
307 | } |
||
308 | |||
309 | R_InitSpriteDefs (namelist); |
||
310 | } |
||
311 | |||
312 | |||
313 | |||
314 | // |
||
315 | // R_ClearSprites |
||
316 | // Called at frame start. |
||
317 | // |
||
318 | void R_ClearSprites (void) |
||
319 | { |
||
320 | vissprite_p = vissprites; |
||
321 | } |
||
322 | |||
323 | |||
324 | // |
||
325 | // R_NewVisSprite |
||
326 | // |
||
327 | vissprite_t overflowsprite; |
||
328 | |||
329 | vissprite_t* R_NewVisSprite (void) |
||
330 | { |
||
331 | if (vissprite_p == &vissprites[MAXVISSPRITES]) |
||
332 | return &overflowsprite; |
||
333 | |||
334 | vissprite_p++; |
||
335 | return vissprite_p-1; |
||
336 | } |
||
337 | |||
338 | |||
339 | |||
340 | // |
||
341 | // R_DrawMaskedColumn |
||
342 | // Used for sprites and masked mid textures. |
||
343 | // Masked means: partly transparent, i.e. stored |
||
344 | // in posts/runs of opaque pixels. |
||
345 | // |
||
346 | short* mfloorclip; |
||
347 | short* mceilingclip; |
||
348 | |||
349 | fixed_t spryscale; |
||
350 | fixed_t sprtopscreen; |
||
351 | |||
352 | void R_DrawMaskedColumn (column_t* column) |
||
353 | { |
||
354 | int topscreen; |
||
355 | int bottomscreen; |
||
356 | fixed_t basetexturemid; |
||
357 | |||
358 | basetexturemid = dc_texturemid; |
||
359 | |||
360 | for ( ; column->topdelta != 0xff ; ) |
||
361 | { |
||
362 | // calculate unclipped screen coordinates |
||
363 | // for post |
||
364 | topscreen = sprtopscreen + spryscale*column->topdelta; |
||
365 | bottomscreen = topscreen + spryscale*column->length; |
||
366 | |||
367 | dc_yl = (topscreen+FRACUNIT-1)>>FRACBITS; |
||
368 | dc_yh = (bottomscreen-1)>>FRACBITS; |
||
369 | |||
370 | if (dc_yh >= mfloorclip[dc_x]) |
||
371 | dc_yh = mfloorclip[dc_x]-1; |
||
372 | if (dc_yl <= mceilingclip[dc_x]) |
||
373 | dc_yl = mceilingclip[dc_x]+1; |
||
374 | |||
375 | if (dc_yl <= dc_yh) |
||
376 | { |
||
377 | dc_source = (byte *)column + 3; |
||
378 | dc_texturemid = basetexturemid - (column->topdelta< |
||
379 | // dc_source = (byte *)column + 3 - column->topdelta; |
||
380 | |||
381 | // Drawn by either R_DrawColumn |
||
382 | // or (SHADOW) R_DrawFuzzColumn. |
||
383 | colfunc (); |
||
384 | } |
||
385 | column = (column_t *)( (byte *)column + column->length + 4); |
||
386 | } |
||
387 | |||
388 | dc_texturemid = basetexturemid; |
||
389 | } |
||
390 | |||
391 | |||
392 | |||
393 | // |
||
394 | // R_DrawVisSprite |
||
395 | // mfloorclip and mceilingclip should also be set. |
||
396 | // |
||
397 | void |
||
398 | R_DrawVisSprite |
||
399 | ( vissprite_t* vis, |
||
400 | int x1, |
||
401 | int x2 ) |
||
402 | { |
||
403 | column_t* column; |
||
404 | int texturecolumn; |
||
405 | fixed_t frac; |
||
406 | patch_t* patch; |
||
407 | |||
408 | |||
409 | patch = W_CacheLumpNum (vis->patch+firstspritelump, PU_CACHE); |
||
410 | |||
411 | dc_colormap = vis->colormap; |
||
412 | |||
413 | if (!dc_colormap) |
||
414 | { |
||
415 | // NULL colormap = shadow draw |
||
416 | colfunc = fuzzcolfunc; |
||
417 | } |
||
418 | else if (vis->mobjflags & MF_TRANSLATION) |
||
419 | { |
||
420 | colfunc = R_DrawTranslatedColumn; |
||
421 | dc_translation = translationtables - 256 + |
||
422 | ( (vis->mobjflags & MF_TRANSLATION) >> (MF_TRANSSHIFT-8) ); |
||
423 | } |
||
424 | |||
425 | dc_iscale = abs(vis->xiscale)>>detailshift; |
||
426 | dc_texturemid = vis->texturemid; |
||
427 | frac = vis->startfrac; |
||
428 | spryscale = vis->scale; |
||
429 | sprtopscreen = centeryfrac - FixedMul(dc_texturemid,spryscale); |
||
430 | |||
431 | for (dc_x=vis->x1 ; dc_x<=vis->x2 ; dc_x++, frac += vis->xiscale) |
||
432 | { |
||
433 | texturecolumn = frac>>FRACBITS; |
||
434 | #ifdef RANGECHECK |
||
435 | if (texturecolumn < 0 || texturecolumn >= SHORT(patch->width)) |
||
436 | { |
||
437 | // I_Error ("R_DrawSpriteRange: bad texturecolumn"); |
||
438 | printf( "texturecolumn= %d, width= %d\n\r", |
||
439 | texturecolumn,patch->width); |
||
440 | texturecolumn=patch->width-1; |
||
441 | } |
||
442 | #endif |
||
443 | column = (column_t *) ((byte *)patch + |
||
444 | LONG(patch->columnofs[texturecolumn])); |
||
445 | R_DrawMaskedColumn (column); |
||
446 | } |
||
447 | |||
448 | colfunc = basecolfunc; |
||
449 | } |
||
450 | |||
451 | |||
452 | |||
453 | // |
||
454 | // R_ProjectSprite |
||
455 | // Generates a vissprite for a thing |
||
456 | // if it might be visible. |
||
457 | // |
||
458 | void R_ProjectSprite (mobj_t* thing) |
||
459 | { |
||
460 | fixed_t tr_x; |
||
461 | fixed_t tr_y; |
||
462 | |||
463 | fixed_t gxt; |
||
464 | fixed_t gyt; |
||
465 | |||
466 | fixed_t tx; |
||
467 | fixed_t tz; |
||
468 | |||
469 | fixed_t xscale; |
||
470 | |||
471 | int x1; |
||
472 | int x2; |
||
473 | |||
474 | spritedef_t* sprdef; |
||
475 | spriteframe_t* sprframe; |
||
476 | int lump; |
||
477 | |||
478 | unsigned rot; |
||
479 | boolean flip; |
||
480 | |||
481 | int index; |
||
482 | |||
483 | vissprite_t* vis; |
||
484 | |||
485 | angle_t ang; |
||
486 | fixed_t iscale; |
||
487 | |||
488 | // transform the origin point |
||
489 | tr_x = thing->x - viewx; |
||
490 | tr_y = thing->y - viewy; |
||
491 | |||
492 | gxt = FixedMul(tr_x,viewcos); |
||
493 | gyt = -FixedMul(tr_y,viewsin); |
||
494 | |||
495 | tz = gxt-gyt; |
||
496 | |||
497 | // thing is behind view plane? |
||
498 | if (tz < MINZ) |
||
499 | return; |
||
500 | |||
501 | xscale = FixedDiv(projection, tz); |
||
502 | |||
503 | gxt = -FixedMul(tr_x,viewsin); |
||
504 | gyt = FixedMul(tr_y,viewcos); |
||
505 | tx = -(gyt+gxt); |
||
506 | |||
507 | // too far off the side? |
||
508 | if (abs(tx)>(tz<<2)) |
||
509 | return; |
||
510 | |||
511 | // decide which patch to use for sprite relative to player |
||
512 | #ifdef RANGECHECK |
||
513 | if ((unsigned)thing->sprite >= numsprites) |
||
514 | I_Error ("R_ProjectSprite: invalid sprite number %i ", |
||
515 | thing->sprite); |
||
516 | #endif |
||
517 | sprdef = &sprites[thing->sprite]; |
||
518 | #ifdef RANGECHECK |
||
519 | if ( (thing->frame&FF_FRAMEMASK) >= sprdef->numframes ) |
||
520 | I_Error ("R_ProjectSprite: invalid sprite frame %i : %i ", |
||
521 | thing->sprite, thing->frame); |
||
522 | #endif |
||
523 | sprframe = &sprdef->spriteframes[ thing->frame & FF_FRAMEMASK]; |
||
524 | |||
525 | if (sprframe->rotate) |
||
526 | { |
||
527 | // choose a different rotation based on player view |
||
528 | ang = R_PointToAngle (thing->x, thing->y); |
||
529 | rot = (ang-thing->angle+(unsigned)(ANG45/2)*9)>>29; |
||
530 | lump = sprframe->lump[rot]; |
||
531 | flip = (boolean)sprframe->flip[rot]; |
||
532 | } |
||
533 | else |
||
534 | { |
||
535 | // use single rotation for all views |
||
536 | lump = sprframe->lump[0]; |
||
537 | flip = (boolean)sprframe->flip[0]; |
||
538 | } |
||
539 | |||
540 | // calculate edges of the shape |
||
541 | tx -= spriteoffset[lump]; |
||
542 | x1 = (centerxfrac + FixedMul (tx,xscale) ) >>FRACBITS; |
||
543 | |||
544 | // off the right side? |
||
545 | if (x1 > viewwidth) |
||
546 | return; |
||
547 | |||
548 | tx += spritewidth[lump]; |
||
549 | x2 = ((centerxfrac + FixedMul (tx,xscale) ) >>FRACBITS) - 1; |
||
550 | |||
551 | // off the left side |
||
552 | if (x2 < 0) |
||
553 | return; |
||
554 | |||
555 | // store information in a vissprite |
||
556 | vis = R_NewVisSprite (); |
||
557 | vis->mobjflags = thing->flags; |
||
558 | vis->scale = xscale< |
||
559 | vis->gx = thing->x; |
||
560 | vis->gy = thing->y; |
||
561 | vis->gz = thing->z; |
||
562 | vis->gzt = thing->z + spritetopoffset[lump]; |
||
563 | vis->texturemid = vis->gzt - viewz; |
||
564 | vis->x1 = x1 < 0 ? 0 : x1; |
||
565 | vis->x2 = x2 >= viewwidth ? viewwidth-1 : x2; |
||
566 | iscale = FixedDiv (FRACUNIT, xscale); |
||
567 | |||
568 | if (flip) |
||
569 | { |
||
570 | vis->startfrac = spritewidth[lump]-1; |
||
571 | vis->xiscale = -iscale; |
||
572 | } |
||
573 | else |
||
574 | { |
||
575 | vis->startfrac = 0; |
||
576 | vis->xiscale = iscale; |
||
577 | } |
||
578 | |||
579 | if (vis->x1 > x1) |
||
580 | vis->startfrac += vis->xiscale*(vis->x1-x1); |
||
581 | vis->patch = lump; |
||
582 | |||
583 | // get light level |
||
584 | if (thing->flags & MF_SHADOW) |
||
585 | { |
||
586 | // shadow draw |
||
587 | vis->colormap = NULL; |
||
588 | } |
||
589 | else if (fixedcolormap) |
||
590 | { |
||
591 | // fixed map |
||
592 | vis->colormap = fixedcolormap; |
||
593 | } |
||
594 | else if (thing->frame & FF_FULLBRIGHT) |
||
595 | { |
||
596 | // full bright |
||
597 | vis->colormap = colormaps; |
||
598 | } |
||
599 | |||
600 | else |
||
601 | { |
||
602 | // diminished light |
||
603 | index = xscale>>(LIGHTSCALESHIFT-detailshift); |
||
604 | |||
605 | if (index >= MAXLIGHTSCALE) |
||
606 | index = MAXLIGHTSCALE-1; |
||
607 | |||
608 | vis->colormap = spritelights[index]; |
||
609 | } |
||
610 | } |
||
611 | |||
612 | |||
613 | |||
614 | |||
615 | // |
||
616 | // R_AddSprites |
||
617 | // During BSP traversal, this adds sprites by sector. |
||
618 | // |
||
619 | void R_AddSprites (sector_t* sec) |
||
620 | { |
||
621 | mobj_t* thing; |
||
622 | int lightnum; |
||
623 | |||
624 | // BSP is traversed by subsector. |
||
625 | // A sector might have been split into several |
||
626 | // subsectors during BSP building. |
||
627 | // Thus we check whether its already added. |
||
628 | if (sec->validcount == validcount) |
||
629 | return; |
||
630 | |||
631 | // Well, now it will be done. |
||
632 | sec->validcount = validcount; |
||
633 | |||
634 | lightnum = (sec->lightlevel >> LIGHTSEGSHIFT)+extralight; |
||
635 | |||
636 | if (lightnum < 0) |
||
637 | spritelights = scalelight[0]; |
||
638 | else if (lightnum >= LIGHTLEVELS) |
||
639 | spritelights = scalelight[LIGHTLEVELS-1]; |
||
640 | else |
||
641 | spritelights = scalelight[lightnum]; |
||
642 | |||
643 | // Handle all things in sector. |
||
644 | for (thing = sec->thinglist ; thing ; thing = thing->snext) |
||
645 | R_ProjectSprite (thing); |
||
646 | } |
||
647 | |||
648 | |||
649 | // |
||
650 | // R_DrawPSprite |
||
651 | // |
||
652 | void R_DrawPSprite (pspdef_t* psp) |
||
653 | { |
||
654 | fixed_t tx; |
||
655 | int x1; |
||
656 | int x2; |
||
657 | spritedef_t* sprdef; |
||
658 | spriteframe_t* sprframe; |
||
659 | int lump; |
||
660 | boolean flip; |
||
661 | vissprite_t* vis; |
||
662 | vissprite_t avis; |
||
663 | |||
664 | // decide which patch to use |
||
665 | #ifdef RANGECHECK |
||
666 | if ( (unsigned)psp->state->sprite >= numsprites) |
||
667 | I_Error ("R_ProjectSprite: invalid sprite number %i ", |
||
668 | psp->state->sprite); |
||
669 | #endif |
||
670 | sprdef = &sprites[psp->state->sprite]; |
||
671 | #ifdef RANGECHECK |
||
672 | if ( (psp->state->frame & FF_FRAMEMASK) >= sprdef->numframes) |
||
673 | I_Error ("R_ProjectSprite: invalid sprite frame %i : %i ", |
||
674 | psp->state->sprite, psp->state->frame); |
||
675 | #endif |
||
676 | sprframe = &sprdef->spriteframes[ psp->state->frame & FF_FRAMEMASK ]; |
||
677 | |||
678 | lump = sprframe->lump[0]; |
||
679 | flip = (boolean)sprframe->flip[0]; |
||
680 | |||
681 | // calculate edges of the shape |
||
682 | tx = psp->sx-160*FRACUNIT; |
||
683 | |||
684 | tx -= spriteoffset[lump]; |
||
685 | x1 = (centerxfrac + FixedMul (tx,pspritescale) ) >>FRACBITS; |
||
686 | |||
687 | // off the right side |
||
688 | if (x1 > viewwidth) |
||
689 | return; |
||
690 | |||
691 | tx += spritewidth[lump]; |
||
692 | x2 = ((centerxfrac + FixedMul (tx, pspritescale) ) >>FRACBITS) - 1; |
||
693 | |||
694 | // off the left side |
||
695 | if (x2 < 0) |
||
696 | return; |
||
697 | |||
698 | // store information in a vissprite |
||
699 | vis = &avis; |
||
700 | vis->mobjflags = 0; |
||
701 | vis->texturemid = (BASEYCENTER< |
||
702 | vis->x1 = x1 < 0 ? 0 : x1; |
||
703 | vis->x2 = x2 >= viewwidth ? viewwidth-1 : x2; |
||
704 | vis->scale = pspritescale< |
||
705 | |||
706 | if (flip) |
||
707 | { |
||
708 | vis->xiscale = -pspriteiscale; |
||
709 | vis->startfrac = spritewidth[lump]-1; |
||
710 | } |
||
711 | else |
||
712 | { |
||
713 | vis->xiscale = pspriteiscale; |
||
714 | vis->startfrac = 0; |
||
715 | } |
||
716 | |||
717 | if (vis->x1 > x1) |
||
718 | vis->startfrac += vis->xiscale*(vis->x1-x1); |
||
719 | |||
720 | vis->patch = lump; |
||
721 | |||
722 | if (viewplayer->powers[pw_invisibility] > 4*32 |
||
723 | || viewplayer->powers[pw_invisibility] & 8) |
||
724 | { |
||
725 | // shadow draw |
||
726 | vis->colormap = NULL; |
||
727 | } |
||
728 | else if (fixedcolormap) |
||
729 | { |
||
730 | // fixed color |
||
731 | vis->colormap = fixedcolormap; |
||
732 | } |
||
733 | else if (psp->state->frame & FF_FULLBRIGHT) |
||
734 | { |
||
735 | // full bright |
||
736 | vis->colormap = colormaps; |
||
737 | } |
||
738 | else |
||
739 | { |
||
740 | // local light |
||
741 | vis->colormap = spritelights[MAXLIGHTSCALE-1]; |
||
742 | } |
||
743 | |||
744 | R_DrawVisSprite (vis, vis->x1, vis->x2); |
||
745 | } |
||
746 | |||
747 | |||
748 | |||
749 | // |
||
750 | // R_DrawPlayerSprites |
||
751 | // |
||
752 | void R_DrawPlayerSprites (void) |
||
753 | { |
||
754 | int i; |
||
755 | int lightnum; |
||
756 | pspdef_t* psp; |
||
757 | |||
758 | // get light level |
||
759 | lightnum = |
||
760 | (viewplayer->mo->subsector->sector->lightlevel >> LIGHTSEGSHIFT) |
||
761 | +extralight; |
||
762 | |||
763 | if (lightnum < 0) |
||
764 | spritelights = scalelight[0]; |
||
765 | else if (lightnum >= LIGHTLEVELS) |
||
766 | spritelights = scalelight[LIGHTLEVELS-1]; |
||
767 | else |
||
768 | spritelights = scalelight[lightnum]; |
||
769 | |||
770 | // clip to screen bounds |
||
771 | mfloorclip = screenheightarray; |
||
772 | mceilingclip = negonearray; |
||
773 | |||
774 | // add all active psprites |
||
775 | for (i=0, psp=viewplayer->psprites; |
||
776 | i |
||
777 | i++,psp++) |
||
778 | { |
||
779 | if (psp->state) |
||
780 | R_DrawPSprite (psp); |
||
781 | } |
||
782 | } |
||
783 | |||
784 | |||
785 | |||
786 | |||
787 | // |
||
788 | // R_SortVisSprites |
||
789 | // |
||
790 | vissprite_t vsprsortedhead; |
||
791 | |||
792 | |||
793 | void R_SortVisSprites (void) |
||
794 | { |
||
795 | int i; |
||
796 | int count; |
||
797 | vissprite_t* ds; |
||
798 | vissprite_t* best; |
||
799 | vissprite_t unsorted; |
||
800 | fixed_t bestscale; |
||
801 | |||
802 | count = vissprite_p - vissprites; |
||
803 | |||
804 | unsorted.next = unsorted.prev = &unsorted; |
||
805 | |||
806 | if (!count) |
||
807 | return; |
||
808 | |||
809 | for (ds=vissprites ; ds |
||
810 | { |
||
811 | ds->next = ds+1; |
||
812 | ds->prev = ds-1; |
||
813 | } |
||
814 | |||
815 | vissprites[0].prev = &unsorted; |
||
816 | unsorted.next = &vissprites[0]; |
||
817 | (vissprite_p-1)->next = &unsorted; |
||
818 | unsorted.prev = vissprite_p-1; |
||
819 | |||
820 | // pull the vissprites out by scale |
||
821 | //best = 0; // shut up the compiler warning |
||
822 | vsprsortedhead.next = vsprsortedhead.prev = &vsprsortedhead; |
||
823 | for (i=0 ; i |
||
824 | { |
||
825 | bestscale = MAXINT; |
||
826 | for (ds=unsorted.next ; ds!= &unsorted ; ds=ds->next) |
||
827 | { |
||
828 | if (ds->scale < bestscale) |
||
829 | { |
||
830 | bestscale = ds->scale; |
||
831 | best = ds; |
||
832 | } |
||
833 | } |
||
834 | best->next->prev = best->prev; |
||
835 | best->prev->next = best->next; |
||
836 | best->next = &vsprsortedhead; |
||
837 | best->prev = vsprsortedhead.prev; |
||
838 | vsprsortedhead.prev->next = best; |
||
839 | vsprsortedhead.prev = best; |
||
840 | } |
||
841 | } |
||
842 | |||
843 | |||
844 | |||
845 | // |
||
846 | // R_DrawSprite |
||
847 | // |
||
848 | void R_DrawSprite (vissprite_t* spr) |
||
849 | { |
||
850 | drawseg_t* ds; |
||
851 | short clipbot[SCREENWIDTH]; |
||
852 | short cliptop[SCREENWIDTH]; |
||
853 | int x; |
||
854 | int r1; |
||
855 | int r2; |
||
856 | fixed_t scale; |
||
857 | fixed_t lowscale; |
||
858 | int silhouette; |
||
859 | |||
860 | for (x = spr->x1 ; x<=spr->x2 ; x++) |
||
861 | clipbot[x] = cliptop[x] = -2; |
||
862 | |||
863 | // Scan drawsegs from end to start for obscuring segs. |
||
864 | // The first drawseg that has a greater scale |
||
865 | // is the clip seg. |
||
866 | for (ds=ds_p-1 ; ds >= drawsegs ; ds--) |
||
867 | { |
||
868 | // determine if the drawseg obscures the sprite |
||
869 | if (ds->x1 > spr->x2 |
||
870 | || ds->x2 < spr->x1 |
||
871 | || (!ds->silhouette |
||
872 | && !ds->maskedtexturecol) ) |
||
873 | { |
||
874 | // does not cover sprite |
||
875 | continue; |
||
876 | } |
||
877 | |||
878 | r1 = ds->x1 < spr->x1 ? spr->x1 : ds->x1; |
||
879 | r2 = ds->x2 > spr->x2 ? spr->x2 : ds->x2; |
||
880 | |||
881 | if (ds->scale1 > ds->scale2) |
||
882 | { |
||
883 | lowscale = ds->scale2; |
||
884 | scale = ds->scale1; |
||
885 | } |
||
886 | else |
||
887 | { |
||
888 | lowscale = ds->scale1; |
||
889 | scale = ds->scale2; |
||
890 | } |
||
891 | |||
892 | if (scale < spr->scale |
||
893 | || ( lowscale < spr->scale |
||
894 | && !R_PointOnSegSide (spr->gx, spr->gy, ds->curline) ) ) |
||
895 | { |
||
896 | // masked mid texture? |
||
897 | if (ds->maskedtexturecol) |
||
898 | R_RenderMaskedSegRange (ds, r1, r2); |
||
899 | // seg is behind sprite |
||
900 | continue; |
||
901 | } |
||
902 | |||
903 | |||
904 | // clip this piece of the sprite |
||
905 | silhouette = ds->silhouette; |
||
906 | |||
907 | if (spr->gz >= ds->bsilheight) |
||
908 | silhouette &= ~SIL_BOTTOM; |
||
909 | |||
910 | if (spr->gzt <= ds->tsilheight) |
||
911 | silhouette &= ~SIL_TOP; |
||
912 | |||
913 | if (silhouette == 1) |
||
914 | { |
||
915 | // bottom sil |
||
916 | for (x=r1 ; x<=r2 ; x++) |
||
917 | if (clipbot[x] == -2) |
||
918 | clipbot[x] = ds->sprbottomclip[x]; |
||
919 | } |
||
920 | else if (silhouette == 2) |
||
921 | { |
||
922 | // top sil |
||
923 | for (x=r1 ; x<=r2 ; x++) |
||
924 | if (cliptop[x] == -2) |
||
925 | cliptop[x] = ds->sprtopclip[x]; |
||
926 | } |
||
927 | else if (silhouette == 3) |
||
928 | { |
||
929 | // both |
||
930 | for (x=r1 ; x<=r2 ; x++) |
||
931 | { |
||
932 | if (clipbot[x] == -2) |
||
933 | clipbot[x] = ds->sprbottomclip[x]; |
||
934 | if (cliptop[x] == -2) |
||
935 | cliptop[x] = ds->sprtopclip[x]; |
||
936 | } |
||
937 | } |
||
938 | |||
939 | } |
||
940 | |||
941 | // all clipping has been performed, so draw the sprite |
||
942 | |||
943 | // check for unclipped columns |
||
944 | for (x = spr->x1 ; x<=spr->x2 ; x++) |
||
945 | { |
||
946 | if (clipbot[x] == -2) |
||
947 | clipbot[x] = viewheight; |
||
948 | |||
949 | if (cliptop[x] == -2) |
||
950 | cliptop[x] = -1; |
||
951 | } |
||
952 | |||
953 | mfloorclip = clipbot; |
||
954 | mceilingclip = cliptop; |
||
955 | R_DrawVisSprite (spr, spr->x1, spr->x2); |
||
956 | } |
||
957 | |||
958 | |||
959 | |||
960 | |||
961 | // |
||
962 | // R_DrawMasked |
||
963 | // |
||
964 | void R_DrawMasked (void) |
||
965 | { |
||
966 | vissprite_t* spr; |
||
967 | drawseg_t* ds; |
||
968 | |||
969 | R_SortVisSprites (); |
||
970 | |||
971 | if (vissprite_p > vissprites) |
||
972 | { |
||
973 | // draw all vissprites back to front |
||
974 | for (spr = vsprsortedhead.next ; |
||
975 | spr != &vsprsortedhead ; |
||
976 | spr=spr->next) |
||
977 | { |
||
978 | |||
979 | R_DrawSprite (spr); |
||
980 | } |
||
981 | } |
||
982 | |||
983 | // render any remaining masked mid textures |
||
984 | for (ds=ds_p-1 ; ds >= drawsegs ; ds--) |
||
985 | if (ds->maskedtexturecol) |
||
986 | R_RenderMaskedSegRange (ds, ds->x1, ds->x2); |
||
987 | |||
988 | // draw the psprites on top of everything |
||
989 | // but does not draw on side views |
||
990 | if (!viewangleoffset) |
||
991 | R_DrawPlayerSprites (); |
||
992 | }=spr->=r2>=r2>=r2>=>>>>>=spr->> |
||
993 | |||
994 | |||
995 |