3 #include "cl_collision.h"
11 // LordHavoc: vertex arrays
13 void *aliasvertarrays = NULL;
14 float *aliasvertcolor4fbuf = NULL;
15 float *aliasvertcolor4f = NULL; // this may point at aliasvertcolorbuf or at vertex arrays in the mesh backend
16 float *aliasvert_svector3f = NULL;
17 float *aliasvert_tvector3f = NULL;
18 float *aliasvert_normal3f = NULL;
20 float *aliasvertcolor2_4f = NULL;
22 zymbonematrix *zymbonepose;
24 mempool_t *gl_models_mempool;
26 #define expandaliasvert(newmax) if ((newmax) > aliasvertmax) gl_models_allocarrays(newmax)
28 void gl_models_allocarrays(int newmax)
31 aliasvertmax = newmax;
32 if (aliasvertarrays != NULL)
33 Mem_Free(aliasvertarrays);
34 aliasvertarrays = Mem_Alloc(gl_models_mempool, aliasvertmax * (sizeof(float[4+4+3+3+3]) + sizeof(int[3])));
35 data = aliasvertarrays;
36 aliasvertcolor4f = aliasvertcolor4fbuf = (void *)data;data += aliasvertmax * sizeof(float[4]);
37 aliasvertcolor2_4f = (void *)data;data += aliasvertmax * sizeof(float[4]); // used temporarily for tinted coloring
38 aliasvert_svector3f = (void *)data;data += aliasvertmax * sizeof(float[3]);
39 aliasvert_tvector3f = (void *)data;data += aliasvertmax * sizeof(float[3]);
40 aliasvert_normal3f = (void *)data;data += aliasvertmax * sizeof(float[3]);
41 aliasvertusage = (void *)data;data += aliasvertmax * sizeof(int[3]);
44 void gl_models_freearrays(void)
47 if (aliasvertarrays != NULL)
48 Mem_Free(aliasvertarrays);
49 aliasvertarrays = NULL;
50 aliasvertcolor4f = aliasvertcolor4fbuf = NULL;
51 aliasvertcolor2_4f = NULL;
52 aliasvert_svector3f = NULL;
53 aliasvert_tvector3f = NULL;
54 aliasvert_normal3f = NULL;
55 aliasvertusage = NULL;
58 void gl_models_start(void)
60 // allocate vertex processing arrays
61 gl_models_mempool = Mem_AllocPool("GL_Models");
62 zymbonepose = Mem_Alloc(gl_models_mempool, sizeof(zymbonematrix[256]));
63 gl_models_allocarrays(4096);
66 void gl_models_shutdown(void)
68 gl_models_freearrays();
69 Mem_FreePool(&gl_models_mempool);
72 void gl_models_newmap(void)
76 void GL_Models_Init(void)
78 R_RegisterModule("GL_Models", gl_models_start, gl_models_shutdown, gl_models_newmap);
81 #define MODELARRAY_VERTEX 0
82 #define MODELARRAY_SVECTOR 1
83 #define MODELARRAY_TVECTOR 2
84 #define MODELARRAY_NORMAL 3
86 void R_Model_Alias_GetMesh_Array3f(const entity_render_t *ent, aliasmesh_t *mesh, int whicharray, float *out3f)
89 float lerp1, lerp2, lerp3, lerp4;
90 const float *vertsbase, *verts1, *verts2, *verts3, *verts4;
94 case MODELARRAY_VERTEX:vertsbase = mesh->data_aliasvertex3f;break;
95 case MODELARRAY_SVECTOR:vertsbase = mesh->data_aliassvector3f;break;
96 case MODELARRAY_TVECTOR:vertsbase = mesh->data_aliastvector3f;break;
97 case MODELARRAY_NORMAL:vertsbase = mesh->data_aliasnormal3f;break;
99 Host_Error("R_Model_Alias_GetBlendedArray: unknown whicharray %i\n", whicharray);
103 vertcount = mesh->num_vertices;
104 verts1 = vertsbase + ent->frameblend[0].frame * vertcount * 3;
105 lerp1 = ent->frameblend[0].lerp;
106 if (ent->frameblend[1].lerp)
108 verts2 = vertsbase + ent->frameblend[1].frame * vertcount * 3;
109 lerp2 = ent->frameblend[1].lerp;
110 if (ent->frameblend[2].lerp)
112 verts3 = vertsbase + ent->frameblend[2].frame * vertcount * 3;
113 lerp3 = ent->frameblend[2].lerp;
114 if (ent->frameblend[3].lerp)
116 verts4 = vertsbase + ent->frameblend[3].frame * vertcount * 3;
117 lerp4 = ent->frameblend[3].lerp;
118 for (i = 0;i < vertcount * 3;i++)
119 VectorMAMAMAM(lerp1, verts1 + i, lerp2, verts2 + i, lerp3, verts3 + i, lerp4, verts4 + i, out3f + i);
122 for (i = 0;i < vertcount * 3;i++)
123 VectorMAMAM(lerp1, verts1 + i, lerp2, verts2 + i, lerp3, verts3 + i, out3f + i);
126 for (i = 0;i < vertcount * 3;i++)
127 VectorMAM(lerp1, verts1 + i, lerp2, verts2 + i, out3f + i);
130 memcpy(out3f, verts1, vertcount * sizeof(float[3]));
133 aliaslayer_t r_aliasnoskinlayers[2] = {{ALIASLAYER_DIFFUSE, NULL, NULL}, {ALIASLAYER_FOG | ALIASLAYER_FORCEDRAW_IF_FIRSTPASS, NULL, NULL}};
134 aliasskin_t r_aliasnoskin = {0, 2, r_aliasnoskinlayers};
135 aliasskin_t *R_FetchAliasSkin(const entity_render_t *ent, const aliasmesh_t *mesh)
137 model_t *model = ent->model;
140 int s = ent->skinnum;
141 if ((unsigned int)s >= (unsigned int)model->numskins)
143 if (model->skinscenes[s].framecount > 1)
144 s = model->skinscenes[s].firstframe + (int) (cl.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
146 s = model->skinscenes[s].firstframe;
147 if (s >= mesh->num_skins)
149 return mesh->data_skins + s;
153 r_aliasnoskinlayers[0].texture = r_notexture;
154 return &r_aliasnoskin;
158 void R_DrawAliasModelCallback (const void *calldata1, int calldata2)
160 int c, fullbright, layernum, firstpass;
161 float tint[3], fog, ifog, colorscale;
165 const entity_render_t *ent = calldata1;
166 aliasmesh_t *mesh = ent->model->aliasdata_meshes + calldata2;
170 R_Mesh_Matrix(&ent->matrix);
175 VectorSubtract(ent->origin, r_origin, diff);
176 fog = DotProduct(diff,diff);
179 fog = exp(fogdensity/fog);
184 // fog method: darken, additive fog
185 // 1. render model as normal, scaled by inverse of fog alpha (darkens it)
186 // 2. render fog as additive
191 memset(&m, 0, sizeof(m));
192 skin = R_FetchAliasSkin(ent, mesh);
193 for (layernum = 0, layer = skin->data_layers;layernum < skin->num_layers;layernum++, layer++)
195 if (!(layer->flags & ALIASLAYER_FORCEDRAW_IF_FIRSTPASS) || !firstpass)
197 if (((layer->flags & ALIASLAYER_NODRAW_IF_NOTCOLORMAPPED) && ent->colormap < 0)
198 || ((layer->flags & ALIASLAYER_NODRAW_IF_COLORMAPPED) && ent->colormap >= 0)
199 || ((layer->flags & ALIASLAYER_FOG) && !fogenabled)
200 || (layer->flags & ALIASLAYER_SPECULAR)
201 || ((layer->flags & ALIASLAYER_DIFFUSE) && (r_shadow_realtime_world.integer && r_ambient.integer <= 0 && r_fullbright.integer == 0 && !(ent->effects & EF_FULLBRIGHT))))
204 if (!firstpass || (ent->effects & EF_ADDITIVE))
206 m.blendfunc1 = GL_SRC_ALPHA;
207 m.blendfunc2 = GL_ONE;
209 else if ((skin->flags & ALIASSKIN_TRANSPARENT) || ent->alpha != 1.0)
211 m.blendfunc1 = GL_SRC_ALPHA;
212 m.blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
216 m.blendfunc1 = GL_ONE;
217 m.blendfunc2 = GL_ZERO;
220 expandaliasvert(mesh->num_vertices);
221 colorscale = r_colorscale;
222 m.texrgbscale[0] = 1;
223 m.tex[0] = R_GetTexture(layer->texture);
224 if (gl_combine.integer && layer->flags & (ALIASLAYER_DIFFUSE | ALIASLAYER_SPECULAR))
227 m.texrgbscale[0] = 4;
230 c_alias_polys += mesh->num_triangles;
231 R_Mesh_GetSpace(mesh->num_vertices);
232 if (layer->texture != NULL)
233 R_Mesh_CopyTexCoord2f(0, mesh->data_texcoord2f, mesh->num_vertices);
234 if (layer->flags & ALIASLAYER_FOG)
237 R_Model_Alias_GetMesh_Array3f(ent, mesh, MODELARRAY_VERTEX, varray_vertex3f);
238 GL_Color(fogcolor[0] * colorscale, fogcolor[1] * colorscale, fogcolor[2] * colorscale, ent->alpha);
242 if (layer->flags & (ALIASLAYER_COLORMAP_PANTS | ALIASLAYER_COLORMAP_SHIRT))
244 // 128-224 are backwards ranges
245 if (layer->flags & ALIASLAYER_COLORMAP_PANTS)
246 c = (ent->colormap & 0xF) << 4;
247 else //if (layer->flags & ALIASLAYER_COLORMAP_SHIRT)
248 c = (ent->colormap & 0xF0);
249 c += (c >= 128 && c < 224) ? 4 : 12;
250 bcolor = (qbyte *) (&palette_complete[c]);
251 fullbright = c >= 224;
252 VectorScale(bcolor, (1.0f / 255.0f), tint);
256 tint[0] = tint[1] = tint[2] = 1;
260 R_Model_Alias_GetMesh_Array3f(ent, mesh, MODELARRAY_VERTEX, varray_vertex3f);
261 if (fullbright || !(layer->flags & ALIASLAYER_DIFFUSE) || r_fullbright.integer || (ent->effects & EF_FULLBRIGHT))
262 GL_Color(tint[0] * colorscale, tint[1] * colorscale, tint[2] * colorscale, ent->alpha);
263 else if (r_shadow_realtime_world.integer)
265 colorscale *= r_ambient.value * (2.0f / 128.0f);
266 GL_Color(tint[0] * colorscale, tint[1] * colorscale, tint[2] * colorscale, ent->alpha);
270 R_Model_Alias_GetMesh_Array3f(ent, mesh, MODELARRAY_NORMAL, aliasvert_normal3f);
271 R_LightModel(ent, mesh->num_vertices, varray_vertex3f, aliasvert_normal3f, varray_color4f, tint[0] * colorscale, tint[1] * colorscale, tint[2] * colorscale, false);
274 R_Mesh_Draw(mesh->num_vertices, mesh->num_triangles, mesh->data_element3i);
278 void R_Model_Alias_Draw(entity_render_t *ent)
282 if (ent->alpha < (1.0f / 64.0f))
283 return; // basically completely transparent
287 for (meshnum = 0, mesh = ent->model->aliasdata_meshes;meshnum < ent->model->aliasnum_meshes;meshnum++, mesh++)
289 if (ent->effects & EF_ADDITIVE || ent->alpha != 1.0 || R_FetchAliasSkin(ent, mesh)->flags & ALIASSKIN_TRANSPARENT)
290 R_MeshQueue_AddTransparent(ent->origin, R_DrawAliasModelCallback, ent, meshnum);
292 R_DrawAliasModelCallback(ent, meshnum);
296 void R_Model_Alias_DrawFakeShadow (entity_render_t *ent)
302 float *v, planenormal[3], planedist, dist, projection[3], floororigin[3], surfnormal[3], lightdirection[3], v2[3];
304 if ((ent->effects & EF_ADDITIVE) || ent->alpha < 1)
307 lightdirection[0] = 0.5;
308 lightdirection[1] = 0.2;
309 lightdirection[2] = -1;
310 VectorNormalizeFast(lightdirection);
312 VectorMA(ent->origin, 65536.0f, lightdirection, v2);
313 if (CL_TraceLine(ent->origin, v2, floororigin, surfnormal, 0, false, NULL) == 1)
316 R_Mesh_Matrix(&ent->matrix);
318 memset(&m, 0, sizeof(m));
319 m.blendfunc1 = GL_SRC_ALPHA;
320 m.blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
322 GL_Color(0, 0, 0, 0.5);
324 // put a light direction in the entity's coordinate space
325 Matrix4x4_Transform3x3(&ent->inversematrix, lightdirection, projection);
326 VectorNormalizeFast(projection);
328 // put the plane's normal in the entity's coordinate space
329 Matrix4x4_Transform3x3(&ent->inversematrix, surfnormal, planenormal);
330 VectorNormalizeFast(planenormal);
332 // put the plane's distance in the entity's coordinate space
333 VectorSubtract(floororigin, ent->origin, floororigin);
334 planedist = DotProduct(floororigin, surfnormal) + 2;
336 dist = -1.0f / DotProduct(projection, planenormal);
337 VectorScale(projection, dist, projection);
338 for (meshnum = 0, mesh = ent->model->aliasdata_meshes;meshnum < ent->model->aliasnum_meshes;meshnum++)
340 skin = R_FetchAliasSkin(ent, mesh);
341 if (skin->flags & ALIASSKIN_TRANSPARENT)
343 R_Mesh_GetSpace(mesh->num_vertices);
344 R_Model_Alias_GetMesh_Array3f(ent, mesh, MODELARRAY_VERTEX, varray_vertex3f);
345 for (i = 0, v = varray_vertex3f;i < mesh->num_vertices;i++, v += 3)
347 dist = DotProduct(v, planenormal) - planedist;
349 VectorMA(v, dist, projection, v);
351 c_alias_polys += mesh->num_triangles;
352 R_Mesh_Draw(mesh->num_vertices, mesh->num_triangles, mesh->data_element3i);
356 void R_Model_Alias_DrawShadowVolume(entity_render_t *ent, vec3_t relativelightorigin, float lightradius)
361 float projectdistance;
362 if (ent->effects & EF_ADDITIVE || ent->alpha < 1)
364 projectdistance = lightradius + ent->model->radius - sqrt(DotProduct(relativelightorigin, relativelightorigin));
365 if (projectdistance > 0.1)
367 R_Mesh_Matrix(&ent->matrix);
368 for (meshnum = 0, mesh = ent->model->aliasdata_meshes;meshnum < ent->model->aliasnum_meshes;meshnum++, mesh++)
370 skin = R_FetchAliasSkin(ent, mesh);
371 if (skin->flags & ALIASSKIN_TRANSPARENT)
373 R_Mesh_GetSpace(mesh->num_vertices * 2);
374 R_Model_Alias_GetMesh_Array3f(ent, mesh, MODELARRAY_VERTEX, varray_vertex3f);
375 R_Shadow_Volume(mesh->num_vertices, mesh->num_triangles, mesh->data_element3i, mesh->data_neighbor3i, relativelightorigin, lightradius, projectdistance);
380 void R_Model_Alias_DrawLight(entity_render_t *ent, vec3_t relativelightorigin, vec3_t relativeeyeorigin, float lightradius, float *lightcolor, const matrix4x4_t *matrix_modeltofilter, const matrix4x4_t *matrix_modeltoattenuationxyz, const matrix4x4_t *matrix_modeltoattenuationz)
382 int c, meshnum, layernum;
383 float fog, ifog, lightcolor2[3], *vertices;
390 if (ent->effects & (EF_ADDITIVE | EF_FULLBRIGHT) || ent->alpha < 1)
393 R_Mesh_Matrix(&ent->matrix);
398 VectorSubtract(ent->origin, r_origin, diff);
399 fog = DotProduct(diff,diff);
402 fog = exp(fogdensity/fog);
407 // fog method: darken, additive fog
408 // 1. render model as normal, scaled by inverse of fog alpha (darkens it)
409 // 2. render fog as additive
413 for (meshnum = 0, mesh = ent->model->aliasdata_meshes;meshnum < ent->model->aliasnum_meshes;meshnum++, mesh++)
415 skin = R_FetchAliasSkin(ent, mesh);
416 if (skin->flags & ALIASSKIN_TRANSPARENT)
418 expandaliasvert(mesh->num_vertices);
419 vertices = R_Shadow_VertexBuffer(mesh->num_vertices);
420 R_Model_Alias_GetMesh_Array3f(ent, mesh, MODELARRAY_VERTEX, vertices);
421 R_Model_Alias_GetMesh_Array3f(ent, mesh, MODELARRAY_SVECTOR, aliasvert_svector3f);
422 R_Model_Alias_GetMesh_Array3f(ent, mesh, MODELARRAY_TVECTOR, aliasvert_tvector3f);
423 R_Model_Alias_GetMesh_Array3f(ent, mesh, MODELARRAY_NORMAL, aliasvert_normal3f);
424 for (layernum = 0, layer = skin->data_layers;layernum < skin->num_layers;layernum++, layer++)
426 if (!(layer->flags & (ALIASLAYER_DIFFUSE | ALIASLAYER_SPECULAR))
427 || ((layer->flags & ALIASLAYER_NODRAW_IF_NOTCOLORMAPPED) && ent->colormap < 0)
428 || ((layer->flags & ALIASLAYER_NODRAW_IF_COLORMAPPED) && ent->colormap >= 0))
430 lightcolor2[0] = lightcolor[0] * ifog;
431 lightcolor2[1] = lightcolor[1] * ifog;
432 lightcolor2[2] = lightcolor[2] * ifog;
433 if (layer->flags & ALIASLAYER_SPECULAR)
435 c_alias_polys += mesh->num_triangles;
436 R_Shadow_SpecularLighting(mesh->num_vertices, mesh->num_triangles, mesh->data_element3i, vertices, aliasvert_svector3f, aliasvert_tvector3f, aliasvert_normal3f, mesh->data_texcoord2f, relativelightorigin, relativeeyeorigin, lightradius, lightcolor2, matrix_modeltofilter, matrix_modeltoattenuationxyz, matrix_modeltoattenuationz, layer->texture, layer->nmap, NULL);
438 else if (layer->flags & ALIASLAYER_DIFFUSE)
440 if (layer->flags & ALIASLAYER_COLORMAP_PANTS)
442 // 128-224 are backwards ranges
443 c = (ent->colormap & 0xF) << 4;c += (c >= 128 && c < 224) ? 4 : 12;
444 // fullbright passes were already taken care of, so skip them in realtime lighting passes
447 bcolor = (qbyte *) (&palette_complete[c]);
448 lightcolor2[0] *= bcolor[0] * (1.0f / 255.0f);
449 lightcolor2[1] *= bcolor[1] * (1.0f / 255.0f);
450 lightcolor2[2] *= bcolor[2] * (1.0f / 255.0f);
452 else if (layer->flags & ALIASLAYER_COLORMAP_SHIRT)
454 // 128-224 are backwards ranges
455 c = (ent->colormap & 0xF0);c += (c >= 128 && c < 224) ? 4 : 12;
456 // fullbright passes were already taken care of, so skip them in realtime lighting passes
459 bcolor = (qbyte *) (&palette_complete[c]);
460 lightcolor2[0] *= bcolor[0] * (1.0f / 255.0f);
461 lightcolor2[1] *= bcolor[1] * (1.0f / 255.0f);
462 lightcolor2[2] *= bcolor[2] * (1.0f / 255.0f);
464 c_alias_polys += mesh->num_triangles;
465 R_Shadow_DiffuseLighting(mesh->num_vertices, mesh->num_triangles, mesh->data_element3i, vertices, aliasvert_svector3f, aliasvert_tvector3f, aliasvert_normal3f, mesh->data_texcoord2f, relativelightorigin, lightradius, lightcolor2, matrix_modeltofilter, matrix_modeltoattenuationxyz, matrix_modeltoattenuationz, layer->texture, layer->nmap, NULL);
471 int ZymoticLerpBones(int count, const zymbonematrix *bonebase, const frameblend_t *blend, const zymbone_t *bone)
474 float lerp1, lerp2, lerp3, lerp4;
475 zymbonematrix *out, rootmatrix, m;
476 const zymbonematrix *bone1, *bone2, *bone3, *bone4;
478 rootmatrix.m[0][0] = 1;
479 rootmatrix.m[0][1] = 0;
480 rootmatrix.m[0][2] = 0;
481 rootmatrix.m[0][3] = 0;
482 rootmatrix.m[1][0] = 0;
483 rootmatrix.m[1][1] = 1;
484 rootmatrix.m[1][2] = 0;
485 rootmatrix.m[1][3] = 0;
486 rootmatrix.m[2][0] = 0;
487 rootmatrix.m[2][1] = 0;
488 rootmatrix.m[2][2] = 1;
489 rootmatrix.m[2][3] = 0;
491 bone1 = bonebase + blend[0].frame * count;
492 lerp1 = blend[0].lerp;
495 bone2 = bonebase + blend[1].frame * count;
496 lerp2 = blend[1].lerp;
499 bone3 = bonebase + blend[2].frame * count;
500 lerp3 = blend[2].lerp;
504 bone4 = bonebase + blend[3].frame * count;
505 lerp4 = blend[3].lerp;
506 for (i = 0, out = zymbonepose;i < count;i++, out++)
508 // interpolate matrices
509 m.m[0][0] = bone1->m[0][0] * lerp1 + bone2->m[0][0] * lerp2 + bone3->m[0][0] * lerp3 + bone4->m[0][0] * lerp4;
510 m.m[0][1] = bone1->m[0][1] * lerp1 + bone2->m[0][1] * lerp2 + bone3->m[0][1] * lerp3 + bone4->m[0][1] * lerp4;
511 m.m[0][2] = bone1->m[0][2] * lerp1 + bone2->m[0][2] * lerp2 + bone3->m[0][2] * lerp3 + bone4->m[0][2] * lerp4;
512 m.m[0][3] = bone1->m[0][3] * lerp1 + bone2->m[0][3] * lerp2 + bone3->m[0][3] * lerp3 + bone4->m[0][3] * lerp4;
513 m.m[1][0] = bone1->m[1][0] * lerp1 + bone2->m[1][0] * lerp2 + bone3->m[1][0] * lerp3 + bone4->m[1][0] * lerp4;
514 m.m[1][1] = bone1->m[1][1] * lerp1 + bone2->m[1][1] * lerp2 + bone3->m[1][1] * lerp3 + bone4->m[1][1] * lerp4;
515 m.m[1][2] = bone1->m[1][2] * lerp1 + bone2->m[1][2] * lerp2 + bone3->m[1][2] * lerp3 + bone4->m[1][2] * lerp4;
516 m.m[1][3] = bone1->m[1][3] * lerp1 + bone2->m[1][3] * lerp2 + bone3->m[1][3] * lerp3 + bone4->m[1][3] * lerp4;
517 m.m[2][0] = bone1->m[2][0] * lerp1 + bone2->m[2][0] * lerp2 + bone3->m[2][0] * lerp3 + bone4->m[2][0] * lerp4;
518 m.m[2][1] = bone1->m[2][1] * lerp1 + bone2->m[2][1] * lerp2 + bone3->m[2][1] * lerp3 + bone4->m[2][1] * lerp4;
519 m.m[2][2] = bone1->m[2][2] * lerp1 + bone2->m[2][2] * lerp2 + bone3->m[2][2] * lerp3 + bone4->m[2][2] * lerp4;
520 m.m[2][3] = bone1->m[2][3] * lerp1 + bone2->m[2][3] * lerp2 + bone3->m[2][3] * lerp3 + bone4->m[2][3] * lerp4;
521 if (bone->parent >= 0)
522 R_ConcatTransforms(&zymbonepose[bone->parent].m[0][0], &m.m[0][0], &out->m[0][0]);
524 R_ConcatTransforms(&rootmatrix.m[0][0], &m.m[0][0], &out->m[0][0]);
535 for (i = 0, out = zymbonepose;i < count;i++, out++)
537 // interpolate matrices
538 m.m[0][0] = bone1->m[0][0] * lerp1 + bone2->m[0][0] * lerp2 + bone3->m[0][0] * lerp3;
539 m.m[0][1] = bone1->m[0][1] * lerp1 + bone2->m[0][1] * lerp2 + bone3->m[0][1] * lerp3;
540 m.m[0][2] = bone1->m[0][2] * lerp1 + bone2->m[0][2] * lerp2 + bone3->m[0][2] * lerp3;
541 m.m[0][3] = bone1->m[0][3] * lerp1 + bone2->m[0][3] * lerp2 + bone3->m[0][3] * lerp3;
542 m.m[1][0] = bone1->m[1][0] * lerp1 + bone2->m[1][0] * lerp2 + bone3->m[1][0] * lerp3;
543 m.m[1][1] = bone1->m[1][1] * lerp1 + bone2->m[1][1] * lerp2 + bone3->m[1][1] * lerp3;
544 m.m[1][2] = bone1->m[1][2] * lerp1 + bone2->m[1][2] * lerp2 + bone3->m[1][2] * lerp3;
545 m.m[1][3] = bone1->m[1][3] * lerp1 + bone2->m[1][3] * lerp2 + bone3->m[1][3] * lerp3;
546 m.m[2][0] = bone1->m[2][0] * lerp1 + bone2->m[2][0] * lerp2 + bone3->m[2][0] * lerp3;
547 m.m[2][1] = bone1->m[2][1] * lerp1 + bone2->m[2][1] * lerp2 + bone3->m[2][1] * lerp3;
548 m.m[2][2] = bone1->m[2][2] * lerp1 + bone2->m[2][2] * lerp2 + bone3->m[2][2] * lerp3;
549 m.m[2][3] = bone1->m[2][3] * lerp1 + bone2->m[2][3] * lerp2 + bone3->m[2][3] * lerp3;
550 if (bone->parent >= 0)
551 R_ConcatTransforms(&zymbonepose[bone->parent].m[0][0], &m.m[0][0], &out->m[0][0]);
553 R_ConcatTransforms(&rootmatrix.m[0][0], &m.m[0][0], &out->m[0][0]);
564 for (i = 0, out = zymbonepose;i < count;i++, out++)
566 // interpolate matrices
567 m.m[0][0] = bone1->m[0][0] * lerp1 + bone2->m[0][0] * lerp2;
568 m.m[0][1] = bone1->m[0][1] * lerp1 + bone2->m[0][1] * lerp2;
569 m.m[0][2] = bone1->m[0][2] * lerp1 + bone2->m[0][2] * lerp2;
570 m.m[0][3] = bone1->m[0][3] * lerp1 + bone2->m[0][3] * lerp2;
571 m.m[1][0] = bone1->m[1][0] * lerp1 + bone2->m[1][0] * lerp2;
572 m.m[1][1] = bone1->m[1][1] * lerp1 + bone2->m[1][1] * lerp2;
573 m.m[1][2] = bone1->m[1][2] * lerp1 + bone2->m[1][2] * lerp2;
574 m.m[1][3] = bone1->m[1][3] * lerp1 + bone2->m[1][3] * lerp2;
575 m.m[2][0] = bone1->m[2][0] * lerp1 + bone2->m[2][0] * lerp2;
576 m.m[2][1] = bone1->m[2][1] * lerp1 + bone2->m[2][1] * lerp2;
577 m.m[2][2] = bone1->m[2][2] * lerp1 + bone2->m[2][2] * lerp2;
578 m.m[2][3] = bone1->m[2][3] * lerp1 + bone2->m[2][3] * lerp2;
579 if (bone->parent >= 0)
580 R_ConcatTransforms(&zymbonepose[bone->parent].m[0][0], &m.m[0][0], &out->m[0][0]);
582 R_ConcatTransforms(&rootmatrix.m[0][0], &m.m[0][0], &out->m[0][0]);
595 for (i = 0, out = zymbonepose;i < count;i++, out++)
597 // interpolate matrices
598 m.m[0][0] = bone1->m[0][0] * lerp1;
599 m.m[0][1] = bone1->m[0][1] * lerp1;
600 m.m[0][2] = bone1->m[0][2] * lerp1;
601 m.m[0][3] = bone1->m[0][3] * lerp1;
602 m.m[1][0] = bone1->m[1][0] * lerp1;
603 m.m[1][1] = bone1->m[1][1] * lerp1;
604 m.m[1][2] = bone1->m[1][2] * lerp1;
605 m.m[1][3] = bone1->m[1][3] * lerp1;
606 m.m[2][0] = bone1->m[2][0] * lerp1;
607 m.m[2][1] = bone1->m[2][1] * lerp1;
608 m.m[2][2] = bone1->m[2][2] * lerp1;
609 m.m[2][3] = bone1->m[2][3] * lerp1;
610 if (bone->parent >= 0)
611 R_ConcatTransforms(&zymbonepose[bone->parent].m[0][0], &m.m[0][0], &out->m[0][0]);
613 R_ConcatTransforms(&rootmatrix.m[0][0], &m.m[0][0], &out->m[0][0]);
621 for (i = 0, out = zymbonepose;i < count;i++, out++)
623 if (bone->parent >= 0)
624 R_ConcatTransforms(&zymbonepose[bone->parent].m[0][0], &bone1->m[0][0], &out->m[0][0]);
626 R_ConcatTransforms(&rootmatrix.m[0][0], &bone1->m[0][0], &out->m[0][0]);
635 void ZymoticTransformVerts(int vertcount, float *vertex, int *bonecounts, zymvertex_t *vert)
639 zymbonematrix *matrix;
643 // FIXME: validate bonecounts at load time (must be >= 1)
644 // FIXME: need 4th component in origin, for how much of the translate to blend in
647 matrix = &zymbonepose[vert->bonenum];
648 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];
649 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];
650 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];
658 matrix = &zymbonepose[vert->bonenum];
659 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];
660 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];
661 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];
669 void ZymoticCalcNormal3f(int vertcount, float *vertex3f, float *normal3f, int shadercount, int *renderlist)
672 float *out, v1[3], v2[3], normal[3], s;
675 memset(normal3f, 0, sizeof(float) * vertcount * 3);
676 memset(aliasvertusage, 0, sizeof(int) * vertcount);
677 // parse render list and accumulate surface normals
686 v1[0] = vertex3f[a+0] - vertex3f[b+0];
687 v1[1] = vertex3f[a+1] - vertex3f[b+1];
688 v1[2] = vertex3f[a+2] - vertex3f[b+2];
689 v2[0] = vertex3f[c+0] - vertex3f[b+0];
690 v2[1] = vertex3f[c+1] - vertex3f[b+1];
691 v2[2] = vertex3f[c+2] - vertex3f[b+2];
692 CrossProduct(v1, v2, normal);
693 VectorNormalizeFast(normal);
694 // add surface normal to vertices
695 a = renderlist[0] * 3;
696 normal3f[a+0] += normal[0];
697 normal3f[a+1] += normal[1];
698 normal3f[a+2] += normal[2];
699 aliasvertusage[renderlist[0]]++;
700 a = renderlist[1] * 3;
701 normal3f[a+0] += normal[0];
702 normal3f[a+1] += normal[1];
703 normal3f[a+2] += normal[2];
704 aliasvertusage[renderlist[1]]++;
705 a = renderlist[2] * 3;
706 normal3f[a+0] += normal[0];
707 normal3f[a+1] += normal[1];
708 normal3f[a+2] += normal[2];
709 aliasvertusage[renderlist[2]]++;
713 // FIXME: precalc this
714 // average surface normals
731 void R_DrawZymoticModelMeshCallback (const void *calldata1, int calldata2)
733 float fog, ifog, colorscale;
735 int i, *renderlist, *elements;
738 const entity_render_t *ent = calldata1;
739 int shadernum = calldata2;
740 int numverts, numtriangles;
742 R_Mesh_Matrix(&ent->matrix);
744 // find the vertex index list and texture
745 renderlist = ent->model->zymdata_renderlist;
746 for (i = 0;i < shadernum;i++)
747 renderlist += renderlist[0] * 3 + 1;
748 texture = ent->model->zymdata_textures[shadernum];
750 numverts = ent->model->zymnum_verts;
751 numtriangles = *renderlist++;
752 elements = renderlist;
754 expandaliasvert(numverts);
759 VectorSubtract(ent->origin, r_origin, diff);
760 fog = DotProduct(diff,diff);
763 fog = exp(fogdensity/fog);
768 // fog method: darken, additive fog
769 // 1. render model as normal, scaled by inverse of fog alpha (darkens it)
770 // 2. render fog as additive
774 memset(&mstate, 0, sizeof(mstate));
775 if (ent->effects & EF_ADDITIVE)
777 mstate.blendfunc1 = GL_SRC_ALPHA;
778 mstate.blendfunc2 = GL_ONE;
780 else if (ent->alpha != 1.0 || R_TextureHasAlpha(texture))
782 mstate.blendfunc1 = GL_SRC_ALPHA;
783 mstate.blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
787 mstate.blendfunc1 = GL_ONE;
788 mstate.blendfunc2 = GL_ZERO;
790 colorscale = r_colorscale;
791 if (gl_combine.integer)
793 mstate.texrgbscale[0] = 4;
796 mstate.tex[0] = R_GetTexture(texture);
797 R_Mesh_State(&mstate);
798 ZymoticLerpBones(ent->model->zymnum_bones, (zymbonematrix *) ent->model->zymdata_poses, ent->frameblend, ent->model->zymdata_bones);
800 R_Mesh_GetSpace(numverts);
801 ZymoticTransformVerts(numverts, varray_vertex3f, ent->model->zymdata_vertbonecounts, ent->model->zymdata_verts);
802 R_Mesh_CopyTexCoord2f(0, ent->model->zymdata_texcoords, ent->model->zymnum_verts);
803 ZymoticCalcNormal3f(numverts, varray_vertex3f, aliasvert_normal3f, ent->model->zymnum_shaders, ent->model->zymdata_renderlist);
804 R_LightModel(ent, numverts, varray_vertex3f, aliasvert_normal3f, varray_color4f, ifog * colorscale, ifog * colorscale, ifog * colorscale, false);
805 R_Mesh_Draw(numverts, numtriangles, elements);
806 c_alias_polys += numtriangles;
810 memset(&mstate, 0, sizeof(mstate));
811 mstate.blendfunc1 = GL_SRC_ALPHA;
812 mstate.blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
813 // FIXME: need alpha mask for fogging...
814 //mstate.tex[0] = R_GetTexture(texture);
815 R_Mesh_State(&mstate);
816 GL_Color(fogcolor[0] * r_colorscale, fogcolor[1] * r_colorscale, fogcolor[2] * r_colorscale, ent->alpha * fog);
817 R_Mesh_GetSpace(numverts);
818 ZymoticTransformVerts(numverts, varray_vertex3f, ent->model->zymdata_vertbonecounts, ent->model->zymdata_verts);
819 R_Mesh_Draw(numverts, numtriangles, elements);
820 c_alias_polys += numtriangles;
824 void R_Model_Zymotic_Draw(entity_render_t *ent)
828 if (ent->alpha < (1.0f / 64.0f))
829 return; // basically completely transparent
833 for (i = 0;i < ent->model->zymnum_shaders;i++)
835 if (ent->effects & EF_ADDITIVE || ent->alpha != 1.0 || R_TextureHasAlpha(ent->model->zymdata_textures[i]))
836 R_MeshQueue_AddTransparent(ent->origin, R_DrawZymoticModelMeshCallback, ent, i);
838 R_DrawZymoticModelMeshCallback(ent, i);
842 void R_Model_Zymotic_DrawFakeShadow(entity_render_t *ent)
847 void R_Model_Zymotic_DrawLight(entity_render_t *ent, vec3_t relativelightorigin, float lightradius2, float lightdistbias, float lightsubtract, float *lightcolor)
852 void R_Model_Zymotic_DrawOntoLight(entity_render_t *ent)