diff options
Diffstat (limited to 'apps/plugins/sdl/progs/quake/r_alias.c')
-rw-r--r-- | apps/plugins/sdl/progs/quake/r_alias.c | 753 |
1 files changed, 753 insertions, 0 deletions
diff --git a/apps/plugins/sdl/progs/quake/r_alias.c b/apps/plugins/sdl/progs/quake/r_alias.c new file mode 100644 index 0000000000..86074199bc --- /dev/null +++ b/apps/plugins/sdl/progs/quake/r_alias.c | |||
@@ -0,0 +1,753 @@ | |||
1 | /* | ||
2 | Copyright (C) 1996-1997 Id Software, Inc. | ||
3 | |||
4 | This program is free software; you can redistribute it and/or | ||
5 | modify it under the terms of the GNU General Public License | ||
6 | as published by the Free Software Foundation; either version 2 | ||
7 | of the License, or (at your option) any later version. | ||
8 | |||
9 | This program is distributed in the hope that it will be useful, | ||
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | ||
12 | |||
13 | See the GNU General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with this program; if not, write to the Free Software | ||
17 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
18 | |||
19 | */ | ||
20 | // r_alias.c: routines for setting up to draw alias models | ||
21 | |||
22 | #include "quakedef.h" | ||
23 | #include "r_local.h" | ||
24 | #include "d_local.h" // FIXME: shouldn't be needed (is needed for patch | ||
25 | // right now, but that should move) | ||
26 | |||
27 | #define LIGHT_MIN 5 // lowest light value we'll allow, to avoid the | ||
28 | // need for inner-loop light clamping | ||
29 | |||
30 | mtriangle_t *ptriangles; | ||
31 | affinetridesc_t r_affinetridesc; | ||
32 | |||
33 | void * acolormap; // FIXME: should go away | ||
34 | |||
35 | trivertx_t *r_apverts; | ||
36 | |||
37 | // TODO: these probably will go away with optimized rasterization | ||
38 | mdl_t *pmdl; | ||
39 | vec3_t r_plightvec; | ||
40 | int r_ambientlight; | ||
41 | float r_shadelight; | ||
42 | aliashdr_t *paliashdr; | ||
43 | finalvert_t *pfinalverts; | ||
44 | auxvert_t *pauxverts; | ||
45 | static float ziscale; | ||
46 | static model_t *pmodel; | ||
47 | |||
48 | static vec3_t alias_forward, alias_right, alias_up; | ||
49 | |||
50 | static maliasskindesc_t *pskindesc; | ||
51 | |||
52 | int r_amodels_drawn; | ||
53 | int a_skinwidth; | ||
54 | int r_anumverts; | ||
55 | |||
56 | float aliastransform[3][4]; | ||
57 | |||
58 | typedef struct { | ||
59 | int index0; | ||
60 | int index1; | ||
61 | } aedge_t; | ||
62 | |||
63 | static aedge_t aedges[12] = { | ||
64 | {0, 1}, {1, 2}, {2, 3}, {3, 0}, | ||
65 | {4, 5}, {5, 6}, {6, 7}, {7, 4}, | ||
66 | {0, 5}, {1, 4}, {2, 7}, {3, 6} | ||
67 | }; | ||
68 | |||
69 | #define NUMVERTEXNORMALS 162 | ||
70 | |||
71 | float r_avertexnormals[NUMVERTEXNORMALS][3] = { | ||
72 | #include "anorms.h" | ||
73 | }; | ||
74 | |||
75 | void R_AliasTransformAndProjectFinalVerts (finalvert_t *fv, | ||
76 | stvert_t *pstverts); | ||
77 | void R_AliasSetUpTransform (int trivial_accept); | ||
78 | void R_AliasTransformVector (vec3_t in, vec3_t out); | ||
79 | void R_AliasTransformFinalVert (finalvert_t *fv, auxvert_t *av, | ||
80 | trivertx_t *pverts, stvert_t *pstverts); | ||
81 | void R_AliasProjectFinalVert (finalvert_t *fv, auxvert_t *av); | ||
82 | |||
83 | |||
84 | /* | ||
85 | ================ | ||
86 | R_AliasCheckBBox | ||
87 | ================ | ||
88 | */ | ||
89 | qboolean R_AliasCheckBBox (void) | ||
90 | { | ||
91 | int i, flags, frame, numv; | ||
92 | aliashdr_t *pahdr; | ||
93 | float zi, basepts[8][3], v0, v1, frac; | ||
94 | finalvert_t *pv0, *pv1, viewpts[16]; | ||
95 | auxvert_t *pa0, *pa1, viewaux[16]; | ||
96 | maliasframedesc_t *pframedesc; | ||
97 | qboolean zclipped, zfullyclipped; | ||
98 | unsigned anyclip, allclip; | ||
99 | int minz; | ||
100 | |||
101 | // expand, rotate, and translate points into worldspace | ||
102 | |||
103 | currententity->trivial_accept = 0; | ||
104 | pmodel = currententity->model; | ||
105 | pahdr = Mod_Extradata (pmodel); | ||
106 | pmdl = (mdl_t *)((byte *)pahdr + pahdr->model); | ||
107 | |||
108 | R_AliasSetUpTransform (0); | ||
109 | |||
110 | // construct the base bounding box for this frame | ||
111 | frame = currententity->frame; | ||
112 | // TODO: don't repeat this check when drawing? | ||
113 | if ((frame >= pmdl->numframes) || (frame < 0)) | ||
114 | { | ||
115 | Con_DPrintf ("No such frame %d %s\n", frame, | ||
116 | pmodel->name); | ||
117 | frame = 0; | ||
118 | } | ||
119 | |||
120 | pframedesc = &pahdr->frames[frame]; | ||
121 | |||
122 | // x worldspace coordinates | ||
123 | basepts[0][0] = basepts[1][0] = basepts[2][0] = basepts[3][0] = | ||
124 | (float)pframedesc->bboxmin.v[0]; | ||
125 | basepts[4][0] = basepts[5][0] = basepts[6][0] = basepts[7][0] = | ||
126 | (float)pframedesc->bboxmax.v[0]; | ||
127 | |||
128 | // y worldspace coordinates | ||
129 | basepts[0][1] = basepts[3][1] = basepts[5][1] = basepts[6][1] = | ||
130 | (float)pframedesc->bboxmin.v[1]; | ||
131 | basepts[1][1] = basepts[2][1] = basepts[4][1] = basepts[7][1] = | ||
132 | (float)pframedesc->bboxmax.v[1]; | ||
133 | |||
134 | // z worldspace coordinates | ||
135 | basepts[0][2] = basepts[1][2] = basepts[4][2] = basepts[5][2] = | ||
136 | (float)pframedesc->bboxmin.v[2]; | ||
137 | basepts[2][2] = basepts[3][2] = basepts[6][2] = basepts[7][2] = | ||
138 | (float)pframedesc->bboxmax.v[2]; | ||
139 | |||
140 | zclipped = false; | ||
141 | zfullyclipped = true; | ||
142 | |||
143 | minz = 9999; | ||
144 | for (i=0; i<8 ; i++) | ||
145 | { | ||
146 | R_AliasTransformVector (&basepts[i][0], &viewaux[i].fv[0]); | ||
147 | |||
148 | if (viewaux[i].fv[2] < ALIAS_Z_CLIP_PLANE) | ||
149 | { | ||
150 | // we must clip points that are closer than the near clip plane | ||
151 | viewpts[i].flags = ALIAS_Z_CLIP; | ||
152 | zclipped = true; | ||
153 | } | ||
154 | else | ||
155 | { | ||
156 | if (viewaux[i].fv[2] < minz) | ||
157 | minz = viewaux[i].fv[2]; | ||
158 | viewpts[i].flags = 0; | ||
159 | zfullyclipped = false; | ||
160 | } | ||
161 | } | ||
162 | |||
163 | |||
164 | if (zfullyclipped) | ||
165 | { | ||
166 | return false; // everything was near-z-clipped | ||
167 | } | ||
168 | |||
169 | numv = 8; | ||
170 | |||
171 | if (zclipped) | ||
172 | { | ||
173 | // organize points by edges, use edges to get new points (possible trivial | ||
174 | // reject) | ||
175 | for (i=0 ; i<12 ; i++) | ||
176 | { | ||
177 | // edge endpoints | ||
178 | pv0 = &viewpts[aedges[i].index0]; | ||
179 | pv1 = &viewpts[aedges[i].index1]; | ||
180 | pa0 = &viewaux[aedges[i].index0]; | ||
181 | pa1 = &viewaux[aedges[i].index1]; | ||
182 | |||
183 | // if one end is clipped and the other isn't, make a new point | ||
184 | if (pv0->flags ^ pv1->flags) | ||
185 | { | ||
186 | frac = (ALIAS_Z_CLIP_PLANE - pa0->fv[2]) / | ||
187 | (pa1->fv[2] - pa0->fv[2]); | ||
188 | viewaux[numv].fv[0] = pa0->fv[0] + | ||
189 | (pa1->fv[0] - pa0->fv[0]) * frac; | ||
190 | viewaux[numv].fv[1] = pa0->fv[1] + | ||
191 | (pa1->fv[1] - pa0->fv[1]) * frac; | ||
192 | viewaux[numv].fv[2] = ALIAS_Z_CLIP_PLANE; | ||
193 | viewpts[numv].flags = 0; | ||
194 | numv++; | ||
195 | } | ||
196 | } | ||
197 | } | ||
198 | |||
199 | // project the vertices that remain after clipping | ||
200 | anyclip = 0; | ||
201 | allclip = ALIAS_XY_CLIP_MASK; | ||
202 | |||
203 | // TODO: probably should do this loop in ASM, especially if we use floats | ||
204 | for (i=0 ; i<numv ; i++) | ||
205 | { | ||
206 | // we don't need to bother with vertices that were z-clipped | ||
207 | if (viewpts[i].flags & ALIAS_Z_CLIP) | ||
208 | continue; | ||
209 | |||
210 | zi = 1.0 / viewaux[i].fv[2]; | ||
211 | |||
212 | // FIXME: do with chop mode in ASM, or convert to float | ||
213 | v0 = (viewaux[i].fv[0] * xscale * zi) + xcenter; | ||
214 | v1 = (viewaux[i].fv[1] * yscale * zi) + ycenter; | ||
215 | |||
216 | flags = 0; | ||
217 | |||
218 | if (v0 < r_refdef.fvrectx) | ||
219 | flags |= ALIAS_LEFT_CLIP; | ||
220 | if (v1 < r_refdef.fvrecty) | ||
221 | flags |= ALIAS_TOP_CLIP; | ||
222 | if (v0 > r_refdef.fvrectright) | ||
223 | flags |= ALIAS_RIGHT_CLIP; | ||
224 | if (v1 > r_refdef.fvrectbottom) | ||
225 | flags |= ALIAS_BOTTOM_CLIP; | ||
226 | |||
227 | anyclip |= flags; | ||
228 | allclip &= flags; | ||
229 | } | ||
230 | |||
231 | if (allclip) | ||
232 | return false; // trivial reject off one side | ||
233 | |||
234 | currententity->trivial_accept = !anyclip & !zclipped; | ||
235 | |||
236 | if (currententity->trivial_accept) | ||
237 | { | ||
238 | if (minz > (r_aliastransition + (pmdl->size * r_resfudge))) | ||
239 | { | ||
240 | currententity->trivial_accept |= 2; | ||
241 | } | ||
242 | } | ||
243 | |||
244 | return true; | ||
245 | } | ||
246 | |||
247 | |||
248 | /* | ||
249 | ================ | ||
250 | R_AliasTransformVector | ||
251 | ================ | ||
252 | */ | ||
253 | void R_AliasTransformVector (vec3_t in, vec3_t out) | ||
254 | { | ||
255 | out[0] = DotProduct(in, aliastransform[0]) + aliastransform[0][3]; | ||
256 | out[1] = DotProduct(in, aliastransform[1]) + aliastransform[1][3]; | ||
257 | out[2] = DotProduct(in, aliastransform[2]) + aliastransform[2][3]; | ||
258 | } | ||
259 | |||
260 | |||
261 | /* | ||
262 | ================ | ||
263 | R_AliasPreparePoints | ||
264 | |||
265 | General clipped case | ||
266 | ================ | ||
267 | */ | ||
268 | void R_AliasPreparePoints (void) | ||
269 | { | ||
270 | int i; | ||
271 | stvert_t *pstverts; | ||
272 | finalvert_t *fv; | ||
273 | auxvert_t *av; | ||
274 | mtriangle_t *ptri; | ||
275 | finalvert_t *pfv[3]; | ||
276 | |||
277 | pstverts = (stvert_t *)((byte *)paliashdr + paliashdr->stverts); | ||
278 | r_anumverts = pmdl->numverts; | ||
279 | fv = pfinalverts; | ||
280 | av = pauxverts; | ||
281 | |||
282 | for (i=0 ; i<r_anumverts ; i++, fv++, av++, r_apverts++, pstverts++) | ||
283 | { | ||
284 | R_AliasTransformFinalVert (fv, av, r_apverts, pstverts); | ||
285 | if (av->fv[2] < ALIAS_Z_CLIP_PLANE) | ||
286 | fv->flags |= ALIAS_Z_CLIP; | ||
287 | else | ||
288 | { | ||
289 | R_AliasProjectFinalVert (fv, av); | ||
290 | |||
291 | if (fv->v[0] < r_refdef.aliasvrect.x) | ||
292 | fv->flags |= ALIAS_LEFT_CLIP; | ||
293 | if (fv->v[1] < r_refdef.aliasvrect.y) | ||
294 | fv->flags |= ALIAS_TOP_CLIP; | ||
295 | if (fv->v[0] > r_refdef.aliasvrectright) | ||
296 | fv->flags |= ALIAS_RIGHT_CLIP; | ||
297 | if (fv->v[1] > r_refdef.aliasvrectbottom) | ||
298 | fv->flags |= ALIAS_BOTTOM_CLIP; | ||
299 | } | ||
300 | } | ||
301 | |||
302 | // | ||
303 | // clip and draw all triangles | ||
304 | // | ||
305 | r_affinetridesc.numtriangles = 1; | ||
306 | |||
307 | ptri = (mtriangle_t *)((byte *)paliashdr + paliashdr->triangles); | ||
308 | for (i=0 ; i<pmdl->numtris ; i++, ptri++) | ||
309 | { | ||
310 | pfv[0] = &pfinalverts[ptri->vertindex[0]]; | ||
311 | pfv[1] = &pfinalverts[ptri->vertindex[1]]; | ||
312 | pfv[2] = &pfinalverts[ptri->vertindex[2]]; | ||
313 | |||
314 | if ( pfv[0]->flags & pfv[1]->flags & pfv[2]->flags & (ALIAS_XY_CLIP_MASK | ALIAS_Z_CLIP) ) | ||
315 | continue; // completely clipped | ||
316 | |||
317 | if ( ! ( (pfv[0]->flags | pfv[1]->flags | pfv[2]->flags) & | ||
318 | (ALIAS_XY_CLIP_MASK | ALIAS_Z_CLIP) ) ) | ||
319 | { // totally unclipped | ||
320 | r_affinetridesc.pfinalverts = pfinalverts; | ||
321 | r_affinetridesc.ptriangles = ptri; | ||
322 | D_PolysetDraw (); | ||
323 | } | ||
324 | else | ||
325 | { // partially clipped | ||
326 | R_AliasClipTriangle (ptri); | ||
327 | } | ||
328 | } | ||
329 | } | ||
330 | |||
331 | |||
332 | /* | ||
333 | ================ | ||
334 | R_AliasSetUpTransform | ||
335 | ================ | ||
336 | */ | ||
337 | void R_AliasSetUpTransform (int trivial_accept) | ||
338 | { | ||
339 | int i; | ||
340 | float rotationmatrix[3][4], t2matrix[3][4]; | ||
341 | static float tmatrix[3][4]; | ||
342 | static float viewmatrix[3][4]; | ||
343 | vec3_t angles; | ||
344 | |||
345 | // TODO: should really be stored with the entity instead of being reconstructed | ||
346 | // TODO: should use a look-up table | ||
347 | // TODO: could cache lazily, stored in the entity | ||
348 | |||
349 | angles[ROLL] = currententity->angles[ROLL]; | ||
350 | angles[PITCH] = -currententity->angles[PITCH]; | ||
351 | angles[YAW] = currententity->angles[YAW]; | ||
352 | AngleVectors (angles, alias_forward, alias_right, alias_up); | ||
353 | |||
354 | tmatrix[0][0] = pmdl->scale[0]; | ||
355 | tmatrix[1][1] = pmdl->scale[1]; | ||
356 | tmatrix[2][2] = pmdl->scale[2]; | ||
357 | |||
358 | tmatrix[0][3] = pmdl->scale_origin[0]; | ||
359 | tmatrix[1][3] = pmdl->scale_origin[1]; | ||
360 | tmatrix[2][3] = pmdl->scale_origin[2]; | ||
361 | |||
362 | // TODO: can do this with simple matrix rearrangement | ||
363 | |||
364 | for (i=0 ; i<3 ; i++) | ||
365 | { | ||
366 | t2matrix[i][0] = alias_forward[i]; | ||
367 | t2matrix[i][1] = -alias_right[i]; | ||
368 | t2matrix[i][2] = alias_up[i]; | ||
369 | } | ||
370 | |||
371 | t2matrix[0][3] = -modelorg[0]; | ||
372 | t2matrix[1][3] = -modelorg[1]; | ||
373 | t2matrix[2][3] = -modelorg[2]; | ||
374 | |||
375 | // FIXME: can do more efficiently than full concatenation | ||
376 | R_ConcatTransforms (t2matrix, tmatrix, rotationmatrix); | ||
377 | |||
378 | // TODO: should be global, set when vright, etc., set | ||
379 | VectorCopy (vright, viewmatrix[0]); | ||
380 | VectorCopy (vup, viewmatrix[1]); | ||
381 | VectorInverse (viewmatrix[1]); | ||
382 | VectorCopy (vpn, viewmatrix[2]); | ||
383 | |||
384 | // viewmatrix[0][3] = 0; | ||
385 | // viewmatrix[1][3] = 0; | ||
386 | // viewmatrix[2][3] = 0; | ||
387 | |||
388 | R_ConcatTransforms (viewmatrix, rotationmatrix, aliastransform); | ||
389 | |||
390 | // do the scaling up of x and y to screen coordinates as part of the transform | ||
391 | // for the unclipped case (it would mess up clipping in the clipped case). | ||
392 | // Also scale down z, so 1/z is scaled 31 bits for free, and scale down x and y | ||
393 | // correspondingly so the projected x and y come out right | ||
394 | // FIXME: make this work for clipped case too? | ||
395 | if (trivial_accept) | ||
396 | { | ||
397 | for (i=0 ; i<4 ; i++) | ||
398 | { | ||
399 | aliastransform[0][i] *= aliasxscale * | ||
400 | (1.0 / ((float)0x8000 * 0x10000)); | ||
401 | aliastransform[1][i] *= aliasyscale * | ||
402 | (1.0 / ((float)0x8000 * 0x10000)); | ||
403 | aliastransform[2][i] *= 1.0 / ((float)0x8000 * 0x10000); | ||
404 | |||
405 | } | ||
406 | } | ||
407 | } | ||
408 | |||
409 | |||
410 | /* | ||
411 | ================ | ||
412 | R_AliasTransformFinalVert | ||
413 | ================ | ||
414 | */ | ||
415 | void R_AliasTransformFinalVert (finalvert_t *fv, auxvert_t *av, | ||
416 | trivertx_t *pverts, stvert_t *pstverts) | ||
417 | { | ||
418 | int temp; | ||
419 | float lightcos, *plightnormal; | ||
420 | |||
421 | av->fv[0] = DotProduct(pverts->v, aliastransform[0]) + | ||
422 | aliastransform[0][3]; | ||
423 | av->fv[1] = DotProduct(pverts->v, aliastransform[1]) + | ||
424 | aliastransform[1][3]; | ||
425 | av->fv[2] = DotProduct(pverts->v, aliastransform[2]) + | ||
426 | aliastransform[2][3]; | ||
427 | |||
428 | fv->v[2] = pstverts->s; | ||
429 | fv->v[3] = pstverts->t; | ||
430 | |||
431 | fv->flags = pstverts->onseam; | ||
432 | |||
433 | // lighting | ||
434 | plightnormal = r_avertexnormals[pverts->lightnormalindex]; | ||
435 | lightcos = DotProduct (plightnormal, r_plightvec); | ||
436 | temp = r_ambientlight; | ||
437 | |||
438 | if (lightcos < 0) | ||
439 | { | ||
440 | temp += (int)(r_shadelight * lightcos); | ||
441 | |||
442 | // clamp; because we limited the minimum ambient and shading light, we | ||
443 | // don't have to clamp low light, just bright | ||
444 | if (temp < 0) | ||
445 | temp = 0; | ||
446 | } | ||
447 | |||
448 | fv->v[4] = temp; | ||
449 | } | ||
450 | |||
451 | |||
452 | #if !id386 | ||
453 | |||
454 | /* | ||
455 | ================ | ||
456 | R_AliasTransformAndProjectFinalVerts | ||
457 | ================ | ||
458 | */ | ||
459 | void R_AliasTransformAndProjectFinalVerts (finalvert_t *fv, stvert_t *pstverts) | ||
460 | { | ||
461 | int i, temp; | ||
462 | float lightcos, *plightnormal, zi; | ||
463 | trivertx_t *pverts; | ||
464 | |||
465 | pverts = r_apverts; | ||
466 | |||
467 | for (i=0 ; i<r_anumverts ; i++, fv++, pverts++, pstverts++) | ||
468 | { | ||
469 | // transform and project | ||
470 | zi = 1.0 / (DotProduct(pverts->v, aliastransform[2]) + | ||
471 | aliastransform[2][3]); | ||
472 | |||
473 | // x, y, and z are scaled down by 1/2**31 in the transform, so 1/z is | ||
474 | // scaled up by 1/2**31, and the scaling cancels out for x and y in the | ||
475 | // projection | ||
476 | fv->v[5] = zi; | ||
477 | |||
478 | fv->v[0] = ((DotProduct(pverts->v, aliastransform[0]) + | ||
479 | aliastransform[0][3]) * zi) + aliasxcenter; | ||
480 | fv->v[1] = ((DotProduct(pverts->v, aliastransform[1]) + | ||
481 | aliastransform[1][3]) * zi) + aliasycenter; | ||
482 | |||
483 | fv->v[2] = pstverts->s; | ||
484 | fv->v[3] = pstverts->t; | ||
485 | fv->flags = pstverts->onseam; | ||
486 | |||
487 | // lighting | ||
488 | plightnormal = r_avertexnormals[pverts->lightnormalindex]; | ||
489 | lightcos = DotProduct (plightnormal, r_plightvec); | ||
490 | temp = r_ambientlight; | ||
491 | |||
492 | if (lightcos < 0) | ||
493 | { | ||
494 | temp += (int)(r_shadelight * lightcos); | ||
495 | |||
496 | // clamp; because we limited the minimum ambient and shading light, we | ||
497 | // don't have to clamp low light, just bright | ||
498 | if (temp < 0) | ||
499 | temp = 0; | ||
500 | } | ||
501 | |||
502 | fv->v[4] = temp; | ||
503 | } | ||
504 | } | ||
505 | |||
506 | #endif | ||
507 | |||
508 | |||
509 | /* | ||
510 | ================ | ||
511 | R_AliasProjectFinalVert | ||
512 | ================ | ||
513 | */ | ||
514 | void R_AliasProjectFinalVert (finalvert_t *fv, auxvert_t *av) | ||
515 | { | ||
516 | float zi; | ||
517 | |||
518 | // project points | ||
519 | zi = 1.0 / av->fv[2]; | ||
520 | |||
521 | fv->v[5] = zi * ziscale; | ||
522 | |||
523 | fv->v[0] = (av->fv[0] * aliasxscale * zi) + aliasxcenter; | ||
524 | fv->v[1] = (av->fv[1] * aliasyscale * zi) + aliasycenter; | ||
525 | } | ||
526 | |||
527 | |||
528 | /* | ||
529 | ================ | ||
530 | R_AliasPrepareUnclippedPoints | ||
531 | ================ | ||
532 | */ | ||
533 | void R_AliasPrepareUnclippedPoints (void) | ||
534 | { | ||
535 | stvert_t *pstverts; | ||
536 | finalvert_t *fv; | ||
537 | |||
538 | pstverts = (stvert_t *)((byte *)paliashdr + paliashdr->stverts); | ||
539 | r_anumverts = pmdl->numverts; | ||
540 | // FIXME: just use pfinalverts directly? | ||
541 | fv = pfinalverts; | ||
542 | |||
543 | R_AliasTransformAndProjectFinalVerts (fv, pstverts); | ||
544 | |||
545 | if (r_affinetridesc.drawtype) | ||
546 | D_PolysetDrawFinalVerts (fv, r_anumverts); | ||
547 | |||
548 | r_affinetridesc.pfinalverts = pfinalverts; | ||
549 | r_affinetridesc.ptriangles = (mtriangle_t *) | ||
550 | ((byte *)paliashdr + paliashdr->triangles); | ||
551 | r_affinetridesc.numtriangles = pmdl->numtris; | ||
552 | |||
553 | D_PolysetDraw (); | ||
554 | } | ||
555 | |||
556 | /* | ||
557 | =============== | ||
558 | R_AliasSetupSkin | ||
559 | =============== | ||
560 | */ | ||
561 | void R_AliasSetupSkin (void) | ||
562 | { | ||
563 | int skinnum; | ||
564 | int i, numskins; | ||
565 | maliasskingroup_t *paliasskingroup; | ||
566 | float *pskinintervals, fullskininterval; | ||
567 | float skintargettime, skintime; | ||
568 | |||
569 | skinnum = currententity->skinnum; | ||
570 | if ((skinnum >= pmdl->numskins) || (skinnum < 0)) | ||
571 | { | ||
572 | Con_DPrintf ("R_AliasSetupSkin: no such skin # %d\n", skinnum); | ||
573 | skinnum = 0; | ||
574 | } | ||
575 | |||
576 | pskindesc = ((maliasskindesc_t *) | ||
577 | ((byte *)paliashdr + paliashdr->skindesc)) + skinnum; | ||
578 | a_skinwidth = pmdl->skinwidth; | ||
579 | |||
580 | if (pskindesc->type == ALIAS_SKIN_GROUP) | ||
581 | { | ||
582 | paliasskingroup = (maliasskingroup_t *)((byte *)paliashdr + | ||
583 | pskindesc->skin); | ||
584 | pskinintervals = (float *) | ||
585 | ((byte *)paliashdr + paliasskingroup->intervals); | ||
586 | numskins = paliasskingroup->numskins; | ||
587 | fullskininterval = pskinintervals[numskins-1]; | ||
588 | |||
589 | skintime = cl.time + currententity->syncbase; | ||
590 | |||
591 | // when loading in Mod_LoadAliasSkinGroup, we guaranteed all interval | ||
592 | // values are positive, so we don't have to worry about division by 0 | ||
593 | skintargettime = skintime - | ||
594 | ((int)(skintime / fullskininterval)) * fullskininterval; | ||
595 | |||
596 | for (i=0 ; i<(numskins-1) ; i++) | ||
597 | { | ||
598 | if (pskinintervals[i] > skintargettime) | ||
599 | break; | ||
600 | } | ||
601 | |||
602 | pskindesc = &paliasskingroup->skindescs[i]; | ||
603 | } | ||
604 | |||
605 | r_affinetridesc.pskindesc = pskindesc; | ||
606 | r_affinetridesc.pskin = (void *)((byte *)paliashdr + pskindesc->skin); | ||
607 | r_affinetridesc.skinwidth = a_skinwidth; | ||
608 | r_affinetridesc.seamfixupX16 = (a_skinwidth >> 1) << 16; | ||
609 | r_affinetridesc.skinheight = pmdl->skinheight; | ||
610 | } | ||
611 | |||
612 | /* | ||
613 | ================ | ||
614 | R_AliasSetupLighting | ||
615 | ================ | ||
616 | */ | ||
617 | void R_AliasSetupLighting (alight_t *plighting) | ||
618 | { | ||
619 | |||
620 | // guarantee that no vertex will ever be lit below LIGHT_MIN, so we don't have | ||
621 | // to clamp off the bottom | ||
622 | r_ambientlight = plighting->ambientlight; | ||
623 | |||
624 | if (r_ambientlight < LIGHT_MIN) | ||
625 | r_ambientlight = LIGHT_MIN; | ||
626 | |||
627 | r_ambientlight = (255 - r_ambientlight) << VID_CBITS; | ||
628 | |||
629 | if (r_ambientlight < LIGHT_MIN) | ||
630 | r_ambientlight = LIGHT_MIN; | ||
631 | |||
632 | r_shadelight = plighting->shadelight; | ||
633 | |||
634 | if (r_shadelight < 0) | ||
635 | r_shadelight = 0; | ||
636 | |||
637 | r_shadelight *= VID_GRADES; | ||
638 | |||
639 | // rotate the lighting vector into the model's frame of reference | ||
640 | r_plightvec[0] = DotProduct (plighting->plightvec, alias_forward); | ||
641 | r_plightvec[1] = -DotProduct (plighting->plightvec, alias_right); | ||
642 | r_plightvec[2] = DotProduct (plighting->plightvec, alias_up); | ||
643 | } | ||
644 | |||
645 | /* | ||
646 | ================= | ||
647 | R_AliasSetupFrame | ||
648 | |||
649 | set r_apverts | ||
650 | ================= | ||
651 | */ | ||
652 | void R_AliasSetupFrame (void) | ||
653 | { | ||
654 | int frame; | ||
655 | int i, numframes; | ||
656 | maliasgroup_t *paliasgroup; | ||
657 | float *pintervals, fullinterval, targettime, time; | ||
658 | |||
659 | frame = currententity->frame; | ||
660 | if ((frame >= pmdl->numframes) || (frame < 0)) | ||
661 | { | ||
662 | Con_DPrintf ("R_AliasSetupFrame: no such frame %d\n", frame); | ||
663 | frame = 0; | ||
664 | } | ||
665 | |||
666 | if (paliashdr->frames[frame].type == ALIAS_SINGLE) | ||
667 | { | ||
668 | r_apverts = (trivertx_t *) | ||
669 | ((byte *)paliashdr + paliashdr->frames[frame].frame); | ||
670 | return; | ||
671 | } | ||
672 | |||
673 | paliasgroup = (maliasgroup_t *) | ||
674 | ((byte *)paliashdr + paliashdr->frames[frame].frame); | ||
675 | pintervals = (float *)((byte *)paliashdr + paliasgroup->intervals); | ||
676 | numframes = paliasgroup->numframes; | ||
677 | fullinterval = pintervals[numframes-1]; | ||
678 | |||
679 | time = cl.time + currententity->syncbase; | ||
680 | |||
681 | // | ||
682 | // when loading in Mod_LoadAliasGroup, we guaranteed all interval values | ||
683 | // are positive, so we don't have to worry about division by 0 | ||
684 | // | ||
685 | targettime = time - ((int)(time / fullinterval)) * fullinterval; | ||
686 | |||
687 | for (i=0 ; i<(numframes-1) ; i++) | ||
688 | { | ||
689 | if (pintervals[i] > targettime) | ||
690 | break; | ||
691 | } | ||
692 | |||
693 | r_apverts = (trivertx_t *) | ||
694 | ((byte *)paliashdr + paliasgroup->frames[i].frame); | ||
695 | } | ||
696 | |||
697 | |||
698 | /* | ||
699 | ================ | ||
700 | R_AliasDrawModel | ||
701 | ================ | ||
702 | */ | ||
703 | void R_AliasDrawModel (alight_t *plighting) | ||
704 | { | ||
705 | finalvert_t finalverts[MAXALIASVERTS + | ||
706 | ((CACHE_SIZE - 1) / sizeof(finalvert_t)) + 1]; | ||
707 | auxvert_t auxverts[MAXALIASVERTS]; | ||
708 | |||
709 | r_amodels_drawn++; | ||
710 | |||
711 | // cache align | ||
712 | pfinalverts = (finalvert_t *) | ||
713 | (((long)&finalverts[0] + CACHE_SIZE - 1) & ~(CACHE_SIZE - 1)); | ||
714 | pauxverts = &auxverts[0]; | ||
715 | |||
716 | paliashdr = (aliashdr_t *)Mod_Extradata (currententity->model); | ||
717 | pmdl = (mdl_t *)((byte *)paliashdr + paliashdr->model); | ||
718 | |||
719 | R_AliasSetupSkin (); | ||
720 | R_AliasSetUpTransform (currententity->trivial_accept); | ||
721 | R_AliasSetupLighting (plighting); | ||
722 | R_AliasSetupFrame (); | ||
723 | |||
724 | if (!currententity->colormap) | ||
725 | Sys_Error ("R_AliasDrawModel: !currententity->colormap"); | ||
726 | |||
727 | r_affinetridesc.drawtype = (currententity->trivial_accept == 3) && | ||
728 | r_recursiveaffinetriangles; | ||
729 | |||
730 | if (r_affinetridesc.drawtype) | ||
731 | { | ||
732 | D_PolysetUpdateTables (); // FIXME: precalc... | ||
733 | } | ||
734 | else | ||
735 | { | ||
736 | #if id386 | ||
737 | D_Aff8Patch (currententity->colormap); | ||
738 | #endif | ||
739 | } | ||
740 | |||
741 | acolormap = currententity->colormap; | ||
742 | |||
743 | if (currententity != &cl.viewent) | ||
744 | ziscale = (float)0x8000 * (float)0x10000; | ||
745 | else | ||
746 | ziscale = (float)0x8000 * (float)0x10000 * 3.0; | ||
747 | |||
748 | if (currententity->trivial_accept) | ||
749 | R_AliasPrepareUnclippedPoints (); | ||
750 | else | ||
751 | R_AliasPreparePoints (); | ||
752 | } | ||
753 | |||