9 // LordHavoc: vertex array
11 float *modelaliasvert;
14 byte *aliasvertcolor2;
15 zymbonematrix *zymbonepose;
20 void makechrometexture()
26 fractalnoise(noise, 64, 16);
28 // convert to RGBA data
29 for (i = 0;i < 64*64;i++)
31 data[i][0] = data[i][1] = data[i][2] = noise[i];
35 chrometexture = GL_LoadTexture ("chrometexture", 64, 64, &data[0][0], true, false, 4);
38 void gl_models_start()
40 // allocate vertex processing arrays
41 aliasvert = qmalloc(sizeof(float[MD2MAX_VERTS][3]));
42 modelaliasvert = qmalloc(sizeof(float[MD2MAX_VERTS][3]));
43 aliasvertnorm = qmalloc(sizeof(float[MD2MAX_VERTS][3]));
44 aliasvertcolor = qmalloc(sizeof(byte[MD2MAX_VERTS][4]));
45 aliasvertcolor2 = qmalloc(sizeof(byte[MD2MAX_VERTS][4])); // used temporarily for tinted coloring
46 zymbonepose = qmalloc(sizeof(zymbonematrix[256]));
47 aliasvertusage = qmalloc(sizeof(int[MD2MAX_VERTS]));
51 void gl_models_shutdown()
55 qfree(aliasvertcolor);
56 qfree(aliasvertcolor2);
58 qfree(aliasvertusage);
63 R_RegisterModule("GL_Models", gl_models_start, gl_models_shutdown);
66 extern vec3_t softwaretransform_x;
67 extern vec3_t softwaretransform_y;
68 extern vec3_t softwaretransform_z;
69 extern vec_t softwaretransform_scale;
70 extern vec3_t softwaretransform_offset;
71 extern cvar_t r_modelsdonttransformnormals;
72 void R_AliasLerpVerts(int vertcount, float lerp, trivert2 *verts1, vec3_t scale1, vec3_t translate1, trivert2 *verts2, vec3_t scale2, vec3_t translate2)
75 vec3_t point, matrix_x, matrix_y, matrix_z;
79 VectorScale(softwaretransform_x, softwaretransform_scale, matrix_x);
80 VectorScale(softwaretransform_y, softwaretransform_scale, matrix_y);
81 VectorScale(softwaretransform_z, softwaretransform_scale, matrix_z);
82 if (lerp < 0) lerp = 0;
83 if (lerp > 1) lerp = 1;
86 float ilerp, ilerp127, lerp127, scalex1, scalex2, translatex, scaley1, scaley2, translatey, scalez1, scalez2, translatez;
88 ilerp127 = ilerp * (1.0 / 127.0);
89 lerp127 = lerp * (1.0 / 127.0);
90 // calculate combined interpolation variables
91 scalex1 = scale1[0] * ilerp;scalex2 = scale2[0] * lerp;translatex = translate1[0] * ilerp + translate2[0] * lerp;
92 scaley1 = scale1[1] * ilerp;scaley2 = scale2[1] * lerp;translatey = translate1[1] * ilerp + translate2[1] * lerp;
93 scalez1 = scale1[2] * ilerp;scalez2 = scale2[2] * lerp;translatez = translate1[2] * ilerp + translate2[2] * lerp;
95 if (r_modelsdonttransformnormals.value)
97 float *modelav = modelaliasvert;
98 for (i = 0;i < vertcount;i++)
100 // rotate, scale, and translate the vertex locations
101 point[0] = verts1->v[0] * scalex1 + verts2->v[0] * scalex2 + translatex;
102 point[1] = verts1->v[1] * scaley1 + verts2->v[1] * scaley2 + translatey;
103 point[2] = verts1->v[2] * scalez1 + verts2->v[2] * scalez2 + translatez;
104 // save mostly un-transformed copy for lighting
105 modelav[0] = point[0] * softwaretransform_scale;
106 modelav[1] = point[1] * softwaretransform_scale;
107 modelav[2] = point[2] * softwaretransform_scale;
108 av[0] = point[0] * matrix_x[0] + point[1] * matrix_y[0] + point[2] * matrix_z[0] + softwaretransform_offset[0];
109 av[1] = point[0] * matrix_x[1] + point[1] * matrix_y[1] + point[2] * matrix_z[1] + softwaretransform_offset[1];
110 av[2] = point[0] * matrix_x[2] + point[1] * matrix_y[2] + point[2] * matrix_z[2] + softwaretransform_offset[2];
111 // decompress but do not transform the normals
112 avn[0] = verts1->n[0] * ilerp127 + verts2->n[0] * lerp127;
113 avn[1] = verts1->n[1] * ilerp127 + verts2->n[1] * lerp127;
114 avn[2] = verts1->n[2] * ilerp127 + verts2->n[2] * lerp127;
123 for (i = 0;i < vertcount;i++)
125 // rotate, scale, and translate the vertex locations
126 point[0] = verts1->v[0] * scalex1 + verts2->v[0] * scalex2 + translatex;
127 point[1] = verts1->v[1] * scaley1 + verts2->v[1] * scaley2 + translatey;
128 point[2] = verts1->v[2] * scalez1 + verts2->v[2] * scalez2 + translatez;
129 av[0] = point[0] * matrix_x[0] + point[1] * matrix_y[0] + point[2] * matrix_z[0] + softwaretransform_offset[0];
130 av[1] = point[0] * matrix_x[1] + point[1] * matrix_y[1] + point[2] * matrix_z[1] + softwaretransform_offset[1];
131 av[2] = point[0] * matrix_x[2] + point[1] * matrix_y[2] + point[2] * matrix_z[2] + softwaretransform_offset[2];
132 // rotate the normals
133 point[0] = verts1->n[0] * ilerp127 + verts2->n[0] * lerp127;
134 point[1] = verts1->n[1] * ilerp127 + verts2->n[1] * lerp127;
135 point[2] = verts1->n[2] * ilerp127 + verts2->n[2] * lerp127;
136 avn[0] = point[0] * softwaretransform_x[0] + point[1] * softwaretransform_y[0] + point[2] * softwaretransform_z[0];
137 avn[1] = point[0] * softwaretransform_x[1] + point[1] * softwaretransform_y[1] + point[2] * softwaretransform_z[1];
138 avn[2] = point[0] * softwaretransform_x[2] + point[1] * softwaretransform_y[2] + point[2] * softwaretransform_z[2];
148 if (r_modelsdonttransformnormals.value)
150 float *modelav = modelaliasvert;
151 for (i = 0;i < vertcount;i++)
153 // rotate, scale, and translate the vertex locations
154 point[0] = verts1->v[0] * scale1[0] + translate1[0];
155 point[1] = verts1->v[1] * scale1[1] + translate1[1];
156 point[2] = verts1->v[2] * scale1[2] + translate1[2];
157 // save mostly un-transformed copy for lighting
158 modelav[0] = point[0] * softwaretransform_scale;
159 modelav[1] = point[1] * softwaretransform_scale;
160 modelav[2] = point[2] * softwaretransform_scale;
161 av[0] = point[0] * matrix_x[0] + point[1] * matrix_y[0] + point[2] * matrix_z[0] + softwaretransform_offset[0];
162 av[1] = point[0] * matrix_x[1] + point[1] * matrix_y[1] + point[2] * matrix_z[1] + softwaretransform_offset[1];
163 av[2] = point[0] * matrix_x[2] + point[1] * matrix_y[2] + point[2] * matrix_z[2] + softwaretransform_offset[2];
164 // decompress normal but do not rotate it
165 avn[0] = verts1->n[0] * (1.0f / 127.0f);
166 avn[1] = verts1->n[1] * (1.0f / 127.0f);
167 avn[2] = verts1->n[2] * (1.0f / 127.0f);
176 for (i = 0;i < vertcount;i++)
178 // rotate, scale, and translate the vertex locations
179 point[0] = verts1->v[0] * scale1[0] + translate1[0];
180 point[1] = verts1->v[1] * scale1[1] + translate1[1];
181 point[2] = verts1->v[2] * scale1[2] + translate1[2];
182 av[0] = point[0] * matrix_x[0] + point[1] * matrix_y[0] + point[2] * matrix_z[0] + softwaretransform_offset[0];
183 av[1] = point[0] * matrix_x[1] + point[1] * matrix_y[1] + point[2] * matrix_z[1] + softwaretransform_offset[1];
184 av[2] = point[0] * matrix_x[2] + point[1] * matrix_y[2] + point[2] * matrix_z[2] + softwaretransform_offset[2];
185 // rotate the normals
186 point[0] = verts1->n[0] * (1.0f / 127.0f);
187 point[1] = verts1->n[1] * (1.0f / 127.0f);
188 point[2] = verts1->n[2] * (1.0f / 127.0f);
189 avn[0] = point[0] * softwaretransform_x[0] + point[1] * softwaretransform_y[0] + point[2] * softwaretransform_z[0];
190 avn[1] = point[0] * softwaretransform_x[1] + point[1] * softwaretransform_y[1] + point[2] * softwaretransform_z[1];
191 avn[2] = point[0] * softwaretransform_x[2] + point[1] * softwaretransform_y[2] + point[2] * softwaretransform_z[2];
200 float R_CalcAnimLerp(entity_t *ent, int pose, float lerpscale)
202 if (ent->draw_lastmodel == ent->model && ent->draw_lerpstart <= cl.time)
204 if (pose != ent->draw_pose)
206 ent->draw_lastpose = ent->draw_pose;
207 ent->draw_pose = pose;
208 ent->draw_lerpstart = cl.time;
212 return ((cl.time - ent->draw_lerpstart) * lerpscale);
214 else // uninitialized
216 ent->draw_lastmodel = ent->model;
217 ent->draw_lastpose = ent->draw_pose = pose;
218 ent->draw_lerpstart = cl.time;
223 void GL_DrawModelMesh(int skin, byte *colors, maliashdr_t *maliashdr)
228 glBindTexture(GL_TEXTURE_2D, skin);
232 glColor3f(0.5f, 0.5f, 0.5f);
234 glColor3f(1.0f, 1.0f, 1.0f);
236 if (gl_vertexarrays.value)
240 qglColorPointer(4, GL_UNSIGNED_BYTE, 0, colors);
241 glEnableClientState(GL_COLOR_ARRAY);
244 qglTexCoordPointer(2, GL_FLOAT, 0, (void *)((int) maliashdr->texdata + (int) maliashdr));
245 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
247 qglDrawElements(GL_TRIANGLES, maliashdr->numtris * 3, GL_UNSIGNED_SHORT, (void *)((int) maliashdr + maliashdr->tridata));
249 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
252 glDisableClientState(GL_COLOR_ARRAY);
256 unsigned short *in, index;
258 in = (void *)((int) maliashdr + maliashdr->tridata);
259 glBegin(GL_TRIANGLES);
260 tex = (void *)((int) maliashdr + maliashdr->texdata);
261 for (i = 0;i < maliashdr->numtris * 3;i++)
264 glTexCoord2f(tex[index*2], tex[index*2+1]);
266 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));
267 glVertex3fv(&aliasvert[index*3]);
271 // leave it in a state for additional passes
274 glBlendFunc(GL_SRC_ALPHA, GL_ONE); // additive
277 void R_TintModel(byte *in, byte *out, int verts, byte *color)
283 for (i = 0;i < verts;i++)
285 out[0] = (byte) ((in[0] * r) >> 8);
286 out[1] = (byte) ((in[1] * g) >> 8);
287 out[2] = (byte) ((in[2] * b) >> 8);
300 extern vec3_t lightspot;
301 void R_LightModel(int numverts, vec3_t center, vec3_t basecolor);
302 void R_DrawAliasFrame (maliashdr_t *maliashdr, float alpha, vec3_t color, entity_t *ent, int shadow, vec3_t org, vec3_t angles, int frame, int *skin, int colormap, int effects, int flags)
305 float lerpscale, lerp;
306 maliasframe_t *frameinfo;
308 softwaretransformforentity(ent);
310 if ((frame >= maliashdr->numframes) || (frame < 0))
312 Con_DPrintf ("R_AliasSetupFrame: no such frame %d\n", frame);
316 frameinfo = ((maliasframe_t *)((int) maliashdr + maliashdr->framedata)) + frame;
317 pose = frameinfo->start;
319 if (frameinfo->length > 1)
321 lerpscale = frameinfo->rate;
322 pose += (int)(cl.time * frameinfo->rate) % frameinfo->length;
327 lerp = R_CalcAnimLerp(ent, pose, lerpscale);
329 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);
331 // prep the vertex array as early as possible
334 if (gl_vertexarrays.value)
336 qglVertexPointer(3, GL_FLOAT, 0, aliasvert);
337 glEnableClientState(GL_VERTEX_ARRAY);
341 R_LightModel(maliashdr->numverts, org, color);
345 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
346 glShadeModel(GL_SMOOTH);
347 if (effects & EF_ADDITIVE)
349 glBlendFunc(GL_SRC_ALPHA, GL_ONE); // additive rendering
353 else if (alpha != 1.0)
355 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
365 if (skin[0] || skin[1] || skin[2] || skin[3] || skin[4])
367 if (colormap >= 0 && (skin[0] || skin[1] || skin[2]))
371 GL_DrawModelMesh(skin[0], aliasvertcolor, maliashdr);
374 c = (colormap & 0xF) << 4;c += (c >= 128 && c < 224) ? 4 : 12; // 128-224 are backwards ranges
375 R_TintModel(aliasvertcolor, aliasvertcolor2, maliashdr->numverts, (byte *) (&d_8to24table[c]));
376 GL_DrawModelMesh(skin[1], aliasvertcolor2, maliashdr);
380 c = colormap & 0xF0 ;c += (c >= 128 && c < 224) ? 4 : 12; // 128-224 are backwards ranges
381 R_TintModel(aliasvertcolor, aliasvertcolor2, maliashdr->numverts, (byte *) (&d_8to24table[c]));
382 GL_DrawModelMesh(skin[2], aliasvertcolor2, maliashdr);
387 if (skin[4]) GL_DrawModelMesh(skin[4], aliasvertcolor, maliashdr);
390 if (skin[0]) GL_DrawModelMesh(skin[0], aliasvertcolor, maliashdr);
391 if (skin[1]) GL_DrawModelMesh(skin[1], aliasvertcolor, maliashdr);
392 if (skin[2]) GL_DrawModelMesh(skin[2], aliasvertcolor, maliashdr);
395 if (skin[3]) GL_DrawModelMesh(skin[3], NULL, maliashdr);
398 GL_DrawModelMesh(0, NULL, maliashdr);
403 glDisable (GL_TEXTURE_2D);
404 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
406 glDepthMask(0); // disable zbuffer updates
408 VectorSubtract(org, r_refdef.vieworg, diff);
409 glColor4f(fogcolor[0], fogcolor[1], fogcolor[2], exp(fogdensity/DotProduct(diff,diff)));
411 if (gl_vertexarrays.value)
413 qglDrawElements(GL_TRIANGLES, maliashdr->numtris * 3, GL_UNSIGNED_SHORT, (void *)((int) maliashdr + maliashdr->tridata));
418 in = (void *)((int) maliashdr + maliashdr->tridata);
419 glBegin(GL_TRIANGLES);
420 for (i = 0;i < maliashdr->numtris * 3;i++)
421 glVertex3fv(&aliasvert[*in++ * 3]);
425 glEnable (GL_TEXTURE_2D);
428 if (gl_vertexarrays.value)
429 glDisableClientState(GL_VERTEX_ARRAY);
431 if (!fogenabled && r_shadows.value && !(effects & EF_ADDITIVE) && shadow)
433 // flatten it to make a shadow
434 float *av = aliasvert + 2, l = lightspot[2] + 0.125;
436 for (i = 0;i < maliashdr->numverts;i++, av+=3)
439 glDisable (GL_TEXTURE_2D);
440 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
442 glDepthMask(0); // disable zbuffer updates
443 glColor4f (0,0,0,0.5 * alpha);
445 if (gl_vertexarrays.value)
447 qglVertexPointer(3, GL_FLOAT, 0, aliasvert);
448 glEnableClientState(GL_VERTEX_ARRAY);
449 qglDrawElements(GL_TRIANGLES, maliashdr->numtris * 3, GL_UNSIGNED_SHORT, (void *)((int) maliashdr + maliashdr->tridata));
450 glDisableClientState(GL_VERTEX_ARRAY);
455 in = (void *)((int) maliashdr + maliashdr->tridata);
456 glBegin(GL_TRIANGLES);
457 for (i = 0;i < maliashdr->numtris * 3;i++)
458 glVertex3fv(&aliasvert[*in++ * 3]);
462 glEnable (GL_TEXTURE_2D);
466 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
477 void R_DrawQ2AliasFrame (md2mem_t *pheader, float alpha, vec3_t color, entity_t *ent, int shadow, vec3_t org, vec3_t angles, int frame, int skin, int effects, int flags)
481 md2memframe_t *frame1, *frame2;
484 glBindTexture(GL_TEXTURE_2D, skin);
486 softwaretransformforentity(ent);
488 if ((frame >= pheader->num_frames) || (frame < 0))
490 Con_DPrintf ("R_SetupQ2AliasFrame: no such frame %d\n", frame);
494 lerp = R_CalcAnimLerp(ent, frame, 10);
496 frame1 = (void *)((int) pheader + pheader->ofs_frames + (pheader->framesize * ent->draw_lastpose));
497 frame2 = (void *)((int) pheader + pheader->ofs_frames + (pheader->framesize * ent->draw_pose));
498 R_AliasLerpVerts(pheader->num_xyz, lerp, frame1->verts, frame1->scale, frame1->translate, frame2->verts, frame2->scale, frame2->translate);
500 R_LightModel(pheader->num_xyz, org, color);
504 if (gl_vertexarrays.value)
506 // LordHavoc: big mess...
507 // using arrays only slightly, although it is enough to prevent duplicates
508 // (saving half the transforms)
509 qglVertexPointer(3, GL_FLOAT, 0, aliasvert);
510 qglColorPointer(4, GL_UNSIGNED_BYTE, 0, aliasvertcolor);
511 glEnableClientState(GL_VERTEX_ARRAY);
512 glEnableClientState(GL_COLOR_ARRAY);
514 order = (int *)((int)pheader + pheader->ofs_glcmds);
517 if (!(count = *order++))
520 glBegin(GL_TRIANGLE_STRIP);
523 glBegin(GL_TRIANGLE_FAN);
528 glTexCoord2f(((float *)order)[0], ((float *)order)[1]);
529 qglArrayElement(order[2]);
535 glDisableClientState(GL_COLOR_ARRAY);
536 glDisableClientState(GL_VERTEX_ARRAY);
540 order = (int *)((int)pheader + pheader->ofs_glcmds);
543 if (!(count = *order++))
546 glBegin(GL_TRIANGLE_STRIP);
549 glBegin(GL_TRIANGLE_FAN);
554 glTexCoord2f(((float *)order)[0], ((float *)order)[1]);
555 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));
556 glVertex3fv(&aliasvert[order[2] * 3]);
565 glDisable (GL_TEXTURE_2D);
566 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
568 glDepthMask(0); // disable zbuffer updates
571 VectorSubtract(org, r_refdef.vieworg, diff);
572 glColor4f(fogcolor[0], fogcolor[1], fogcolor[2], exp(fogdensity/DotProduct(diff,diff)));
575 if (gl_vertexarrays.value)
577 // LordHavoc: big mess...
578 // using arrays only slightly, although it is enough to prevent duplicates
579 // (saving half the transforms)
580 qglVertexPointer(3, GL_FLOAT, 0, aliasvert);
581 glEnableClientState(GL_VERTEX_ARRAY);
583 order = (int *)((int)pheader + pheader->ofs_glcmds);
586 if (!(count = *order++))
589 glBegin(GL_TRIANGLE_STRIP);
592 glBegin(GL_TRIANGLE_FAN);
597 qglArrayElement(order[2]);
603 glDisableClientState(GL_VERTEX_ARRAY);
607 order = (int *)((int)pheader + pheader->ofs_glcmds);
610 if (!(count = *order++))
613 glBegin(GL_TRIANGLE_STRIP);
616 glBegin(GL_TRIANGLE_FAN);
621 glVertex3fv(&aliasvert[order[2] * 3]);
628 glEnable (GL_TEXTURE_2D);
632 if (!fogenabled && r_shadows.value && !(effects & EF_ADDITIVE) && shadow)
635 float *av = aliasvert + 2, l = lightspot[2] + 0.125;
637 for (i = 0;i < pheader->num_xyz;i++, av+=3)
640 glDisable (GL_TEXTURE_2D);
641 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
643 glDepthMask(0); // disable zbuffer updates
644 glColor4f (0,0,0,0.5 * alpha);
646 if (gl_vertexarrays.value)
648 qglVertexPointer(3, GL_FLOAT, 0, aliasvert);
649 glEnableClientState(GL_VERTEX_ARRAY);
653 if (!(count = *order++))
656 glBegin(GL_TRIANGLE_STRIP);
659 glBegin(GL_TRIANGLE_FAN);
664 qglArrayElement(order[2]);
670 glDisableClientState(GL_VERTEX_ARRAY);
676 if (!(count = *order++))
679 glBegin(GL_TRIANGLE_STRIP);
682 glBegin(GL_TRIANGLE_FAN);
687 glVertex3fv(&aliasvert[order[2] * 3]);
694 glEnable (GL_TEXTURE_2D);
698 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
703 void ZymoticLerpBones(int count, float lerp2, zymbonematrix *bone1, zymbonematrix *bone2, zymbone_t *bone, float rootorigin[3], float rootangles[3])
706 zymbonematrix *out, rootmatrix, m;
709 AngleVectors(rootangles, rootmatrix.m[0], rootmatrix.m[1], rootmatrix.m[2]);
710 rootmatrix.m[0][3] = rootorigin[0];
711 rootmatrix.m[1][3] = rootorigin[1];
712 rootmatrix.m[2][3] = rootorigin[2];
713 if (lerp1 != 1) // interpolation
717 // interpolate matrices
718 m.m[0][0] = bone1->m[0][0] * lerp1 + bone2->m[0][0] * lerp2;
719 m.m[0][1] = bone1->m[0][1] * lerp1 + bone2->m[0][1] * lerp2;
720 m.m[0][2] = bone1->m[0][2] * lerp1 + bone2->m[0][2] * lerp2;
721 m.m[0][3] = bone1->m[0][3] * lerp1 + bone2->m[0][3] * lerp2;
722 m.m[1][0] = bone1->m[1][0] * lerp1 + bone2->m[1][0] * lerp2;
723 m.m[1][1] = bone1->m[1][1] * lerp1 + bone2->m[1][1] * lerp2;
724 m.m[1][2] = bone1->m[1][2] * lerp1 + bone2->m[1][2] * lerp2;
725 m.m[1][3] = bone1->m[1][3] * lerp1 + bone2->m[1][3] * lerp2;
726 m.m[2][0] = bone1->m[2][0] * lerp1 + bone2->m[2][0] * lerp2;
727 m.m[2][1] = bone1->m[2][1] * lerp1 + bone2->m[2][1] * lerp2;
728 m.m[2][2] = bone1->m[2][2] * lerp1 + bone2->m[2][2] * lerp2;
729 m.m[2][3] = bone1->m[2][3] * lerp1 + bone2->m[2][3] * lerp2;
730 if (bone->parent >= 0)
731 R_ConcatTransforms(&zymbonepose[bone->parent].m[0], &m.m[0], &out->m[0]);
733 R_ConcatTransforms(&rootmatrix.m[0], &m.m[0], &out->m[0]);
740 else // no interpolation
744 if (bone->parent >= 0)
745 R_ConcatTransforms(&zymbonepose[bone->parent].m[0], &bone1->m[0], &out->m[0]);
747 R_ConcatTransforms(&rootmatrix.m[0], &bone1->m[0], &out->m[0]);
755 void ZymoticTransformVerts(int vertcount, int *bonecounts, zymvertex_t *vert)
758 float *out = aliasvert;
759 zymbonematrix *matrix;
765 matrix = &zymbonepose[vert->bonenum];
766 out[0] = vert->origin[0] * matrix->m[0][0] + vert->origin[1] * matrix->m[0][1] + vert->origin[2] * matrix->m[0][2] + matrix->m[0][3];
767 out[1] = vert->origin[0] * matrix->m[1][0] + vert->origin[1] * matrix->m[1][1] + vert->origin[2] * matrix->m[1][2] + matrix->m[1][3];
768 out[2] = vert->origin[0] * matrix->m[2][0] + vert->origin[1] * matrix->m[2][1] + vert->origin[2] * matrix->m[2][2] + matrix->m[2][3];
776 matrix = &zymbonepose[vert->bonenum];
777 out[0] += vert->origin[0] * matrix->m[0][0] + vert->origin[1] * matrix->m[0][1] + vert->origin[2] * matrix->m[0][2] + matrix->m[0][3];
778 out[1] += vert->origin[0] * matrix->m[1][0] + vert->origin[1] * matrix->m[1][1] + vert->origin[2] * matrix->m[1][2] + matrix->m[1][3];
779 out[2] += vert->origin[0] * matrix->m[2][0] + vert->origin[1] * matrix->m[2][1] + vert->origin[2] * matrix->m[2][2] + matrix->m[2][3];
789 void ZymoticCalcNormals(int vertcount, int shadercount, int *renderlist)
792 float *out, v1[3], v2[3], normal[3];
797 for (a = 1;a < 4096;a++)
798 ixtable[a] = 1.0f / a;
801 memset(aliasvertnorm, 0, sizeof(float[3]) * vertcount);
802 memset(aliasvertusage, 0, sizeof(int) * vertcount);
803 // parse render list and accumulate surface normals
812 v1[0] = aliasvert[a+0] - aliasvert[b+0];
813 v1[1] = aliasvert[a+1] - aliasvert[b+1];
814 v1[2] = aliasvert[a+2] - aliasvert[b+2];
815 v2[0] = aliasvert[c+0] - aliasvert[b+0];
816 v2[1] = aliasvert[c+1] - aliasvert[b+1];
817 v2[2] = aliasvert[c+2] - aliasvert[b+2];
818 CrossProduct(v1, v2, normal);
819 VectorNormalize(normal);
820 // add surface normal to vertices
821 aliasvertnorm[a+0] += normal[0];
822 aliasvertnorm[a+1] += normal[1];
823 aliasvertnorm[a+2] += normal[2];
825 aliasvertnorm[b+0] += normal[0];
826 aliasvertnorm[b+1] += normal[1];
827 aliasvertnorm[b+2] += normal[2];
829 aliasvertnorm[c+0] += normal[0];
830 aliasvertnorm[c+1] += normal[1];
831 aliasvertnorm[c+2] += normal[2];
836 // average surface normals
853 void GL_DrawZymoticModelMesh(byte *colors, zymtype1header_t *m)
855 int i, c, *renderlist, *texturenum;
858 renderlist = (int *)(m->lump_render.start + (int) m);
859 texturenum = (int *)(m->lump_shaders.start + (int) m);
860 if (gl_vertexarrays.value)
862 qglVertexPointer(3, GL_FLOAT, 0, aliasvert);
863 glEnableClientState(GL_VERTEX_ARRAY);
865 qglColorPointer(4, GL_UNSIGNED_BYTE, 0, colors);
866 glEnableClientState(GL_COLOR_ARRAY);
868 qglTexCoordPointer(2, GL_FLOAT, 0, (float *)(m->lump_texcoords.start + (int) m));
869 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
871 for (i = 0;i < m->numshaders;i++)
873 c = (*renderlist++) * 3;
874 glBindTexture(GL_TEXTURE_2D, *texturenum++);
875 qglDrawElements(GL_TRIANGLES, c, GL_UNSIGNED_INT, renderlist);
879 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
881 glDisableClientState(GL_COLOR_ARRAY);
883 glDisableClientState(GL_VERTEX_ARRAY);
889 tex = (float *)(m->lump_texcoords.start + (int) m);
891 for (i = 0;i < m->numshaders;i++)
894 glBindTexture(GL_TEXTURE_2D, *texturenum++);
895 glBegin(GL_TRIANGLES);
898 index = *renderlist++;
899 glTexCoord2fv(tex + index*2);
900 glColor4ubv(colors + index*4);
901 glVertex3fv(aliasvert + index*3);
902 index = *renderlist++;
903 glTexCoord2fv(tex + index*2);
904 glColor4ubv(colors + index*4);
905 glVertex3fv(aliasvert + index*3);
906 index = *renderlist++;
907 glTexCoord2fv(tex + index*2);
908 glColor4ubv(colors + index*4);
909 glVertex3fv(aliasvert + index*3);
916 void GL_DrawZymoticModelMeshFog(vec3_t org, zymtype1header_t *m)
919 int i, c, *renderlist;
922 renderlist = (int *)(m->lump_render.start + (int) m);
923 glDisable(GL_TEXTURE_2D);
924 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
926 glDepthMask(0); // disable zbuffer updates
928 VectorSubtract(org, r_refdef.vieworg, diff);
929 glColor4f(fogcolor[0], fogcolor[1], fogcolor[2], exp(fogdensity/DotProduct(diff,diff)));
930 if (gl_vertexarrays.value)
932 qglVertexPointer(3, GL_FLOAT, 0, aliasvert);
933 glEnableClientState(GL_VERTEX_ARRAY);
935 for (i = 0;i < m->numshaders;i++)
937 c = (*renderlist++) * 3;
938 qglDrawElements(GL_TRIANGLES, c, GL_UNSIGNED_INT, renderlist);
942 glDisableClientState(GL_VERTEX_ARRAY);
948 tex = (float *)(m->lump_texcoords.start + (int) m);
950 glBegin(GL_TRIANGLES);
951 for (i = 0;i < m->numshaders;i++)
956 index = *renderlist++;
957 glVertex3fv(aliasvert + index*3);
958 index = *renderlist++;
959 glVertex3fv(aliasvert + index*3);
960 index = *renderlist++;
961 glVertex3fv(aliasvert + index*3);
966 glEnable(GL_TEXTURE_2D);
970 void GL_DrawZymoticModelMeshShadow(zymtype1header_t *m)
972 int i, c, *renderlist;
977 // flatten it to make a shadow
979 l = lightspot[2] + 0.125;
980 for (i = 0;i < m->numverts;i++, av+=3)
984 renderlist = (int *)(m->lump_render.start + (int) m);
985 glDisable(GL_TEXTURE_2D);
986 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
988 glDepthMask(0); // disable zbuffer updates
990 glColor4f(0.0f, 0.0f, 0.0f, 0.5f);
991 if (gl_vertexarrays.value)
993 qglVertexPointer(3, GL_FLOAT, 0, aliasvert);
994 glEnableClientState(GL_VERTEX_ARRAY);
996 for (i = 0;i < m->numshaders;i++)
998 c = (*renderlist++) * 3;
999 qglDrawElements(GL_TRIANGLES, c, GL_UNSIGNED_INT, renderlist);
1003 glDisableClientState(GL_VERTEX_ARRAY);
1009 tex = (float *)(m->lump_texcoords.start + (int) m);
1011 glBegin(GL_TRIANGLES);
1012 for (i = 0;i < m->numshaders;i++)
1017 index = *renderlist++;
1018 glVertex3fv(aliasvert + index*3);
1019 index = *renderlist++;
1020 glVertex3fv(aliasvert + index*3);
1021 index = *renderlist++;
1022 glVertex3fv(aliasvert + index*3);
1027 glEnable(GL_TEXTURE_2D);
1036 void R_DrawZymoticFrame (zymtype1header_t *m, float alpha, vec3_t color, entity_t *ent, int shadow, vec3_t org, vec3_t angles, int frame, int skinblah, int effects, int flags)
1039 float scenetime, scenefrac;
1040 int sceneframe1, sceneframe2;
1041 zymbonematrix *basebonepose;
1042 if ((frame >= m->numscenes) || (frame < 0))
1044 Con_DPrintf ("R_ZymoticSetupFrame: no such frame %d\n", frame);
1048 scene = (zymscene_t *)(m->lump_scenes.start + (int) m) + frame;
1049 if (ent->draw_lastmodel != ent->model || ent->draw_pose != frame || ent->draw_lerpstart >= cl.time)
1051 ent->draw_lastmodel = ent->model;
1052 ent->draw_lastpose = -1;
1053 ent->draw_pose = frame;
1054 ent->draw_lerpstart = cl.time;
1056 scenetime = (cl.time - ent->draw_lerpstart) * scene->framerate;
1057 sceneframe1 = (int) scenetime;
1058 sceneframe2 = sceneframe1 + 1;
1059 scenefrac = scenetime - sceneframe1;
1060 if (scene->flags & ZYMSCENEFLAG_NOLOOP)
1062 if (sceneframe1 > (scene->length - 1))
1063 sceneframe1 = (scene->length - 1);
1064 if (sceneframe2 > (scene->length - 1))
1065 sceneframe2 = (scene->length - 1);
1069 sceneframe1 %= scene->length;
1070 sceneframe2 %= scene->length;
1072 if (sceneframe2 == sceneframe1)
1075 basebonepose = (zymbonematrix *)(m->lump_poses.start + (int) m);
1076 ZymoticLerpBones(m->numbones, scenefrac, basebonepose + sceneframe1 * m->numbones, basebonepose + sceneframe2 * m->numbones, (zymbone_t *)(m->lump_bones.start + (int) m), org, angles);
1077 ZymoticTransformVerts(m->numverts, (int *)(m->lump_vertbonecounts.start + (int) m), (zymvertex_t *)(m->lump_verts.start + (int) m));
1078 ZymoticCalcNormals(m->numverts, m->numshaders, (int *)(m->lump_render.start + (int) m));
1080 R_LightModel(m->numverts, org, color);
1082 if (!r_render.value)
1084 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
1085 glShadeModel(GL_SMOOTH);
1086 if (effects & EF_ADDITIVE)
1088 glBlendFunc(GL_SRC_ALPHA, GL_ONE); // additive rendering
1092 else if (alpha != 1.0)
1094 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1100 glDisable(GL_BLEND);
1104 GL_DrawZymoticModelMesh(aliasvertcolor, m);
1107 GL_DrawZymoticModelMeshFog(org, m);
1109 if (!fogenabled && r_shadows.value && !(effects & EF_ADDITIVE) && shadow)
1110 GL_DrawZymoticModelMeshShadow(m);
1112 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1113 glEnable (GL_BLEND);
1117 int modeldlightbits[8];
1118 extern int r_dlightframecount;
1126 void R_DrawAliasModel (entity_t *ent, int cull, float alpha, model_t *clmodel, int frame, int skin, vec3_t org, vec3_t angles, int effects, int flags, int colormap)
1129 vec3_t mins, maxs, color;
1134 if (alpha < (1.0 / 64.0))
1135 return; // basically completely transparent
1137 VectorAdd (org, clmodel->mins, mins);
1138 VectorAdd (org, clmodel->maxs, maxs);
1140 if (cull && R_CullBox (mins, maxs))
1145 leaf = Mod_PointInLeaf (org, cl.worldmodel);
1146 if (leaf->dlightframe == r_dlightframecount)
1147 for (i = 0;i < 8;i++)
1148 modeldlightbits[i] = leaf->dlightbits[i];
1150 for (i = 0;i < 8;i++)
1151 modeldlightbits[i] = 0;
1153 // get lighting information
1155 if ((flags & EF_FULLBRIGHT) || (effects & EF_FULLBRIGHT))
1156 color[0] = color[1] = color[2] = 256;
1158 R_LightPoint (color, org);
1161 glDisable(GL_ALPHA_TEST);
1163 if (frame < 0 || frame >= clmodel->numframes)
1166 Con_DPrintf("invalid skin number %d for model %s\n", frame, clmodel->name);
1169 if (skin < 0 || skin >= clmodel->numskins)
1172 Con_DPrintf("invalid skin number %d for model %s\n", skin, clmodel->name);
1175 modelheader = Mod_Extradata (clmodel);
1178 // int *skinanimrange = (int *) (clmodel->skinanimrange + (int) modelheader) + skin * 2;
1179 // int *skinanim = (int *) (clmodel->skinanim + (int) modelheader);
1180 int *skinanimrange = clmodel->skinanimrange + skin * 2;
1181 int *skinanim = clmodel->skinanim;
1182 i = skinanimrange[0];
1183 if (skinanimrange[1] > 1) // animated
1184 i += ((int) (cl.time * 10) % skinanimrange[1]);
1185 skinset = skinanim + i*5;
1189 glEnable (GL_TEXTURE_2D);
1191 c_alias_polys += clmodel->numtris;
1192 if (clmodel->aliastype == ALIASTYPE_ZYM)
1193 R_DrawZymoticFrame (modelheader, alpha, color, ent, ent != &cl.viewent, org, angles, frame, 0, effects, flags);
1194 else if (clmodel->aliastype == ALIASTYPE_MD2)
1195 R_DrawQ2AliasFrame (modelheader, alpha, color, ent, ent != &cl.viewent, org, angles, frame, skinset[0], effects, flags);
1197 R_DrawAliasFrame (modelheader, alpha, color, ent, ent != &cl.viewent, org, angles, frame, skinset, colormap, effects, flags);