4 //cvar_t gl_transform = {0, "gl_transform", "1"};
5 cvar_t gl_lockarrays = {0, "gl_lockarrays", "1"};
12 // LordHavoc: vertex array
15 float *aliasvertcolor;
16 float *aliasvertcolor2;
17 zymbonematrix *zymbonepose;
20 rmeshinfo_t aliasmeshinfo;
22 rtexture_t *chrometexture;
24 int arraylocked = false;
25 void GL_LockArray(int first, int count)
27 if (gl_supportslockarrays && gl_lockarrays.integer)
29 qglLockArraysEXT(first, count);
34 void GL_UnlockArray(void)
44 void GL_SetupModelTransform (vec3_t origin, vec3_t angles, vec_t scale)
46 glTranslatef (origin[0], origin[1], origin[2]);
49 glScalef (scale, scale, scale);
51 glRotatef (angles[1], 0, 0, 1);
53 glRotatef (-angles[0], 0, 1, 0);
55 glRotatef (angles[2], 1, 0, 0);
59 rtexturepool_t *chrometexturepool;
61 // currently unused reflection effect texture
62 void makechrometexture(void)
68 fractalnoise(noise, 64, 8);
70 // convert to RGBA data
71 for (i = 0;i < 64*64;i++)
73 data[i][0] = data[i][1] = data[i][2] = noise[i];
77 chrometexture = R_LoadTexture (chrometexturepool, "chrometexture", 64, 64, &data[0][0], TEXTYPE_RGBA, TEXF_MIPMAP | TEXF_PRECACHE);
80 mempool_t *gl_models_mempool;
82 void gl_models_start(void)
84 // allocate vertex processing arrays
85 gl_models_mempool = Mem_AllocPool("GL_Models");
86 aliasvert = Mem_Alloc(gl_models_mempool, sizeof(float[MD2MAX_VERTS][3]));
87 aliasvertnorm = Mem_Alloc(gl_models_mempool, sizeof(float[MD2MAX_VERTS][3]));
88 aliasvertcolor = Mem_Alloc(gl_models_mempool, sizeof(float[MD2MAX_VERTS][4]));
89 aliasvertcolor2 = Mem_Alloc(gl_models_mempool, sizeof(float[MD2MAX_VERTS][4])); // used temporarily for tinted coloring
90 zymbonepose = Mem_Alloc(gl_models_mempool, sizeof(zymbonematrix[256]));
91 aliasvertusage = Mem_Alloc(gl_models_mempool, sizeof(int[MD2MAX_VERTS]));
92 chrometexturepool = R_AllocTexturePool();
96 void gl_models_shutdown(void)
98 R_FreeTexturePool(&chrometexturepool);
99 Mem_FreePool(&gl_models_mempool);
102 void gl_models_newmap(void)
106 void GL_Models_Init(void)
108 // Cvar_RegisterVariable(&gl_transform);
109 Cvar_RegisterVariable(&gl_lockarrays);
111 R_RegisterModule("GL_Models", gl_models_start, gl_models_shutdown, gl_models_newmap);
114 void R_AliasTransformVerts(int vertcount)
120 while (vertcount >= 4)
122 VectorCopy(av, point);softwaretransform(point, av);av += 3;
123 VectorCopy(av, point);softwaretransform(point, av);av += 3;
124 VectorCopy(av, point);softwaretransform(point, av);av += 3;
125 VectorCopy(av, point);softwaretransform(point, av);av += 3;
126 VectorCopy(avn, point);softwaretransformdirection(point, avn);avn += 3;
127 VectorCopy(avn, point);softwaretransformdirection(point, avn);avn += 3;
128 VectorCopy(avn, point);softwaretransformdirection(point, avn);avn += 3;
129 VectorCopy(avn, point);softwaretransformdirection(point, avn);avn += 3;
134 VectorCopy(av, point);softwaretransform(point, av);av += 3;
135 VectorCopy(avn, point);softwaretransformdirection(point, avn);avn += 3;
140 void R_AliasLerpVerts(int vertcount,
141 float lerp1, trivertx_t *verts1, vec3_t fscale1, vec3_t translate1,
142 float lerp2, trivertx_t *verts2, vec3_t fscale2, vec3_t translate2,
143 float lerp3, trivertx_t *verts3, vec3_t fscale3, vec3_t translate3,
144 float lerp4, trivertx_t *verts4, vec3_t fscale4, vec3_t translate4)
147 vec3_t scale1, scale2, scale3, scale4, translate;
148 float *n1, *n2, *n3, *n4;
152 VectorScale(fscale1, lerp1, scale1);
155 VectorScale(fscale2, lerp2, scale2);
158 VectorScale(fscale3, lerp3, scale3);
161 VectorScale(fscale4, lerp4, scale4);
162 translate[0] = translate1[0] * lerp1 + translate2[0] * lerp2 + translate3[0] * lerp3 + translate4[0] * lerp4;
163 translate[1] = translate1[1] * lerp1 + translate2[1] * lerp2 + translate3[1] * lerp3 + translate4[1] * lerp4;
164 translate[2] = translate1[2] * lerp1 + translate2[2] * lerp2 + translate3[2] * lerp3 + translate4[2] * lerp4;
166 for (i = 0;i < vertcount;i++)
168 av[0] = verts1->v[0] * scale1[0] + verts2->v[0] * scale2[0] + verts3->v[0] * scale3[0] + verts4->v[0] * scale4[0] + translate[0];
169 av[1] = verts1->v[1] * scale1[1] + verts2->v[1] * scale2[1] + verts3->v[1] * scale3[1] + verts4->v[1] * scale4[1] + translate[1];
170 av[2] = verts1->v[2] * scale1[2] + verts2->v[2] * scale2[2] + verts3->v[2] * scale3[2] + verts4->v[2] * scale4[2] + translate[2];
171 n1 = m_bytenormals[verts1->lightnormalindex];
172 n2 = m_bytenormals[verts2->lightnormalindex];
173 n3 = m_bytenormals[verts3->lightnormalindex];
174 n4 = m_bytenormals[verts4->lightnormalindex];
175 avn[0] = n1[0] * lerp1 + n2[0] * lerp2 + n3[0] * lerp3 + n4[0] * lerp4;
176 avn[1] = n1[1] * lerp1 + n2[1] * lerp2 + n3[1] * lerp3 + n4[1] * lerp4;
177 avn[2] = n1[2] * lerp1 + n2[2] * lerp2 + n3[2] * lerp3 + n4[2] * lerp4;
180 verts1++;verts2++;verts3++;verts4++;
185 translate[0] = translate1[0] * lerp1 + translate2[0] * lerp2 + translate3[0] * lerp3;
186 translate[1] = translate1[1] * lerp1 + translate2[1] * lerp2 + translate3[1] * lerp3;
187 translate[2] = translate1[2] * lerp1 + translate2[2] * lerp2 + translate3[2] * lerp3;
189 for (i = 0;i < vertcount;i++)
191 av[0] = verts1->v[0] * scale1[0] + verts2->v[0] * scale2[0] + verts3->v[0] * scale3[0] + translate[0];
192 av[1] = verts1->v[1] * scale1[1] + verts2->v[1] * scale2[1] + verts3->v[1] * scale3[1] + translate[1];
193 av[2] = verts1->v[2] * scale1[2] + verts2->v[2] * scale2[2] + verts3->v[2] * scale3[2] + translate[2];
194 n1 = m_bytenormals[verts1->lightnormalindex];
195 n2 = m_bytenormals[verts2->lightnormalindex];
196 n3 = m_bytenormals[verts3->lightnormalindex];
197 avn[0] = n1[0] * lerp1 + n2[0] * lerp2 + n3[0] * lerp3;
198 avn[1] = n1[1] * lerp1 + n2[1] * lerp2 + n3[1] * lerp3;
199 avn[2] = n1[2] * lerp1 + n2[2] * lerp2 + n3[2] * lerp3;
202 verts1++;verts2++;verts3++;
208 translate[0] = translate1[0] * lerp1 + translate2[0] * lerp2;
209 translate[1] = translate1[1] * lerp1 + translate2[1] * lerp2;
210 translate[2] = translate1[2] * lerp1 + translate2[2] * lerp2;
212 for (i = 0;i < vertcount;i++)
214 av[0] = verts1->v[0] * scale1[0] + verts2->v[0] * scale2[0] + translate[0];
215 av[1] = verts1->v[1] * scale1[1] + verts2->v[1] * scale2[1] + translate[1];
216 av[2] = verts1->v[2] * scale1[2] + verts2->v[2] * scale2[2] + translate[2];
217 n1 = m_bytenormals[verts1->lightnormalindex];
218 n2 = m_bytenormals[verts2->lightnormalindex];
219 avn[0] = n1[0] * lerp1 + n2[0] * lerp2;
220 avn[1] = n1[1] * lerp1 + n2[1] * lerp2;
221 avn[2] = n1[2] * lerp1 + n2[2] * lerp2;
230 translate[0] = translate1[0] * lerp1;
231 translate[1] = translate1[1] * lerp1;
232 translate[2] = translate1[2] * lerp1;
236 // general but almost never used case
237 for (i = 0;i < vertcount;i++)
239 av[0] = verts1->v[0] * scale1[0] + translate[0];
240 av[1] = verts1->v[1] * scale1[1] + translate[1];
241 av[2] = verts1->v[2] * scale1[2] + translate[2];
242 n1 = m_bytenormals[verts1->lightnormalindex];
243 avn[0] = n1[0] * lerp1;
244 avn[1] = n1[1] * lerp1;
245 avn[2] = n1[2] * lerp1;
254 for (i = 0;i < vertcount;i++)
256 av[0] = verts1->v[0] * scale1[0] + translate[0];
257 av[1] = verts1->v[1] * scale1[1] + translate[1];
258 av[2] = verts1->v[2] * scale1[2] + translate[2];
259 VectorCopy(m_bytenormals[verts1->lightnormalindex], avn);
268 void R_DrawModelMesh(rtexture_t *skin, float *colors, float cred, float cgreen, float cblue)
270 aliasmeshinfo.tex[0] = R_GetTexture(skin);
271 aliasmeshinfo.color = colors;
274 aliasmeshinfo.cr = cred;
275 aliasmeshinfo.cg = cgreen;
276 aliasmeshinfo.cb = cblue;
277 aliasmeshinfo.ca = currentrenderentity->alpha;
280 c_alias_polys += aliasmeshinfo.numtriangles;
281 R_Mesh_Draw(&aliasmeshinfo);
283 // leave it in a state for additional passes
284 aliasmeshinfo.blendfunc1 = GL_SRC_ALPHA;
285 aliasmeshinfo.blendfunc2 = GL_ONE;
288 void R_TintModel(float *in, float *out, int verts, float r, float g, float b)
291 for (i = 0;i < verts;i++)
302 void R_SetupMDLMD2Frames(skinframe_t **skinframe)
304 md2frame_t *frame1, *frame2, *frame3, *frame4;
305 trivertx_t *frame1verts, *frame2verts, *frame3verts, *frame4verts;
307 model = currentrenderentity->model;
309 if (model->skinscenes[currentrenderentity->skinnum].framecount > 1)
310 *skinframe = &model->skinframes[model->skinscenes[currentrenderentity->skinnum].firstframe + (int) (cl.time * 10) % model->skinscenes[currentrenderentity->skinnum].framecount];
312 *skinframe = &model->skinframes[model->skinscenes[currentrenderentity->skinnum].firstframe];
314 frame1 = &model->mdlmd2data_frames[currentrenderentity->frameblend[0].frame];
315 frame2 = &model->mdlmd2data_frames[currentrenderentity->frameblend[1].frame];
316 frame3 = &model->mdlmd2data_frames[currentrenderentity->frameblend[2].frame];
317 frame4 = &model->mdlmd2data_frames[currentrenderentity->frameblend[3].frame];
318 frame1verts = &model->mdlmd2data_pose[currentrenderentity->frameblend[0].frame * model->numverts];
319 frame2verts = &model->mdlmd2data_pose[currentrenderentity->frameblend[1].frame * model->numverts];
320 frame3verts = &model->mdlmd2data_pose[currentrenderentity->frameblend[2].frame * model->numverts];
321 frame4verts = &model->mdlmd2data_pose[currentrenderentity->frameblend[3].frame * model->numverts];
322 R_AliasLerpVerts(model->numverts,
323 currentrenderentity->frameblend[0].lerp, frame1verts, frame1->scale, frame1->translate,
324 currentrenderentity->frameblend[1].lerp, frame2verts, frame2->scale, frame2->translate,
325 currentrenderentity->frameblend[2].lerp, frame3verts, frame3->scale, frame3->translate,
326 currentrenderentity->frameblend[3].lerp, frame4verts, frame4->scale, frame4->translate);
327 R_AliasTransformVerts(model->numverts);
329 R_LightModel(model->numverts);
332 void R_DrawQ1AliasModel (void)
337 skinframe_t *skinframe;
339 model = currentrenderentity->model;
341 R_SetupMDLMD2Frames(&skinframe);
343 memset(&aliasmeshinfo, 0, sizeof(aliasmeshinfo));
345 aliasmeshinfo.vertex = aliasvert;
346 aliasmeshinfo.vertexstep = sizeof(float[3]);
347 aliasmeshinfo.numverts = model->numverts;
348 aliasmeshinfo.numtriangles = model->numtris;
349 aliasmeshinfo.index = model->mdldata_indices;
350 aliasmeshinfo.colorstep = sizeof(float[4]);
351 aliasmeshinfo.texcoords[0] = model->mdldata_texcoords;
352 aliasmeshinfo.texcoordstep[0] = sizeof(float[2]);
357 VectorSubtract(currentrenderentity->origin, r_origin, diff);
358 fog = DotProduct(diff,diff);
361 fog = exp(fogdensity/fog);
366 // fog method: darken, additive fog
367 // 1. render model as normal, scaled by inverse of fog alpha (darkens it)
368 // 2. render fog as additive
371 if (currentrenderentity->effects & EF_ADDITIVE)
373 aliasmeshinfo.transparent = true;
374 aliasmeshinfo.blendfunc1 = GL_SRC_ALPHA;
375 aliasmeshinfo.blendfunc2 = GL_ONE;
377 else if (currentrenderentity->alpha != 1.0 || skinframe->fog != NULL)
379 aliasmeshinfo.transparent = true;
380 aliasmeshinfo.blendfunc1 = GL_SRC_ALPHA;
381 aliasmeshinfo.blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
385 aliasmeshinfo.transparent = false;
386 aliasmeshinfo.blendfunc1 = GL_ONE;
387 aliasmeshinfo.blendfunc2 = GL_ZERO;
392 R_TintModel(aliasvertcolor, aliasvertcolor, model->numverts, 1 - fog, 1 - fog, 1 - fog);
394 if (skinframe->base || skinframe->pants || skinframe->shirt || skinframe->glow || skinframe->merged)
396 if (currentrenderentity->colormap >= 0 && (skinframe->base || skinframe->pants || skinframe->shirt))
401 R_DrawModelMesh(skinframe->base, aliasvertcolor, 0, 0, 0);
402 if (skinframe->pants)
404 c = (currentrenderentity->colormap & 0xF) << 4;c += (c >= 128 && c < 224) ? 4 : 12; // 128-224 are backwards ranges
405 color = (byte *) (&d_8to24table[c]);
406 if (c >= 224) // fullbright ranges
407 R_DrawModelMesh(skinframe->pants, NULL, color[0] * (1.0f / 255.0f), color[1] * (1.0f / 255.0f), color[2] * (1.0f / 255.0f));
410 R_TintModel(aliasvertcolor, aliasvertcolor2, model->numverts, color[0] * (1.0f / 255.0f), color[1] * (1.0f / 255.0f), color[2] * (1.0f / 255.0f));
411 R_DrawModelMesh(skinframe->pants, aliasvertcolor2, 0, 0, 0);
414 if (skinframe->shirt)
416 c = currentrenderentity->colormap & 0xF0 ;c += (c >= 128 && c < 224) ? 4 : 12; // 128-224 are backwards ranges
417 color = (byte *) (&d_8to24table[c]);
418 if (c >= 224) // fullbright ranges
419 R_DrawModelMesh(skinframe->shirt, NULL, color[0] * (1.0f / 255.0f), color[1] * (1.0f / 255.0f), color[2] * (1.0f / 255.0f));
422 R_TintModel(aliasvertcolor, aliasvertcolor2, model->numverts, color[0] * (1.0f / 255.0f), color[1] * (1.0f / 255.0f), color[2] * (1.0f / 255.0f));
423 R_DrawModelMesh(skinframe->shirt, aliasvertcolor2, 0, 0, 0);
429 if (skinframe->merged)
430 R_DrawModelMesh(skinframe->merged, aliasvertcolor, 0, 0, 0);
433 if (skinframe->base) R_DrawModelMesh(skinframe->base, aliasvertcolor, 0, 0, 0);
434 if (skinframe->pants) R_DrawModelMesh(skinframe->pants, aliasvertcolor, 0, 0, 0);
435 if (skinframe->shirt) R_DrawModelMesh(skinframe->shirt, aliasvertcolor, 0, 0, 0);
438 if (skinframe->glow) R_DrawModelMesh(skinframe->glow, NULL, 1 - fog, 1 - fog, 1 - fog);
441 R_DrawModelMesh(0, NULL, 1 - fog, 1 - fog, 1 - fog);
445 aliasmeshinfo.tex[0] = R_GetTexture(skinframe->fog);
446 aliasmeshinfo.blendfunc1 = GL_SRC_ALPHA;
447 aliasmeshinfo.blendfunc2 = GL_ONE;
448 aliasmeshinfo.color = NULL;
450 aliasmeshinfo.cr = fogcolor[0];
451 aliasmeshinfo.cg = fogcolor[1];
452 aliasmeshinfo.cb = fogcolor[2];
453 aliasmeshinfo.ca = currentrenderentity->alpha * fog;
455 c_alias_polys += aliasmeshinfo.numtriangles;
456 R_Mesh_Draw(&aliasmeshinfo);
460 void R_DrawQ2AliasModel (void)
464 skinframe_t *skinframe;
467 model = currentrenderentity->model;
469 R_SetupMDLMD2Frames(&skinframe);
471 if (!r_render.integer)
474 // FIXME FIXME FIXME rewrite loader to convert to triangle mesh
475 glBindTexture(GL_TEXTURE_2D, R_GetTexture(skinframe->base));
477 if (currentrenderentity->effects & EF_ADDITIVE)
479 glBlendFunc(GL_SRC_ALPHA, GL_ONE); // additive rendering
483 else if (currentrenderentity->alpha != 1.0 || R_TextureHasAlpha(skinframe->base))
485 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
495 // LordHavoc: big mess...
496 // using vertex arrays only slightly, although it is enough to prevent duplicates
497 // (saving half the transforms)
498 glVertexPointer(3, GL_FLOAT, sizeof(float[3]), aliasvert);
499 glColorPointer(4, GL_FLOAT, sizeof(float[4]), aliasvertcolor);
500 glEnableClientState(GL_VERTEX_ARRAY);
501 glEnableClientState(GL_COLOR_ARRAY);
503 GL_LockArray(0, model->numverts);
505 order = model->md2data_glcmds;
508 if (!(count = *order++))
511 glBegin(GL_TRIANGLE_STRIP);
514 glBegin(GL_TRIANGLE_FAN);
519 glTexCoord2f(((float *)order)[0], ((float *)order)[1]);
520 glArrayElement(order[2]);
528 glDisableClientState(GL_COLOR_ARRAY);
529 glDisableClientState(GL_VERTEX_ARRAY);
533 glDisable (GL_TEXTURE_2D);
534 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
536 glDepthMask(0); // disable zbuffer updates
538 VectorSubtract(currentrenderentity->origin, r_origin, diff);
539 glColor4f(fogcolor[0], fogcolor[1], fogcolor[2], currentrenderentity->alpha * exp(fogdensity/DotProduct(diff,diff)));
541 // LordHavoc: big mess...
542 // using vertex arrays only slightly, although it is enough to prevent duplicates
543 // (saving half the transforms)
544 glVertexPointer(3, GL_FLOAT, sizeof(float[3]), aliasvert);
545 glEnableClientState(GL_VERTEX_ARRAY);
547 GL_LockArray(0, model->numverts);
549 order = model->md2data_glcmds;
552 if (!(count = *order++))
555 glBegin(GL_TRIANGLE_STRIP);
558 glBegin(GL_TRIANGLE_FAN);
563 glArrayElement(order[2]);
571 glDisableClientState(GL_VERTEX_ARRAY);
573 glEnable (GL_TEXTURE_2D);
577 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
582 int ZymoticLerpBones(int count, zymbonematrix *bonebase, frameblend_t *blend, zymbone_t *bone)
585 float lerp1, lerp2, lerp3, lerp4;
586 zymbonematrix *out, rootmatrix, m, *bone1, *bone2, *bone3, *bone4;
601 R_ConcatTransforms(&softwaretransform_matrix[0], &m.m[0], &rootmatrix.m[0]);
604 // LordHavoc: combine transform from zym coordinate space to quake coordinate space with model to world transform matrix
605 rootmatrix.m[0][0] = softwaretransform_matrix[0][1];
606 rootmatrix.m[0][1] = -softwaretransform_matrix[0][0];
607 rootmatrix.m[0][2] = softwaretransform_matrix[0][2];
608 rootmatrix.m[0][3] = softwaretransform_matrix[0][3];
609 rootmatrix.m[1][0] = softwaretransform_matrix[1][1];
610 rootmatrix.m[1][1] = -softwaretransform_matrix[1][0];
611 rootmatrix.m[1][2] = softwaretransform_matrix[1][2];
612 rootmatrix.m[1][3] = softwaretransform_matrix[1][3];
613 rootmatrix.m[2][0] = softwaretransform_matrix[2][1];
614 rootmatrix.m[2][1] = -softwaretransform_matrix[2][0];
615 rootmatrix.m[2][2] = softwaretransform_matrix[2][2];
616 rootmatrix.m[2][3] = softwaretransform_matrix[2][3];
618 bone1 = bonebase + blend[0].frame * count;
619 lerp1 = blend[0].lerp;
622 bone2 = bonebase + blend[1].frame * count;
623 lerp2 = blend[1].lerp;
626 bone3 = bonebase + blend[2].frame * count;
627 lerp3 = blend[2].lerp;
631 bone4 = bonebase + blend[3].frame * count;
632 lerp4 = blend[3].lerp;
633 for (i = 0, out = zymbonepose;i < count;i++, out++)
635 // interpolate matrices
636 m.m[0][0] = bone1->m[0][0] * lerp1 + bone2->m[0][0] * lerp2 + bone3->m[0][0] * lerp3 + bone4->m[0][0] * lerp4;
637 m.m[0][1] = bone1->m[0][1] * lerp1 + bone2->m[0][1] * lerp2 + bone3->m[0][1] * lerp3 + bone4->m[0][1] * lerp4;
638 m.m[0][2] = bone1->m[0][2] * lerp1 + bone2->m[0][2] * lerp2 + bone3->m[0][2] * lerp3 + bone4->m[0][2] * lerp4;
639 m.m[0][3] = bone1->m[0][3] * lerp1 + bone2->m[0][3] * lerp2 + bone3->m[0][3] * lerp3 + bone4->m[0][3] * lerp4;
640 m.m[1][0] = bone1->m[1][0] * lerp1 + bone2->m[1][0] * lerp2 + bone3->m[1][0] * lerp3 + bone4->m[1][0] * lerp4;
641 m.m[1][1] = bone1->m[1][1] * lerp1 + bone2->m[1][1] * lerp2 + bone3->m[1][1] * lerp3 + bone4->m[1][1] * lerp4;
642 m.m[1][2] = bone1->m[1][2] * lerp1 + bone2->m[1][2] * lerp2 + bone3->m[1][2] * lerp3 + bone4->m[1][2] * lerp4;
643 m.m[1][3] = bone1->m[1][3] * lerp1 + bone2->m[1][3] * lerp2 + bone3->m[1][3] * lerp3 + bone4->m[1][3] * lerp4;
644 m.m[2][0] = bone1->m[2][0] * lerp1 + bone2->m[2][0] * lerp2 + bone3->m[2][0] * lerp3 + bone4->m[2][0] * lerp4;
645 m.m[2][1] = bone1->m[2][1] * lerp1 + bone2->m[2][1] * lerp2 + bone3->m[2][1] * lerp3 + bone4->m[2][1] * lerp4;
646 m.m[2][2] = bone1->m[2][2] * lerp1 + bone2->m[2][2] * lerp2 + bone3->m[2][2] * lerp3 + bone4->m[2][2] * lerp4;
647 m.m[2][3] = bone1->m[2][3] * lerp1 + bone2->m[2][3] * lerp2 + bone3->m[2][3] * lerp3 + bone4->m[2][3] * lerp4;
648 if (bone->parent >= 0)
649 R_ConcatTransforms(&zymbonepose[bone->parent].m[0], &m.m[0], &out->m[0]);
651 R_ConcatTransforms(&rootmatrix.m[0], &m.m[0], &out->m[0]);
662 for (i = 0, out = zymbonepose;i < count;i++, out++)
664 // interpolate matrices
665 m.m[0][0] = bone1->m[0][0] * lerp1 + bone2->m[0][0] * lerp2 + bone3->m[0][0] * lerp3;
666 m.m[0][1] = bone1->m[0][1] * lerp1 + bone2->m[0][1] * lerp2 + bone3->m[0][1] * lerp3;
667 m.m[0][2] = bone1->m[0][2] * lerp1 + bone2->m[0][2] * lerp2 + bone3->m[0][2] * lerp3;
668 m.m[0][3] = bone1->m[0][3] * lerp1 + bone2->m[0][3] * lerp2 + bone3->m[0][3] * lerp3;
669 m.m[1][0] = bone1->m[1][0] * lerp1 + bone2->m[1][0] * lerp2 + bone3->m[1][0] * lerp3;
670 m.m[1][1] = bone1->m[1][1] * lerp1 + bone2->m[1][1] * lerp2 + bone3->m[1][1] * lerp3;
671 m.m[1][2] = bone1->m[1][2] * lerp1 + bone2->m[1][2] * lerp2 + bone3->m[1][2] * lerp3;
672 m.m[1][3] = bone1->m[1][3] * lerp1 + bone2->m[1][3] * lerp2 + bone3->m[1][3] * lerp3;
673 m.m[2][0] = bone1->m[2][0] * lerp1 + bone2->m[2][0] * lerp2 + bone3->m[2][0] * lerp3;
674 m.m[2][1] = bone1->m[2][1] * lerp1 + bone2->m[2][1] * lerp2 + bone3->m[2][1] * lerp3;
675 m.m[2][2] = bone1->m[2][2] * lerp1 + bone2->m[2][2] * lerp2 + bone3->m[2][2] * lerp3;
676 m.m[2][3] = bone1->m[2][3] * lerp1 + bone2->m[2][3] * lerp2 + bone3->m[2][3] * lerp3;
677 if (bone->parent >= 0)
678 R_ConcatTransforms(&zymbonepose[bone->parent].m[0], &m.m[0], &out->m[0]);
680 R_ConcatTransforms(&rootmatrix.m[0], &m.m[0], &out->m[0]);
691 for (i = 0, out = zymbonepose;i < count;i++, out++)
693 // interpolate matrices
694 m.m[0][0] = bone1->m[0][0] * lerp1 + bone2->m[0][0] * lerp2;
695 m.m[0][1] = bone1->m[0][1] * lerp1 + bone2->m[0][1] * lerp2;
696 m.m[0][2] = bone1->m[0][2] * lerp1 + bone2->m[0][2] * lerp2;
697 m.m[0][3] = bone1->m[0][3] * lerp1 + bone2->m[0][3] * lerp2;
698 m.m[1][0] = bone1->m[1][0] * lerp1 + bone2->m[1][0] * lerp2;
699 m.m[1][1] = bone1->m[1][1] * lerp1 + bone2->m[1][1] * lerp2;
700 m.m[1][2] = bone1->m[1][2] * lerp1 + bone2->m[1][2] * lerp2;
701 m.m[1][3] = bone1->m[1][3] * lerp1 + bone2->m[1][3] * lerp2;
702 m.m[2][0] = bone1->m[2][0] * lerp1 + bone2->m[2][0] * lerp2;
703 m.m[2][1] = bone1->m[2][1] * lerp1 + bone2->m[2][1] * lerp2;
704 m.m[2][2] = bone1->m[2][2] * lerp1 + bone2->m[2][2] * lerp2;
705 m.m[2][3] = bone1->m[2][3] * lerp1 + bone2->m[2][3] * lerp2;
706 if (bone->parent >= 0)
707 R_ConcatTransforms(&zymbonepose[bone->parent].m[0], &m.m[0], &out->m[0]);
709 R_ConcatTransforms(&rootmatrix.m[0], &m.m[0], &out->m[0]);
722 for (i = 0, out = zymbonepose;i < count;i++, out++)
724 // interpolate matrices
725 m.m[0][0] = bone1->m[0][0] * lerp1;
726 m.m[0][1] = bone1->m[0][1] * lerp1;
727 m.m[0][2] = bone1->m[0][2] * lerp1;
728 m.m[0][3] = bone1->m[0][3] * lerp1;
729 m.m[1][0] = bone1->m[1][0] * lerp1;
730 m.m[1][1] = bone1->m[1][1] * lerp1;
731 m.m[1][2] = bone1->m[1][2] * lerp1;
732 m.m[1][3] = bone1->m[1][3] * lerp1;
733 m.m[2][0] = bone1->m[2][0] * lerp1;
734 m.m[2][1] = bone1->m[2][1] * lerp1;
735 m.m[2][2] = bone1->m[2][2] * lerp1;
736 m.m[2][3] = bone1->m[2][3] * lerp1;
737 if (bone->parent >= 0)
738 R_ConcatTransforms(&zymbonepose[bone->parent].m[0], &m.m[0], &out->m[0]);
740 R_ConcatTransforms(&rootmatrix.m[0], &m.m[0], &out->m[0]);
748 for (i = 0, out = zymbonepose;i < count;i++, out++)
750 if (bone->parent >= 0)
751 R_ConcatTransforms(&zymbonepose[bone->parent].m[0], &bone1->m[0], &out->m[0]);
753 R_ConcatTransforms(&rootmatrix.m[0], &bone1->m[0], &out->m[0]);
762 void ZymoticTransformVerts(int vertcount, int *bonecounts, zymvertex_t *vert)
765 float *out = aliasvert;
766 zymbonematrix *matrix;
770 // FIXME: validate bonecounts at load time (must be >= 1)
771 // FIXME: need 4th component in origin, for how much of the translate to blend in
774 matrix = &zymbonepose[vert->bonenum];
775 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];
776 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];
777 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];
785 matrix = &zymbonepose[vert->bonenum];
786 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];
787 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];
788 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];
796 void ZymoticCalcNormals(int vertcount, int shadercount, int *renderlist)
799 float *out, v1[3], v2[3], normal[3], s;
802 memset(aliasvertnorm, 0, sizeof(float) * vertcount * 3);
803 memset(aliasvertusage, 0, sizeof(int) * vertcount);
804 // parse render list and accumulate surface normals
813 v1[0] = aliasvert[a+0] - aliasvert[b+0];
814 v1[1] = aliasvert[a+1] - aliasvert[b+1];
815 v1[2] = aliasvert[a+2] - aliasvert[b+2];
816 v2[0] = aliasvert[c+0] - aliasvert[b+0];
817 v2[1] = aliasvert[c+1] - aliasvert[b+1];
818 v2[2] = aliasvert[c+2] - aliasvert[b+2];
819 CrossProduct(v1, v2, normal);
820 VectorNormalizeFast(normal);
821 // add surface normal to vertices
822 aliasvertnorm[a+0] += normal[0];
823 aliasvertnorm[a+1] += normal[1];
824 aliasvertnorm[a+2] += normal[2];
825 aliasvertusage[renderlist[0]]++;
826 aliasvertnorm[b+0] += normal[0];
827 aliasvertnorm[b+1] += normal[1];
828 aliasvertnorm[b+2] += normal[2];
829 aliasvertusage[renderlist[1]]++;
830 aliasvertnorm[c+0] += normal[0];
831 aliasvertnorm[c+1] += normal[1];
832 aliasvertnorm[c+2] += normal[2];
833 aliasvertusage[renderlist[2]]++;
837 // average surface normals
854 void R_DrawZymoticModelMesh(zymtype1header_t *m)
857 rtexture_t **texture;
859 // FIXME: do better fog
860 renderlist = (int *)(m->lump_render.start + (int) m);
861 texture = (rtexture_t **)(m->lump_shaders.start + (int) m);
863 aliasmeshinfo.vertex = aliasvert;
864 aliasmeshinfo.vertexstep = sizeof(float[3]);
865 aliasmeshinfo.color = aliasvertcolor;
866 aliasmeshinfo.colorstep = sizeof(float[4]);
867 aliasmeshinfo.texcoords[0] = (float *)(m->lump_texcoords.start + (int) m);
868 aliasmeshinfo.texcoordstep[0] = sizeof(float[2]);
870 for (i = 0;i < m->numshaders;i++)
872 aliasmeshinfo.tex[0] = R_GetTexture(texture[i]);
873 if (currentrenderentity->effects & EF_ADDITIVE)
875 aliasmeshinfo.transparent = true;
876 aliasmeshinfo.blendfunc1 = GL_SRC_ALPHA;
877 aliasmeshinfo.blendfunc2 = GL_ONE;
879 else if (currentrenderentity->alpha != 1.0 || R_TextureHasAlpha(texture[i]))
881 aliasmeshinfo.transparent = true;
882 aliasmeshinfo.blendfunc1 = GL_SRC_ALPHA;
883 aliasmeshinfo.blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
887 aliasmeshinfo.transparent = false;
888 aliasmeshinfo.blendfunc1 = GL_ONE;
889 aliasmeshinfo.blendfunc2 = GL_ZERO;
891 aliasmeshinfo.numtriangles = *renderlist++;
892 aliasmeshinfo.index = renderlist;
893 c_alias_polys += aliasmeshinfo.numtriangles;
894 R_Mesh_Draw(&aliasmeshinfo);
895 renderlist += aliasmeshinfo.numtriangles * 3;
899 void R_DrawZymoticModelMeshFog(vec3_t org, zymtype1header_t *m)
904 // FIXME: do better fog
905 renderlist = (int *)(m->lump_render.start + (int) m);
907 aliasmeshinfo.tex[0] = 0;
908 aliasmeshinfo.blendfunc1 = GL_SRC_ALPHA;
909 aliasmeshinfo.blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
911 VectorSubtract(org, r_origin, diff);
912 aliasmeshinfo.cr = fogcolor[0];
913 aliasmeshinfo.cg = fogcolor[1];
914 aliasmeshinfo.cb = fogcolor[2];
915 aliasmeshinfo.ca = currentrenderentity->alpha * exp(fogdensity/DotProduct(diff,diff));
917 for (i = 0;i < m->numshaders;i++)
919 aliasmeshinfo.numtriangles = *renderlist++;
920 aliasmeshinfo.index = renderlist;
921 c_alias_polys += aliasmeshinfo.numtriangles;
922 R_Mesh_Draw(&aliasmeshinfo);
923 renderlist += aliasmeshinfo.numtriangles * 3;
927 void R_DrawZymoticModel (void)
931 // FIXME: do better fog
932 m = currentrenderentity->model->zymdata_header;
933 ZymoticLerpBones(m->numbones, (zymbonematrix *)(m->lump_poses.start + (int) m), currentrenderentity->frameblend, (zymbone_t *)(m->lump_bones.start + (int) m));
934 ZymoticTransformVerts(m->numverts, (int *)(m->lump_vertbonecounts.start + (int) m), (zymvertex_t *)(m->lump_verts.start + (int) m));
935 ZymoticCalcNormals(m->numverts, m->numshaders, (int *)(m->lump_render.start + (int) m));
937 R_LightModel(m->numverts);
939 memset(&aliasmeshinfo, 0, sizeof(aliasmeshinfo));
940 aliasmeshinfo.numverts = m->numverts;
942 R_DrawZymoticModelMesh(m);
945 R_DrawZymoticModelMeshFog(currentrenderentity->origin, m);
948 void R_DrawAliasModel (void)
950 if (currentrenderentity->alpha < (1.0f / 64.0f))
951 return; // basically completely transparent
955 softwaretransformforentity(currentrenderentity);
957 if (currentrenderentity->model->aliastype == ALIASTYPE_ZYM)
958 R_DrawZymoticModel();
959 else if (currentrenderentity->model->aliastype == ALIASTYPE_MD2)
960 R_DrawQ2AliasModel();
962 R_DrawQ1AliasModel();