3 #include "cl_collision.h"
11 // LordHavoc: vertex arrays
13 float *aliasvertcolorbuf;
14 float *aliasvertcolor; // this may point at aliasvertcolorbuf or at vertex arrays in the mesh backend
15 float *aliasvert_svectors;
16 float *aliasvert_tvectors;
17 float *aliasvert_normals;
19 float *aliasvertcolor2;
21 zymbonematrix *zymbonepose;
23 mempool_t *gl_models_mempool;
25 void gl_models_start(void)
27 // allocate vertex processing arrays
28 gl_models_mempool = Mem_AllocPool("GL_Models");
29 aliasvertcolor = aliasvertcolorbuf = Mem_Alloc(gl_models_mempool, sizeof(float[MD2MAX_VERTS][4]));
30 aliasvert_svectors = Mem_Alloc(gl_models_mempool, sizeof(float[MD2MAX_VERTS][4]));
31 aliasvert_tvectors = Mem_Alloc(gl_models_mempool, sizeof(float[MD2MAX_VERTS][4]));
32 aliasvert_normals = Mem_Alloc(gl_models_mempool, sizeof(float[MD2MAX_VERTS][4]));
33 aliasvertcolor2 = Mem_Alloc(gl_models_mempool, sizeof(float[MD2MAX_VERTS][4])); // used temporarily for tinted coloring
34 zymbonepose = Mem_Alloc(gl_models_mempool, sizeof(zymbonematrix[256]));
35 aliasvertusage = Mem_Alloc(gl_models_mempool, sizeof(int[MD2MAX_VERTS]));
38 void gl_models_shutdown(void)
40 Mem_FreePool(&gl_models_mempool);
43 void gl_models_newmap(void)
47 void GL_Models_Init(void)
49 R_RegisterModule("GL_Models", gl_models_start, gl_models_shutdown, gl_models_newmap);
52 void R_Model_Alias_GetVerts(const entity_render_t *ent, float *vertices, float *normals, float *svectors, float *tvectors)
55 float lerp1, lerp2, lerp3, lerp4;
56 const aliasvertex_t *verts1, *verts2, *verts3, *verts4;
59 Host_Error("R_Model_Alias_GetVerts: vertices == NULL.\n");
60 if (svectors != NULL && (tvectors == NULL || normals == NULL))
61 Host_Error("R_Model_Alias_GetVerts: svectors requires tvectors and normals.\n");
62 if (tvectors != NULL && (svectors == NULL || normals == NULL))
63 Host_Error("R_Model_Alias_GetVerts: tvectors requires svectors and normals.\n");
65 vertcount = ent->model->numverts;
66 verts1 = ent->model->mdlmd2data_pose + ent->frameblend[0].frame * vertcount;
67 lerp1 = ent->frameblend[0].lerp;
68 if (ent->frameblend[1].lerp)
70 verts2 = ent->model->mdlmd2data_pose + ent->frameblend[1].frame * vertcount;
71 lerp2 = ent->frameblend[1].lerp;
72 if (ent->frameblend[2].lerp)
74 verts3 = ent->model->mdlmd2data_pose + ent->frameblend[2].frame * vertcount;
75 lerp3 = ent->frameblend[2].lerp;
76 if (ent->frameblend[3].lerp)
78 verts4 = ent->model->mdlmd2data_pose + ent->frameblend[3].frame * vertcount;
79 lerp4 = ent->frameblend[3].lerp;
83 for (i = 0;i < vertcount;i++, vertices += 4, normals += 4, svectors += 4, tvectors += 4, verts1++, verts2++, verts3++, verts4++)
85 VectorMAMAMAM(lerp1, verts1->origin, lerp2, verts2->origin, lerp3, verts3->origin, lerp4, verts4->origin, vertices);
86 VectorMAMAMAM(lerp1, verts1->normal, lerp2, verts2->normal, lerp3, verts3->normal, lerp4, verts4->normal, normals);
87 VectorMAMAMAM(lerp1, verts1->svector, lerp2, verts2->svector, lerp3, verts3->svector, lerp4, verts4->svector, svectors);
88 CrossProduct(svectors, normals, tvectors);
91 else if (normals != NULL)
93 for (i = 0;i < vertcount;i++, vertices += 4, normals += 4, verts1++, verts2++, verts3++, verts4++)
95 VectorMAMAMAM(lerp1, verts1->origin, lerp2, verts2->origin, lerp3, verts3->origin, lerp4, verts4->origin, vertices);
96 VectorMAMAMAM(lerp1, verts1->normal, lerp2, verts2->normal, lerp3, verts3->normal, lerp4, verts4->normal, normals);
100 for (i = 0;i < vertcount;i++, vertices += 4, verts1++, verts2++, verts3++, verts4++)
101 VectorMAMAMAM(lerp1, verts1->origin, lerp2, verts2->origin, lerp3, verts3->origin, lerp4, verts4->origin, vertices);
106 if (svectors != NULL)
108 for (i = 0;i < vertcount;i++, vertices += 4, normals += 4, svectors += 4, tvectors += 4, verts1++, verts2++, verts3++)
110 VectorMAMAM(lerp1, verts1->origin, lerp2, verts2->origin, lerp3, verts3->origin, vertices);
111 VectorMAMAM(lerp1, verts1->normal, lerp2, verts2->normal, lerp3, verts3->normal, normals);
112 VectorMAMAM(lerp1, verts1->svector, lerp2, verts2->svector, lerp3, verts3->svector, svectors);
113 CrossProduct(svectors, normals, tvectors);
116 else if (normals != NULL)
118 for (i = 0;i < vertcount;i++, vertices += 4, normals += 4, verts1++, verts2++, verts3++)
120 VectorMAMAM(lerp1, verts1->origin, lerp2, verts2->origin, lerp3, verts3->origin, vertices);
121 VectorMAMAM(lerp1, verts1->normal, lerp2, verts2->normal, lerp3, verts3->normal, normals);
125 for (i = 0;i < vertcount;i++, vertices += 4, verts1++, verts2++, verts3++)
126 VectorMAMAM(lerp1, verts1->origin, lerp2, verts2->origin, lerp3, verts3->origin, vertices);
132 if (svectors != NULL)
134 for (i = 0;i < vertcount;i++, vertices += 4, normals += 4, svectors += 4, tvectors += 4, verts1++, verts2++)
136 VectorMAM(lerp1, verts1->origin, lerp2, verts2->origin, vertices);
137 VectorMAM(lerp1, verts1->normal, lerp2, verts2->normal, normals);
138 VectorMAM(lerp1, verts1->svector, lerp2, verts2->svector, svectors);
139 CrossProduct(svectors, normals, tvectors);
142 else if (normals != NULL)
144 for (i = 0;i < vertcount;i++, vertices += 4, normals += 4, verts1++, verts2++)
146 VectorMAM(lerp1, verts1->origin, lerp2, verts2->origin, vertices);
147 VectorMAM(lerp1, verts1->normal, lerp2, verts2->normal, normals);
151 for (i = 0;i < vertcount;i++, vertices += 4, verts1++, verts2++)
152 VectorMAM(lerp1, verts1->origin, lerp2, verts2->origin, vertices);
158 if (svectors != NULL)
160 for (i = 0;i < vertcount;i++, vertices += 4, normals += 4, svectors += 4, tvectors += 4, verts1++)
162 VectorM(lerp1, verts1->origin, vertices);
163 VectorM(lerp1, verts1->normal, normals);
164 VectorM(lerp1, verts1->svector, svectors);
165 CrossProduct(svectors, normals, tvectors);
168 else if (normals != NULL)
170 for (i = 0;i < vertcount;i++, vertices += 4, normals += 4, verts1++)
172 VectorM(lerp1, verts1->origin, vertices);
173 VectorM(lerp1, verts1->normal, normals);
177 for (i = 0;i < vertcount;i++, vertices += 4, verts1++)
178 VectorM(lerp1, verts1->origin, vertices);
182 skinframe_t *R_FetchSkinFrame(const entity_render_t *ent)
184 model_t *model = ent->model;
185 int s = ent->skinnum;
186 if ((unsigned int)s >= (unsigned int)model->numskins)
188 if (model->skinscenes[s].framecount > 1)
189 return &model->skinframes[model->skinscenes[s].firstframe + (int) (cl.time * 10) % model->skinscenes[s].framecount];
191 return &model->skinframes[model->skinscenes[s].firstframe];
194 void R_DrawAliasModelCallback (const void *calldata1, int calldata2)
196 int i, c, fullbright, pantsfullbright, shirtfullbright, colormapped, tex;
197 float pantscolor[3], shirtcolor[3];
198 float fog, ifog, colorscale;
203 skinframe_t *skinframe;
204 const entity_render_t *ent = calldata1;
205 int blendfunc1, blendfunc2;
207 R_Mesh_Matrix(&ent->matrix);
210 R_Mesh_ResizeCheck(model->numverts);
212 skinframe = R_FetchSkinFrame(ent);
214 fullbright = (ent->effects & EF_FULLBRIGHT) != 0;
219 VectorSubtract(ent->origin, r_origin, diff);
220 fog = DotProduct(diff,diff);
223 fog = exp(fogdensity/fog);
228 // fog method: darken, additive fog
229 // 1. render model as normal, scaled by inverse of fog alpha (darkens it)
230 // 2. render fog as additive
234 if (ent->effects & EF_ADDITIVE)
236 blendfunc1 = GL_SRC_ALPHA;
239 else if (ent->alpha != 1.0 || skinframe->fog != NULL)
241 blendfunc1 = GL_SRC_ALPHA;
242 blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
247 blendfunc2 = GL_ZERO;
250 R_Model_Alias_GetVerts(ent, varray_vertex, aliasvert_normals, NULL, NULL);
251 memcpy(varray_texcoord[0], model->mdlmd2data_texcoords, model->numverts * sizeof(float[4]));
252 if (!skinframe->base && !skinframe->pants && !skinframe->shirt && !skinframe->glow)
255 memset(&m, 0, sizeof(m));
256 m.blendfunc1 = blendfunc1;
257 m.blendfunc2 = blendfunc2;
258 colorscale = r_colorscale;
259 if (gl_combine.integer)
262 m.texrgbscale[0] = 4;
264 m.tex[0] = R_GetTexture(r_notexture);
266 c_alias_polys += model->numtris;
267 for (i = 0;i < model->numverts * 4;i += 4)
269 varray_texcoord[0][i + 0] *= 8.0f;
270 varray_texcoord[0][i + 1] *= 8.0f;
272 R_LightModel(ent, model->numverts, varray_vertex, aliasvert_normals, varray_color, colorscale, colorscale, colorscale, false);
273 R_Mesh_Draw(model->numverts, model->numtris, model->mdlmd2data_indices);
277 colormapped = !skinframe->merged || (ent->colormap >= 0 && skinframe->base && (skinframe->pants || skinframe->shirt));
280 // 128-224 are backwards ranges
281 c = (ent->colormap & 0xF) << 4;c += (c >= 128 && c < 224) ? 4 : 12;
282 bcolor = (qbyte *) (&palette_complete[c]);
283 pantsfullbright = c >= 224;
284 VectorScale(bcolor, (1.0f / 255.0f), pantscolor);
285 c = (ent->colormap & 0xF0);c += (c >= 128 && c < 224) ? 4 : 12;
286 bcolor = (qbyte *) (&palette_complete[c]);
287 shirtfullbright = c >= 224;
288 VectorScale(bcolor, (1.0f / 255.0f), shirtcolor);
292 pantscolor[0] = pantscolor[1] = pantscolor[2] = shirtcolor[0] = shirtcolor[1] = shirtcolor[2] = 1;
293 pantsfullbright = shirtfullbright = false;
296 tex = colormapped ? R_GetTexture(skinframe->base) : R_GetTexture(skinframe->merged);
299 memset(&m, 0, sizeof(m));
300 m.blendfunc1 = blendfunc1;
301 m.blendfunc2 = blendfunc2;
302 colorscale = r_colorscale;
303 if (gl_combine.integer)
306 m.texrgbscale[0] = 4;
311 GL_Color(colorscale * ifog, colorscale * ifog, colorscale * ifog, ent->alpha);
313 R_LightModel(ent, model->numverts, varray_vertex, aliasvert_normals, varray_color, colorscale * ifog, colorscale * ifog, colorscale * ifog, false);
314 R_Mesh_Draw(model->numverts, model->numtris, model->mdlmd2data_indices);
315 c_alias_polys += model->numtris;
316 blendfunc1 = GL_SRC_ALPHA;
322 if (skinframe->pants)
324 tex = R_GetTexture(skinframe->pants);
327 memset(&m, 0, sizeof(m));
328 m.blendfunc1 = blendfunc1;
329 m.blendfunc2 = blendfunc2;
330 colorscale = r_colorscale;
331 if (gl_combine.integer)
334 m.texrgbscale[0] = 4;
339 GL_Color(pantscolor[0] * colorscale * ifog, pantscolor[1] * colorscale * ifog, pantscolor[2] * colorscale * ifog, ent->alpha);
341 R_LightModel(ent, model->numverts, varray_vertex, aliasvert_normals, varray_color, pantscolor[0] * colorscale * ifog, pantscolor[1] * colorscale * ifog, pantscolor[2] * colorscale * ifog, false);
342 R_Mesh_Draw(model->numverts, model->numtris, model->mdlmd2data_indices);
343 c_alias_polys += model->numtris;
344 blendfunc1 = GL_SRC_ALPHA;
348 if (skinframe->shirt)
350 tex = R_GetTexture(skinframe->shirt);
353 memset(&m, 0, sizeof(m));
354 m.blendfunc1 = blendfunc1;
355 m.blendfunc2 = blendfunc2;
356 colorscale = r_colorscale;
357 if (gl_combine.integer)
360 m.texrgbscale[0] = 4;
365 GL_Color(shirtcolor[0] * colorscale * ifog, shirtcolor[1] * colorscale * ifog, shirtcolor[2] * colorscale * ifog, ent->alpha);
367 R_LightModel(ent, model->numverts, varray_vertex, aliasvert_normals, varray_color, shirtcolor[0] * colorscale * ifog, shirtcolor[1] * colorscale * ifog, shirtcolor[2] * colorscale * ifog, false);
368 R_Mesh_Draw(model->numverts, model->numtris, model->mdlmd2data_indices);
369 c_alias_polys += model->numtris;
370 blendfunc1 = GL_SRC_ALPHA;
377 tex = R_GetTexture(skinframe->glow);
380 memset(&m, 0, sizeof(m));
381 m.blendfunc1 = blendfunc1;
382 m.blendfunc2 = blendfunc2;
386 blendfunc1 = GL_SRC_ALPHA;
388 c_alias_polys += model->numtris;
389 GL_Color(ifog * r_colorscale, ifog * r_colorscale, ifog * r_colorscale, ent->alpha);
390 R_Mesh_Draw(model->numverts, model->numtris, model->mdlmd2data_indices);
395 memset(&m, 0, sizeof(m));
396 m.blendfunc1 = GL_SRC_ALPHA;
397 m.blendfunc2 = GL_ONE;
398 m.tex[0] = R_GetTexture(skinframe->fog);
401 c_alias_polys += model->numtris;
402 GL_Color(fogcolor[0] * fog * r_colorscale, fogcolor[1] * fog * r_colorscale, fogcolor[2] * fog * r_colorscale, ent->alpha);
403 R_Mesh_Draw(model->numverts, model->numtris, model->mdlmd2data_indices);
407 void R_Model_Alias_Draw(entity_render_t *ent)
409 if (ent->alpha < (1.0f / 64.0f))
410 return; // basically completely transparent
414 if (ent->effects & EF_ADDITIVE || ent->alpha != 1.0 || R_FetchSkinFrame(ent)->fog != NULL)
415 R_MeshQueue_AddTransparent(ent->origin, R_DrawAliasModelCallback, ent, 0);
417 R_DrawAliasModelCallback(ent, 0);
420 void R_Model_Alias_DrawFakeShadow (entity_render_t *ent)
425 float *v, planenormal[3], planedist, dist, projection[3], floororigin[3], surfnormal[3], lightdirection[3], v2[3];
427 lightdirection[0] = 0.5;
428 lightdirection[1] = 0.2;
429 lightdirection[2] = -1;
430 VectorNormalizeFast(lightdirection);
432 VectorMA(ent->origin, 65536.0f, lightdirection, v2);
433 if (CL_TraceLine(ent->origin, v2, floororigin, surfnormal, 0, false, NULL) == 1)
436 R_Mesh_Matrix(&ent->matrix);
439 R_Mesh_ResizeCheck(model->numverts);
441 memset(&m, 0, sizeof(m));
442 m.blendfunc1 = GL_SRC_ALPHA;
443 m.blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
446 c_alias_polys += model->numtris;
447 R_Model_Alias_GetVerts(ent, varray_vertex, NULL, NULL, NULL);
449 // put a light direction in the entity's coordinate space
450 Matrix4x4_Transform3x3(&ent->inversematrix, lightdirection, projection);
451 VectorNormalizeFast(projection);
453 // put the plane's normal in the entity's coordinate space
454 Matrix4x4_Transform3x3(&ent->inversematrix, surfnormal, planenormal);
455 VectorNormalizeFast(planenormal);
457 // put the plane's distance in the entity's coordinate space
458 VectorSubtract(floororigin, ent->origin, floororigin);
459 planedist = DotProduct(floororigin, surfnormal) + 2;
461 dist = -1.0f / DotProduct(projection, planenormal);
462 VectorScale(projection, dist, projection);
463 for (i = 0, v = varray_vertex;i < model->numverts;i++, v += 4)
465 dist = DotProduct(v, planenormal) - planedist;
468 VectorMA(v, dist, projection, v);
470 GL_Color(0, 0, 0, 0.5);
471 R_Mesh_Draw(model->numverts, model->numtris, model->mdlmd2data_indices);
474 void R_Model_Alias_DrawShadowVolume(entity_render_t *ent, vec3_t relativelightorigin, float lightradius)
476 float projectdistance;
477 projectdistance = lightradius + ent->model->radius - sqrt(DotProduct(relativelightorigin, relativelightorigin));
478 if (projectdistance > 0.1)
480 R_Mesh_Matrix(&ent->matrix);
481 R_Mesh_ResizeCheck(ent->model->numverts * 2);
482 R_Model_Alias_GetVerts(ent, varray_vertex, NULL, NULL, NULL);
483 R_Shadow_Volume(ent->model->numverts, ent->model->numtris, ent->model->mdlmd2data_indices, ent->model->mdlmd2data_triangleneighbors, relativelightorigin, lightradius, projectdistance);
487 void R_Model_Alias_DrawLight(entity_render_t *ent, vec3_t relativelightorigin, vec3_t relativeeyeorigin, float lightradius, float *lightcolor)
490 float lightcolor2[3];
492 skinframe_t *skinframe;
493 R_Mesh_Matrix(&ent->matrix);
494 R_Mesh_ResizeCheck(ent->model->numverts);
495 R_Model_Alias_GetVerts(ent, varray_vertex, aliasvert_normals, aliasvert_svectors, aliasvert_tvectors);
496 skinframe = R_FetchSkinFrame(ent);
498 // note: to properly handle fog this should scale the lightcolor into lightcolor2 according to 1-fog scaling
500 R_Shadow_SpecularLighting(ent->model->numverts, ent->model->numtris, ent->model->mdlmd2data_indices, aliasvert_svectors, aliasvert_tvectors, aliasvert_normals, ent->model->mdlmd2data_texcoords, relativelightorigin, relativeeyeorigin, lightradius, lightcolor, NULL, NULL, NULL);
502 if (!skinframe->base && !skinframe->pants && !skinframe->shirt && !skinframe->glow)
504 R_Shadow_DiffuseLighting(ent->model->numverts, ent->model->numtris, ent->model->mdlmd2data_indices, aliasvert_svectors, aliasvert_tvectors, aliasvert_normals, ent->model->mdlmd2data_texcoords, relativelightorigin, lightradius, lightcolor, r_notexture, NULL, NULL);
508 if (!skinframe->merged || (ent->colormap >= 0 && skinframe->base && (skinframe->pants || skinframe->shirt)))
510 // 128-224 are backwards ranges
511 // we only render non-fullbright ranges here
512 if (skinframe->pants && (ent->colormap & 0xF) < 0xE)
514 c = (ent->colormap & 0xF) << 4;c += (c >= 128 && c < 224) ? 4 : 12;
515 bcolor = (qbyte *) (&palette_complete[c]);
516 lightcolor2[0] = lightcolor[0] * bcolor[0] * (1.0f / 255.0f);
517 lightcolor2[1] = lightcolor[1] * bcolor[1] * (1.0f / 255.0f);
518 lightcolor2[2] = lightcolor[2] * bcolor[2] * (1.0f / 255.0f);
519 R_Shadow_DiffuseLighting(ent->model->numverts, ent->model->numtris, ent->model->mdlmd2data_indices, aliasvert_svectors, aliasvert_tvectors, aliasvert_normals, ent->model->mdlmd2data_texcoords, relativelightorigin, lightradius, lightcolor2, skinframe->pants, skinframe->nmap, NULL);
522 // we only render non-fullbright ranges here
523 if (skinframe->shirt && (ent->colormap & 0xF0) < 0xE0)
525 c = (ent->colormap & 0xF0);c += (c >= 128 && c < 224) ? 4 : 12;
526 bcolor = (qbyte *) (&palette_complete[c]);
527 lightcolor2[0] = lightcolor[0] * bcolor[0] * (1.0f / 255.0f);
528 lightcolor2[1] = lightcolor[1] * bcolor[1] * (1.0f / 255.0f);
529 lightcolor2[2] = lightcolor[2] * bcolor[2] * (1.0f / 255.0f);
530 R_Shadow_DiffuseLighting(ent->model->numverts, ent->model->numtris, ent->model->mdlmd2data_indices, aliasvert_svectors, aliasvert_tvectors, aliasvert_normals, ent->model->mdlmd2data_texcoords, relativelightorigin, lightradius, lightcolor2, skinframe->shirt, skinframe->nmap, NULL);
534 R_Shadow_DiffuseLighting(ent->model->numverts, ent->model->numtris, ent->model->mdlmd2data_indices, aliasvert_svectors, aliasvert_tvectors, aliasvert_normals, ent->model->mdlmd2data_texcoords, relativelightorigin, lightradius, lightcolor, skinframe->base, skinframe->nmap, NULL);
537 if (skinframe->merged)
538 R_Shadow_DiffuseLighting(ent->model->numverts, ent->model->numtris, ent->model->mdlmd2data_indices, aliasvert_svectors, aliasvert_tvectors, aliasvert_normals, ent->model->mdlmd2data_texcoords, relativelightorigin, lightradius, lightcolor, skinframe->merged, skinframe->nmap, NULL);
541 int ZymoticLerpBones(int count, const zymbonematrix *bonebase, const frameblend_t *blend, const zymbone_t *bone)
544 float lerp1, lerp2, lerp3, lerp4;
545 zymbonematrix *out, rootmatrix, m;
546 const zymbonematrix *bone1, *bone2, *bone3, *bone4;
548 rootmatrix.m[0][0] = 1;
549 rootmatrix.m[0][1] = 0;
550 rootmatrix.m[0][2] = 0;
551 rootmatrix.m[0][3] = 0;
552 rootmatrix.m[1][0] = 0;
553 rootmatrix.m[1][1] = 1;
554 rootmatrix.m[1][2] = 0;
555 rootmatrix.m[1][3] = 0;
556 rootmatrix.m[2][0] = 0;
557 rootmatrix.m[2][1] = 0;
558 rootmatrix.m[2][2] = 1;
559 rootmatrix.m[2][3] = 0;
561 bone1 = bonebase + blend[0].frame * count;
562 lerp1 = blend[0].lerp;
565 bone2 = bonebase + blend[1].frame * count;
566 lerp2 = blend[1].lerp;
569 bone3 = bonebase + blend[2].frame * count;
570 lerp3 = blend[2].lerp;
574 bone4 = bonebase + blend[3].frame * count;
575 lerp4 = blend[3].lerp;
576 for (i = 0, out = zymbonepose;i < count;i++, out++)
578 // interpolate matrices
579 m.m[0][0] = bone1->m[0][0] * lerp1 + bone2->m[0][0] * lerp2 + bone3->m[0][0] * lerp3 + bone4->m[0][0] * lerp4;
580 m.m[0][1] = bone1->m[0][1] * lerp1 + bone2->m[0][1] * lerp2 + bone3->m[0][1] * lerp3 + bone4->m[0][1] * lerp4;
581 m.m[0][2] = bone1->m[0][2] * lerp1 + bone2->m[0][2] * lerp2 + bone3->m[0][2] * lerp3 + bone4->m[0][2] * lerp4;
582 m.m[0][3] = bone1->m[0][3] * lerp1 + bone2->m[0][3] * lerp2 + bone3->m[0][3] * lerp3 + bone4->m[0][3] * lerp4;
583 m.m[1][0] = bone1->m[1][0] * lerp1 + bone2->m[1][0] * lerp2 + bone3->m[1][0] * lerp3 + bone4->m[1][0] * lerp4;
584 m.m[1][1] = bone1->m[1][1] * lerp1 + bone2->m[1][1] * lerp2 + bone3->m[1][1] * lerp3 + bone4->m[1][1] * lerp4;
585 m.m[1][2] = bone1->m[1][2] * lerp1 + bone2->m[1][2] * lerp2 + bone3->m[1][2] * lerp3 + bone4->m[1][2] * lerp4;
586 m.m[1][3] = bone1->m[1][3] * lerp1 + bone2->m[1][3] * lerp2 + bone3->m[1][3] * lerp3 + bone4->m[1][3] * lerp4;
587 m.m[2][0] = bone1->m[2][0] * lerp1 + bone2->m[2][0] * lerp2 + bone3->m[2][0] * lerp3 + bone4->m[2][0] * lerp4;
588 m.m[2][1] = bone1->m[2][1] * lerp1 + bone2->m[2][1] * lerp2 + bone3->m[2][1] * lerp3 + bone4->m[2][1] * lerp4;
589 m.m[2][2] = bone1->m[2][2] * lerp1 + bone2->m[2][2] * lerp2 + bone3->m[2][2] * lerp3 + bone4->m[2][2] * lerp4;
590 m.m[2][3] = bone1->m[2][3] * lerp1 + bone2->m[2][3] * lerp2 + bone3->m[2][3] * lerp3 + bone4->m[2][3] * lerp4;
591 if (bone->parent >= 0)
592 R_ConcatTransforms(&zymbonepose[bone->parent].m[0][0], &m.m[0][0], &out->m[0][0]);
594 R_ConcatTransforms(&rootmatrix.m[0][0], &m.m[0][0], &out->m[0][0]);
605 for (i = 0, out = zymbonepose;i < count;i++, out++)
607 // interpolate matrices
608 m.m[0][0] = bone1->m[0][0] * lerp1 + bone2->m[0][0] * lerp2 + bone3->m[0][0] * lerp3;
609 m.m[0][1] = bone1->m[0][1] * lerp1 + bone2->m[0][1] * lerp2 + bone3->m[0][1] * lerp3;
610 m.m[0][2] = bone1->m[0][2] * lerp1 + bone2->m[0][2] * lerp2 + bone3->m[0][2] * lerp3;
611 m.m[0][3] = bone1->m[0][3] * lerp1 + bone2->m[0][3] * lerp2 + bone3->m[0][3] * lerp3;
612 m.m[1][0] = bone1->m[1][0] * lerp1 + bone2->m[1][0] * lerp2 + bone3->m[1][0] * lerp3;
613 m.m[1][1] = bone1->m[1][1] * lerp1 + bone2->m[1][1] * lerp2 + bone3->m[1][1] * lerp3;
614 m.m[1][2] = bone1->m[1][2] * lerp1 + bone2->m[1][2] * lerp2 + bone3->m[1][2] * lerp3;
615 m.m[1][3] = bone1->m[1][3] * lerp1 + bone2->m[1][3] * lerp2 + bone3->m[1][3] * lerp3;
616 m.m[2][0] = bone1->m[2][0] * lerp1 + bone2->m[2][0] * lerp2 + bone3->m[2][0] * lerp3;
617 m.m[2][1] = bone1->m[2][1] * lerp1 + bone2->m[2][1] * lerp2 + bone3->m[2][1] * lerp3;
618 m.m[2][2] = bone1->m[2][2] * lerp1 + bone2->m[2][2] * lerp2 + bone3->m[2][2] * lerp3;
619 m.m[2][3] = bone1->m[2][3] * lerp1 + bone2->m[2][3] * lerp2 + bone3->m[2][3] * lerp3;
620 if (bone->parent >= 0)
621 R_ConcatTransforms(&zymbonepose[bone->parent].m[0][0], &m.m[0][0], &out->m[0][0]);
623 R_ConcatTransforms(&rootmatrix.m[0][0], &m.m[0][0], &out->m[0][0]);
634 for (i = 0, out = zymbonepose;i < count;i++, out++)
636 // interpolate matrices
637 m.m[0][0] = bone1->m[0][0] * lerp1 + bone2->m[0][0] * lerp2;
638 m.m[0][1] = bone1->m[0][1] * lerp1 + bone2->m[0][1] * lerp2;
639 m.m[0][2] = bone1->m[0][2] * lerp1 + bone2->m[0][2] * lerp2;
640 m.m[0][3] = bone1->m[0][3] * lerp1 + bone2->m[0][3] * lerp2;
641 m.m[1][0] = bone1->m[1][0] * lerp1 + bone2->m[1][0] * lerp2;
642 m.m[1][1] = bone1->m[1][1] * lerp1 + bone2->m[1][1] * lerp2;
643 m.m[1][2] = bone1->m[1][2] * lerp1 + bone2->m[1][2] * lerp2;
644 m.m[1][3] = bone1->m[1][3] * lerp1 + bone2->m[1][3] * lerp2;
645 m.m[2][0] = bone1->m[2][0] * lerp1 + bone2->m[2][0] * lerp2;
646 m.m[2][1] = bone1->m[2][1] * lerp1 + bone2->m[2][1] * lerp2;
647 m.m[2][2] = bone1->m[2][2] * lerp1 + bone2->m[2][2] * lerp2;
648 m.m[2][3] = bone1->m[2][3] * lerp1 + bone2->m[2][3] * lerp2;
649 if (bone->parent >= 0)
650 R_ConcatTransforms(&zymbonepose[bone->parent].m[0][0], &m.m[0][0], &out->m[0][0]);
652 R_ConcatTransforms(&rootmatrix.m[0][0], &m.m[0][0], &out->m[0][0]);
665 for (i = 0, out = zymbonepose;i < count;i++, out++)
667 // interpolate matrices
668 m.m[0][0] = bone1->m[0][0] * lerp1;
669 m.m[0][1] = bone1->m[0][1] * lerp1;
670 m.m[0][2] = bone1->m[0][2] * lerp1;
671 m.m[0][3] = bone1->m[0][3] * lerp1;
672 m.m[1][0] = bone1->m[1][0] * lerp1;
673 m.m[1][1] = bone1->m[1][1] * lerp1;
674 m.m[1][2] = bone1->m[1][2] * lerp1;
675 m.m[1][3] = bone1->m[1][3] * lerp1;
676 m.m[2][0] = bone1->m[2][0] * lerp1;
677 m.m[2][1] = bone1->m[2][1] * lerp1;
678 m.m[2][2] = bone1->m[2][2] * lerp1;
679 m.m[2][3] = bone1->m[2][3] * lerp1;
680 if (bone->parent >= 0)
681 R_ConcatTransforms(&zymbonepose[bone->parent].m[0][0], &m.m[0][0], &out->m[0][0]);
683 R_ConcatTransforms(&rootmatrix.m[0][0], &m.m[0][0], &out->m[0][0]);
691 for (i = 0, out = zymbonepose;i < count;i++, out++)
693 if (bone->parent >= 0)
694 R_ConcatTransforms(&zymbonepose[bone->parent].m[0][0], &bone1->m[0][0], &out->m[0][0]);
696 R_ConcatTransforms(&rootmatrix.m[0][0], &bone1->m[0][0], &out->m[0][0]);
705 void ZymoticTransformVerts(int vertcount, float *vertex, int *bonecounts, zymvertex_t *vert)
709 zymbonematrix *matrix;
713 // FIXME: validate bonecounts at load time (must be >= 1)
714 // FIXME: need 4th component in origin, for how much of the translate to blend in
717 matrix = &zymbonepose[vert->bonenum];
718 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];
719 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];
720 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];
728 matrix = &zymbonepose[vert->bonenum];
729 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];
730 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];
731 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];
739 void ZymoticCalcNormals(int vertcount, float *vertex, float *normals, int shadercount, int *renderlist)
742 float *out, v1[3], v2[3], normal[3], s;
745 memset(normals, 0, sizeof(float) * vertcount * 3);
746 memset(aliasvertusage, 0, sizeof(int) * vertcount);
747 // parse render list and accumulate surface normals
756 v1[0] = vertex[a+0] - vertex[b+0];
757 v1[1] = vertex[a+1] - vertex[b+1];
758 v1[2] = vertex[a+2] - vertex[b+2];
759 v2[0] = vertex[c+0] - vertex[b+0];
760 v2[1] = vertex[c+1] - vertex[b+1];
761 v2[2] = vertex[c+2] - vertex[b+2];
762 CrossProduct(v1, v2, normal);
763 VectorNormalizeFast(normal);
764 // add surface normal to vertices
765 a = renderlist[0] * 3;
766 normals[a+0] += normal[0];
767 normals[a+1] += normal[1];
768 normals[a+2] += normal[2];
769 aliasvertusage[renderlist[0]]++;
770 a = renderlist[1] * 3;
771 normals[a+0] += normal[0];
772 normals[a+1] += normal[1];
773 normals[a+2] += normal[2];
774 aliasvertusage[renderlist[1]]++;
775 a = renderlist[2] * 3;
776 normals[a+0] += normal[0];
777 normals[a+1] += normal[1];
778 normals[a+2] += normal[2];
779 aliasvertusage[renderlist[2]]++;
783 // FIXME: precalc this
784 // average surface normals
801 void R_DrawZymoticModelMeshCallback (const void *calldata1, int calldata2)
803 float fog, ifog, colorscale;
805 int i, *renderlist, *elements;
808 const entity_render_t *ent = calldata1;
809 int shadernum = calldata2;
810 int numverts, numtriangles;
812 R_Mesh_Matrix(&ent->matrix);
814 // find the vertex index list and texture
815 renderlist = ent->model->zymdata_renderlist;
816 for (i = 0;i < shadernum;i++)
817 renderlist += renderlist[0] * 3 + 1;
818 texture = ent->model->zymdata_textures[shadernum];
820 numverts = ent->model->zymnum_verts;
821 numtriangles = *renderlist++;
822 elements = renderlist;
823 R_Mesh_ResizeCheck(numverts);
828 VectorSubtract(ent->origin, r_origin, diff);
829 fog = DotProduct(diff,diff);
832 fog = exp(fogdensity/fog);
837 // fog method: darken, additive fog
838 // 1. render model as normal, scaled by inverse of fog alpha (darkens it)
839 // 2. render fog as additive
843 memset(&mstate, 0, sizeof(mstate));
844 if (ent->effects & EF_ADDITIVE)
846 mstate.blendfunc1 = GL_SRC_ALPHA;
847 mstate.blendfunc2 = GL_ONE;
849 else if (ent->alpha != 1.0 || R_TextureHasAlpha(texture))
851 mstate.blendfunc1 = GL_SRC_ALPHA;
852 mstate.blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
856 mstate.blendfunc1 = GL_ONE;
857 mstate.blendfunc2 = GL_ZERO;
859 colorscale = r_colorscale;
860 if (gl_combine.integer)
862 mstate.texrgbscale[0] = 4;
865 mstate.tex[0] = R_GetTexture(texture);
866 R_Mesh_State(&mstate);
867 ZymoticLerpBones(ent->model->zymnum_bones, (zymbonematrix *) ent->model->zymdata_poses, ent->frameblend, ent->model->zymdata_bones);
868 ZymoticTransformVerts(numverts, varray_vertex, ent->model->zymdata_vertbonecounts, ent->model->zymdata_verts);
869 ZymoticCalcNormals(numverts, varray_vertex, aliasvert_normals, ent->model->zymnum_shaders, ent->model->zymdata_renderlist);
870 memcpy(varray_texcoord[0], ent->model->zymdata_texcoords, ent->model->zymnum_verts * sizeof(float[4]));
872 R_LightModel(ent, numverts, varray_vertex, aliasvert_normals, varray_color, ifog * colorscale, ifog * colorscale, ifog * colorscale, false);
873 R_Mesh_Draw(numverts, numtriangles, elements);
874 c_alias_polys += numtriangles;
878 memset(&mstate, 0, sizeof(mstate));
879 mstate.blendfunc1 = GL_SRC_ALPHA;
880 mstate.blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
881 // FIXME: need alpha mask for fogging...
882 //mstate.tex[0] = R_GetTexture(texture);
883 R_Mesh_State(&mstate);
884 GL_Color(fogcolor[0] * r_colorscale, fogcolor[1] * r_colorscale, fogcolor[2] * r_colorscale, ent->alpha * fog);
885 R_Mesh_Draw(numverts, numtriangles, elements);
886 c_alias_polys += numtriangles;
890 void R_Model_Zymotic_Draw(entity_render_t *ent)
894 if (ent->alpha < (1.0f / 64.0f))
895 return; // basically completely transparent
899 for (i = 0;i < ent->model->zymnum_shaders;i++)
901 if (ent->effects & EF_ADDITIVE || ent->alpha != 1.0 || R_TextureHasAlpha(ent->model->zymdata_textures[i]))
902 R_MeshQueue_AddTransparent(ent->origin, R_DrawZymoticModelMeshCallback, ent, i);
904 R_DrawZymoticModelMeshCallback(ent, i);
908 void R_Model_Zymotic_DrawFakeShadow(entity_render_t *ent)
913 void R_Model_Zymotic_DrawLight(entity_render_t *ent, vec3_t relativelightorigin, float lightradius2, float lightdistbias, float lightsubtract, float *lightcolor)
918 void R_Model_Zymotic_DrawOntoLight(entity_render_t *ent)