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 void R_Model_Alias_GetMesh_Vertex3f(const entity_render_t *ent, aliasmesh_t *mesh, float *vertex3f, float *normal3f, float *svector3f, float *tvector3f)
84 float lerp1, lerp2, lerp3, lerp4;
85 const aliasvertex_t *verts1, *verts2, *verts3, *verts4;
88 Host_Error("R_Model_Alias_GetMesh_Vertex3f: vertices == NULL.\n");
89 if (svector3f != NULL && (tvector3f == NULL || normal3f == NULL))
90 Host_Error("R_Model_Alias_GetMesh_Vertex3f: svectors requires tvectors and normals.\n");
91 if (tvector3f != NULL && (svector3f == NULL || normal3f == NULL))
92 Host_Error("R_Model_Alias_GetMesh_Vertex3f: tvectors requires svectors and normals.\n");
94 vertcount = mesh->num_vertices;
95 verts1 = mesh->data_aliasvertex + ent->frameblend[0].frame * vertcount;
96 lerp1 = ent->frameblend[0].lerp;
97 if (ent->frameblend[1].lerp)
99 verts2 = mesh->data_aliasvertex + ent->frameblend[1].frame * vertcount;
100 lerp2 = ent->frameblend[1].lerp;
101 if (ent->frameblend[2].lerp)
103 verts3 = mesh->data_aliasvertex + ent->frameblend[2].frame * vertcount;
104 lerp3 = ent->frameblend[2].lerp;
105 if (ent->frameblend[3].lerp)
107 verts4 = mesh->data_aliasvertex + ent->frameblend[3].frame * vertcount;
108 lerp4 = ent->frameblend[3].lerp;
110 if (svector3f != NULL)
112 for (i = 0;i < vertcount;i++, vertex3f += 3, normal3f += 3, svector3f += 3, tvector3f += 3, verts1++, verts2++, verts3++, verts4++)
114 VectorMAMAMAM(lerp1, verts1->origin, lerp2, verts2->origin, lerp3, verts3->origin, lerp4, verts4->origin, vertex3f);
115 VectorMAMAMAM(lerp1, verts1->normal, lerp2, verts2->normal, lerp3, verts3->normal, lerp4, verts4->normal, normal3f);
116 VectorMAMAMAM(lerp1, verts1->svector, lerp2, verts2->svector, lerp3, verts3->svector, lerp4, verts4->svector, svector3f);
117 CrossProduct(svector3f, normal3f, tvector3f);
120 else if (normal3f != NULL)
122 for (i = 0;i < vertcount;i++, vertex3f += 3, normal3f += 3, verts1++, verts2++, verts3++, verts4++)
124 VectorMAMAMAM(lerp1, verts1->origin, lerp2, verts2->origin, lerp3, verts3->origin, lerp4, verts4->origin, vertex3f);
125 VectorMAMAMAM(lerp1, verts1->normal, lerp2, verts2->normal, lerp3, verts3->normal, lerp4, verts4->normal, normal3f);
129 for (i = 0;i < vertcount;i++, vertex3f += 3, verts1++, verts2++, verts3++, verts4++)
130 VectorMAMAMAM(lerp1, verts1->origin, lerp2, verts2->origin, lerp3, verts3->origin, lerp4, verts4->origin, vertex3f);
135 if (svector3f != NULL)
137 for (i = 0;i < vertcount;i++, vertex3f += 3, normal3f += 3, svector3f += 3, tvector3f += 3, verts1++, verts2++, verts3++)
139 VectorMAMAM(lerp1, verts1->origin, lerp2, verts2->origin, lerp3, verts3->origin, vertex3f);
140 VectorMAMAM(lerp1, verts1->normal, lerp2, verts2->normal, lerp3, verts3->normal, normal3f);
141 VectorMAMAM(lerp1, verts1->svector, lerp2, verts2->svector, lerp3, verts3->svector, svector3f);
142 CrossProduct(svector3f, normal3f, tvector3f);
145 else if (normal3f != NULL)
147 for (i = 0;i < vertcount;i++, vertex3f += 3, normal3f += 3, verts1++, verts2++, verts3++)
149 VectorMAMAM(lerp1, verts1->origin, lerp2, verts2->origin, lerp3, verts3->origin, vertex3f);
150 VectorMAMAM(lerp1, verts1->normal, lerp2, verts2->normal, lerp3, verts3->normal, normal3f);
154 for (i = 0;i < vertcount;i++, vertex3f += 3, verts1++, verts2++, verts3++)
155 VectorMAMAM(lerp1, verts1->origin, lerp2, verts2->origin, lerp3, verts3->origin, vertex3f);
161 if (svector3f != NULL)
163 for (i = 0;i < vertcount;i++, vertex3f += 3, normal3f += 3, svector3f += 3, tvector3f += 3, verts1++, verts2++)
165 VectorMAM(lerp1, verts1->origin, lerp2, verts2->origin, vertex3f);
166 VectorMAM(lerp1, verts1->normal, lerp2, verts2->normal, normal3f);
167 VectorMAM(lerp1, verts1->svector, lerp2, verts2->svector, svector3f);
168 CrossProduct(svector3f, normal3f, tvector3f);
171 else if (normal3f != NULL)
173 for (i = 0;i < vertcount;i++, vertex3f += 3, normal3f += 3, verts1++, verts2++)
175 VectorMAM(lerp1, verts1->origin, lerp2, verts2->origin, vertex3f);
176 VectorMAM(lerp1, verts1->normal, lerp2, verts2->normal, normal3f);
180 for (i = 0;i < vertcount;i++, vertex3f += 3, verts1++, verts2++)
181 VectorMAM(lerp1, verts1->origin, lerp2, verts2->origin, vertex3f);
187 if (svector3f != NULL)
189 for (i = 0;i < vertcount;i++, vertex3f += 3, normal3f += 3, svector3f += 3, tvector3f += 3, verts1++)
191 VectorCopy(verts1->origin, vertex3f);
192 VectorCopy(verts1->normal, normal3f);
193 VectorCopy(verts1->svector, svector3f);
194 CrossProduct(svector3f, normal3f, tvector3f);
197 else if (normal3f != NULL)
199 for (i = 0;i < vertcount;i++, vertex3f += 3, normal3f += 3, verts1++)
201 VectorCopy(verts1->origin, vertex3f);
202 VectorCopy(verts1->normal, normal3f);
206 for (i = 0;i < vertcount;i++, vertex3f += 3, verts1++)
207 VectorCopy(verts1->origin, vertex3f);
211 aliaslayer_t r_aliasnoskinlayers[2] = {{ALIASLAYER_DIFFUSE, NULL, NULL}, {ALIASLAYER_FOG | ALIASLAYER_FORCEDRAW_IF_FIRSTPASS, NULL, NULL}};
212 aliasskin_t r_aliasnoskin = {0, 2, r_aliasnoskinlayers};
213 aliasskin_t *R_FetchAliasSkin(const entity_render_t *ent, const aliasmesh_t *mesh)
215 model_t *model = ent->model;
218 int s = ent->skinnum;
219 if ((unsigned int)s >= (unsigned int)model->numskins)
221 if (model->skinscenes[s].framecount > 1)
222 s = model->skinscenes[s].firstframe + (int) (cl.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
224 s = model->skinscenes[s].firstframe;
225 if (s >= mesh->num_skins)
227 return mesh->data_skins + s;
231 r_aliasnoskinlayers[0].texture = r_notexture;
232 return &r_aliasnoskin;
236 void R_DrawAliasModelCallback (const void *calldata1, int calldata2)
238 int c, fullbright, layernum, firstpass;
239 float tint[3], fog, ifog, colorscale;
243 const entity_render_t *ent = calldata1;
244 aliasmesh_t *mesh = ent->model->aliasdata_meshes + calldata2;
248 R_Mesh_Matrix(&ent->matrix);
253 VectorSubtract(ent->origin, r_origin, diff);
254 fog = DotProduct(diff,diff);
257 fog = exp(fogdensity/fog);
262 // fog method: darken, additive fog
263 // 1. render model as normal, scaled by inverse of fog alpha (darkens it)
264 // 2. render fog as additive
269 memset(&m, 0, sizeof(m));
270 skin = R_FetchAliasSkin(ent, mesh);
271 for (layernum = 0, layer = skin->data_layers;layernum < skin->num_layers;layernum++, layer++)
273 if (!(layer->flags & ALIASLAYER_FORCEDRAW_IF_FIRSTPASS) || !firstpass)
275 if (((layer->flags & ALIASLAYER_NODRAW_IF_NOTCOLORMAPPED) && ent->colormap < 0)
276 || ((layer->flags & ALIASLAYER_NODRAW_IF_COLORMAPPED) && ent->colormap >= 0)
277 || ((layer->flags & ALIASLAYER_FOG) && !fogenabled)
278 || (layer->flags & ALIASLAYER_SPECULAR)
279 || ((layer->flags & ALIASLAYER_DIFFUSE) && (r_shadow_realtime_world.integer && r_ambient.integer <= 0 && r_fullbright.integer == 0 && !(ent->effects & EF_FULLBRIGHT))))
282 if (!firstpass || (ent->effects & EF_ADDITIVE))
284 m.blendfunc1 = GL_SRC_ALPHA;
285 m.blendfunc2 = GL_ONE;
287 else if ((skin->flags & ALIASSKIN_TRANSPARENT) || ent->alpha != 1.0)
289 m.blendfunc1 = GL_SRC_ALPHA;
290 m.blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
294 m.blendfunc1 = GL_ONE;
295 m.blendfunc2 = GL_ZERO;
298 expandaliasvert(mesh->num_vertices);
299 colorscale = r_colorscale;
300 m.texrgbscale[0] = 1;
301 m.tex[0] = R_GetTexture(layer->texture);
302 if (gl_combine.integer && layer->flags & (ALIASLAYER_DIFFUSE | ALIASLAYER_SPECULAR))
305 m.texrgbscale[0] = 4;
308 c_alias_polys += mesh->num_triangles;
309 R_Mesh_GetSpace(mesh->num_vertices);
310 if (layer->texture != NULL)
311 R_Mesh_CopyTexCoord2f(0, mesh->data_texcoord2f, mesh->num_vertices);
312 if (layer->flags & ALIASLAYER_FOG)
315 R_Model_Alias_GetMesh_Vertex3f(ent, mesh, varray_vertex3f, NULL, NULL, NULL);
316 GL_Color(fogcolor[0] * colorscale, fogcolor[1] * colorscale, fogcolor[2] * colorscale, ent->alpha);
320 if (layer->flags & (ALIASLAYER_COLORMAP_PANTS | ALIASLAYER_COLORMAP_SHIRT))
322 // 128-224 are backwards ranges
323 if (layer->flags & ALIASLAYER_COLORMAP_PANTS)
324 c = (ent->colormap & 0xF) << 4;
325 else //if (layer->flags & ALIASLAYER_COLORMAP_SHIRT)
326 c = (ent->colormap & 0xF0);
327 c += (c >= 128 && c < 224) ? 4 : 12;
328 bcolor = (qbyte *) (&palette_complete[c]);
329 fullbright = c >= 224;
330 VectorScale(bcolor, (1.0f / 255.0f), tint);
334 tint[0] = tint[1] = tint[2] = 1;
338 if (fullbright || !(layer->flags & ALIASLAYER_DIFFUSE) || r_fullbright.integer || (ent->effects & EF_FULLBRIGHT))
340 R_Model_Alias_GetMesh_Vertex3f(ent, mesh, varray_vertex3f, NULL, NULL, NULL);
341 GL_Color(tint[0] * colorscale, tint[1] * colorscale, tint[2] * colorscale, ent->alpha);
343 else if (r_shadow_realtime_world.integer)
345 R_Model_Alias_GetMesh_Vertex3f(ent, mesh, varray_vertex3f, NULL, NULL, NULL);
346 colorscale *= r_ambient.value * (2.0f / 128.0f);
347 GL_Color(tint[0] * colorscale, tint[1] * colorscale, tint[2] * colorscale, ent->alpha);
351 R_Model_Alias_GetMesh_Vertex3f(ent, mesh, varray_vertex3f, aliasvert_normal3f, NULL, NULL);
352 R_LightModel(ent, mesh->num_vertices, varray_vertex3f, aliasvert_normal3f, varray_color4f, tint[0] * colorscale, tint[1] * colorscale, tint[2] * colorscale, false);
355 R_Mesh_Draw(mesh->num_vertices, mesh->num_triangles, mesh->data_element3i);
359 void R_Model_Alias_Draw(entity_render_t *ent)
363 if (ent->alpha < (1.0f / 64.0f))
364 return; // basically completely transparent
368 for (meshnum = 0, mesh = ent->model->aliasdata_meshes;meshnum < ent->model->aliasnum_meshes;meshnum++, mesh++)
370 if (ent->effects & EF_ADDITIVE || ent->alpha != 1.0 || R_FetchAliasSkin(ent, mesh)->flags & ALIASSKIN_TRANSPARENT)
371 R_MeshQueue_AddTransparent(ent->origin, R_DrawAliasModelCallback, ent, meshnum);
373 R_DrawAliasModelCallback(ent, meshnum);
377 void R_Model_Alias_DrawFakeShadow (entity_render_t *ent)
383 float *v, planenormal[3], planedist, dist, projection[3], floororigin[3], surfnormal[3], lightdirection[3], v2[3];
385 if ((ent->effects & EF_ADDITIVE) || ent->alpha < 1)
388 lightdirection[0] = 0.5;
389 lightdirection[1] = 0.2;
390 lightdirection[2] = -1;
391 VectorNormalizeFast(lightdirection);
393 VectorMA(ent->origin, 65536.0f, lightdirection, v2);
394 if (CL_TraceLine(ent->origin, v2, floororigin, surfnormal, 0, false, NULL) == 1)
397 R_Mesh_Matrix(&ent->matrix);
399 memset(&m, 0, sizeof(m));
400 m.blendfunc1 = GL_SRC_ALPHA;
401 m.blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
403 GL_Color(0, 0, 0, 0.5);
405 // put a light direction in the entity's coordinate space
406 Matrix4x4_Transform3x3(&ent->inversematrix, lightdirection, projection);
407 VectorNormalizeFast(projection);
409 // put the plane's normal in the entity's coordinate space
410 Matrix4x4_Transform3x3(&ent->inversematrix, surfnormal, planenormal);
411 VectorNormalizeFast(planenormal);
413 // put the plane's distance in the entity's coordinate space
414 VectorSubtract(floororigin, ent->origin, floororigin);
415 planedist = DotProduct(floororigin, surfnormal) + 2;
417 dist = -1.0f / DotProduct(projection, planenormal);
418 VectorScale(projection, dist, projection);
419 for (meshnum = 0, mesh = ent->model->aliasdata_meshes;meshnum < ent->model->aliasnum_meshes;meshnum++)
421 skin = R_FetchAliasSkin(ent, mesh);
422 if (skin->flags & ALIASSKIN_TRANSPARENT)
424 R_Mesh_GetSpace(mesh->num_vertices);
425 R_Model_Alias_GetMesh_Vertex3f(ent, mesh, varray_vertex3f, NULL, NULL, NULL);
426 for (i = 0, v = varray_vertex3f;i < mesh->num_vertices;i++, v += 3)
428 dist = DotProduct(v, planenormal) - planedist;
430 VectorMA(v, dist, projection, v);
432 c_alias_polys += mesh->num_triangles;
433 R_Mesh_Draw(mesh->num_vertices, mesh->num_triangles, mesh->data_element3i);
437 void R_Model_Alias_DrawShadowVolume(entity_render_t *ent, vec3_t relativelightorigin, float lightradius)
442 float projectdistance;
443 if (ent->effects & EF_ADDITIVE || ent->alpha < 1)
445 projectdistance = lightradius + ent->model->radius - sqrt(DotProduct(relativelightorigin, relativelightorigin));
446 if (projectdistance > 0.1)
448 R_Mesh_Matrix(&ent->matrix);
449 for (meshnum = 0, mesh = ent->model->aliasdata_meshes;meshnum < ent->model->aliasnum_meshes;meshnum++, mesh++)
451 skin = R_FetchAliasSkin(ent, mesh);
452 if (skin->flags & ALIASSKIN_TRANSPARENT)
454 R_Mesh_GetSpace(mesh->num_vertices * 2);
455 R_Model_Alias_GetMesh_Vertex3f(ent, mesh, varray_vertex3f, NULL, NULL, NULL);
456 R_Shadow_Volume(mesh->num_vertices, mesh->num_triangles, mesh->data_element3i, mesh->data_neighbor3i, relativelightorigin, lightradius, projectdistance);
461 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)
463 int c, meshnum, layernum;
464 float fog, ifog, lightcolor2[3], *vertices;
471 if (ent->effects & (EF_ADDITIVE | EF_FULLBRIGHT) || ent->alpha < 1)
474 R_Mesh_Matrix(&ent->matrix);
479 VectorSubtract(ent->origin, r_origin, diff);
480 fog = DotProduct(diff,diff);
483 fog = exp(fogdensity/fog);
488 // fog method: darken, additive fog
489 // 1. render model as normal, scaled by inverse of fog alpha (darkens it)
490 // 2. render fog as additive
494 for (meshnum = 0, mesh = ent->model->aliasdata_meshes;meshnum < ent->model->aliasnum_meshes;meshnum++, mesh++)
496 skin = R_FetchAliasSkin(ent, mesh);
497 if (skin->flags & ALIASSKIN_TRANSPARENT)
499 expandaliasvert(mesh->num_vertices);
500 vertices = R_Shadow_VertexBuffer(mesh->num_vertices);
501 R_Model_Alias_GetMesh_Vertex3f(ent, mesh, vertices, aliasvert_normal3f, aliasvert_svector3f, aliasvert_tvector3f);
502 for (layernum = 0, layer = skin->data_layers;layernum < skin->num_layers;layernum++, layer++)
504 if (!(layer->flags & (ALIASLAYER_DIFFUSE | ALIASLAYER_SPECULAR))
505 || ((layer->flags & ALIASLAYER_NODRAW_IF_NOTCOLORMAPPED) && ent->colormap < 0)
506 || ((layer->flags & ALIASLAYER_NODRAW_IF_COLORMAPPED) && ent->colormap >= 0))
508 lightcolor2[0] = lightcolor[0] * ifog;
509 lightcolor2[1] = lightcolor[1] * ifog;
510 lightcolor2[2] = lightcolor[2] * ifog;
511 if (layer->flags & ALIASLAYER_SPECULAR)
513 c_alias_polys += mesh->num_triangles;
514 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);
516 else if (layer->flags & ALIASLAYER_DIFFUSE)
518 if (layer->flags & ALIASLAYER_COLORMAP_PANTS)
520 // 128-224 are backwards ranges
521 c = (ent->colormap & 0xF) << 4;c += (c >= 128 && c < 224) ? 4 : 12;
522 // fullbright passes were already taken care of, so skip them in realtime lighting passes
525 bcolor = (qbyte *) (&palette_complete[c]);
526 lightcolor2[0] *= bcolor[0] * (1.0f / 255.0f);
527 lightcolor2[1] *= bcolor[1] * (1.0f / 255.0f);
528 lightcolor2[2] *= bcolor[2] * (1.0f / 255.0f);
530 else if (layer->flags & ALIASLAYER_COLORMAP_SHIRT)
532 // 128-224 are backwards ranges
533 c = (ent->colormap & 0xF0);c += (c >= 128 && c < 224) ? 4 : 12;
534 // fullbright passes were already taken care of, so skip them in realtime lighting passes
537 bcolor = (qbyte *) (&palette_complete[c]);
538 lightcolor2[0] *= bcolor[0] * (1.0f / 255.0f);
539 lightcolor2[1] *= bcolor[1] * (1.0f / 255.0f);
540 lightcolor2[2] *= bcolor[2] * (1.0f / 255.0f);
542 c_alias_polys += mesh->num_triangles;
543 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);
549 int ZymoticLerpBones(int count, const zymbonematrix *bonebase, const frameblend_t *blend, const zymbone_t *bone)
552 float lerp1, lerp2, lerp3, lerp4;
553 zymbonematrix *out, rootmatrix, m;
554 const zymbonematrix *bone1, *bone2, *bone3, *bone4;
556 rootmatrix.m[0][0] = 1;
557 rootmatrix.m[0][1] = 0;
558 rootmatrix.m[0][2] = 0;
559 rootmatrix.m[0][3] = 0;
560 rootmatrix.m[1][0] = 0;
561 rootmatrix.m[1][1] = 1;
562 rootmatrix.m[1][2] = 0;
563 rootmatrix.m[1][3] = 0;
564 rootmatrix.m[2][0] = 0;
565 rootmatrix.m[2][1] = 0;
566 rootmatrix.m[2][2] = 1;
567 rootmatrix.m[2][3] = 0;
569 bone1 = bonebase + blend[0].frame * count;
570 lerp1 = blend[0].lerp;
573 bone2 = bonebase + blend[1].frame * count;
574 lerp2 = blend[1].lerp;
577 bone3 = bonebase + blend[2].frame * count;
578 lerp3 = blend[2].lerp;
582 bone4 = bonebase + blend[3].frame * count;
583 lerp4 = blend[3].lerp;
584 for (i = 0, out = zymbonepose;i < count;i++, out++)
586 // interpolate matrices
587 m.m[0][0] = bone1->m[0][0] * lerp1 + bone2->m[0][0] * lerp2 + bone3->m[0][0] * lerp3 + bone4->m[0][0] * lerp4;
588 m.m[0][1] = bone1->m[0][1] * lerp1 + bone2->m[0][1] * lerp2 + bone3->m[0][1] * lerp3 + bone4->m[0][1] * lerp4;
589 m.m[0][2] = bone1->m[0][2] * lerp1 + bone2->m[0][2] * lerp2 + bone3->m[0][2] * lerp3 + bone4->m[0][2] * lerp4;
590 m.m[0][3] = bone1->m[0][3] * lerp1 + bone2->m[0][3] * lerp2 + bone3->m[0][3] * lerp3 + bone4->m[0][3] * lerp4;
591 m.m[1][0] = bone1->m[1][0] * lerp1 + bone2->m[1][0] * lerp2 + bone3->m[1][0] * lerp3 + bone4->m[1][0] * lerp4;
592 m.m[1][1] = bone1->m[1][1] * lerp1 + bone2->m[1][1] * lerp2 + bone3->m[1][1] * lerp3 + bone4->m[1][1] * lerp4;
593 m.m[1][2] = bone1->m[1][2] * lerp1 + bone2->m[1][2] * lerp2 + bone3->m[1][2] * lerp3 + bone4->m[1][2] * lerp4;
594 m.m[1][3] = bone1->m[1][3] * lerp1 + bone2->m[1][3] * lerp2 + bone3->m[1][3] * lerp3 + bone4->m[1][3] * lerp4;
595 m.m[2][0] = bone1->m[2][0] * lerp1 + bone2->m[2][0] * lerp2 + bone3->m[2][0] * lerp3 + bone4->m[2][0] * lerp4;
596 m.m[2][1] = bone1->m[2][1] * lerp1 + bone2->m[2][1] * lerp2 + bone3->m[2][1] * lerp3 + bone4->m[2][1] * lerp4;
597 m.m[2][2] = bone1->m[2][2] * lerp1 + bone2->m[2][2] * lerp2 + bone3->m[2][2] * lerp3 + bone4->m[2][2] * lerp4;
598 m.m[2][3] = bone1->m[2][3] * lerp1 + bone2->m[2][3] * lerp2 + bone3->m[2][3] * lerp3 + bone4->m[2][3] * lerp4;
599 if (bone->parent >= 0)
600 R_ConcatTransforms(&zymbonepose[bone->parent].m[0][0], &m.m[0][0], &out->m[0][0]);
602 R_ConcatTransforms(&rootmatrix.m[0][0], &m.m[0][0], &out->m[0][0]);
613 for (i = 0, out = zymbonepose;i < count;i++, out++)
615 // interpolate matrices
616 m.m[0][0] = bone1->m[0][0] * lerp1 + bone2->m[0][0] * lerp2 + bone3->m[0][0] * lerp3;
617 m.m[0][1] = bone1->m[0][1] * lerp1 + bone2->m[0][1] * lerp2 + bone3->m[0][1] * lerp3;
618 m.m[0][2] = bone1->m[0][2] * lerp1 + bone2->m[0][2] * lerp2 + bone3->m[0][2] * lerp3;
619 m.m[0][3] = bone1->m[0][3] * lerp1 + bone2->m[0][3] * lerp2 + bone3->m[0][3] * lerp3;
620 m.m[1][0] = bone1->m[1][0] * lerp1 + bone2->m[1][0] * lerp2 + bone3->m[1][0] * lerp3;
621 m.m[1][1] = bone1->m[1][1] * lerp1 + bone2->m[1][1] * lerp2 + bone3->m[1][1] * lerp3;
622 m.m[1][2] = bone1->m[1][2] * lerp1 + bone2->m[1][2] * lerp2 + bone3->m[1][2] * lerp3;
623 m.m[1][3] = bone1->m[1][3] * lerp1 + bone2->m[1][3] * lerp2 + bone3->m[1][3] * lerp3;
624 m.m[2][0] = bone1->m[2][0] * lerp1 + bone2->m[2][0] * lerp2 + bone3->m[2][0] * lerp3;
625 m.m[2][1] = bone1->m[2][1] * lerp1 + bone2->m[2][1] * lerp2 + bone3->m[2][1] * lerp3;
626 m.m[2][2] = bone1->m[2][2] * lerp1 + bone2->m[2][2] * lerp2 + bone3->m[2][2] * lerp3;
627 m.m[2][3] = bone1->m[2][3] * lerp1 + bone2->m[2][3] * lerp2 + bone3->m[2][3] * lerp3;
628 if (bone->parent >= 0)
629 R_ConcatTransforms(&zymbonepose[bone->parent].m[0][0], &m.m[0][0], &out->m[0][0]);
631 R_ConcatTransforms(&rootmatrix.m[0][0], &m.m[0][0], &out->m[0][0]);
642 for (i = 0, out = zymbonepose;i < count;i++, out++)
644 // interpolate matrices
645 m.m[0][0] = bone1->m[0][0] * lerp1 + bone2->m[0][0] * lerp2;
646 m.m[0][1] = bone1->m[0][1] * lerp1 + bone2->m[0][1] * lerp2;
647 m.m[0][2] = bone1->m[0][2] * lerp1 + bone2->m[0][2] * lerp2;
648 m.m[0][3] = bone1->m[0][3] * lerp1 + bone2->m[0][3] * lerp2;
649 m.m[1][0] = bone1->m[1][0] * lerp1 + bone2->m[1][0] * lerp2;
650 m.m[1][1] = bone1->m[1][1] * lerp1 + bone2->m[1][1] * lerp2;
651 m.m[1][2] = bone1->m[1][2] * lerp1 + bone2->m[1][2] * lerp2;
652 m.m[1][3] = bone1->m[1][3] * lerp1 + bone2->m[1][3] * lerp2;
653 m.m[2][0] = bone1->m[2][0] * lerp1 + bone2->m[2][0] * lerp2;
654 m.m[2][1] = bone1->m[2][1] * lerp1 + bone2->m[2][1] * lerp2;
655 m.m[2][2] = bone1->m[2][2] * lerp1 + bone2->m[2][2] * lerp2;
656 m.m[2][3] = bone1->m[2][3] * lerp1 + bone2->m[2][3] * lerp2;
657 if (bone->parent >= 0)
658 R_ConcatTransforms(&zymbonepose[bone->parent].m[0][0], &m.m[0][0], &out->m[0][0]);
660 R_ConcatTransforms(&rootmatrix.m[0][0], &m.m[0][0], &out->m[0][0]);
673 for (i = 0, out = zymbonepose;i < count;i++, out++)
675 // interpolate matrices
676 m.m[0][0] = bone1->m[0][0] * lerp1;
677 m.m[0][1] = bone1->m[0][1] * lerp1;
678 m.m[0][2] = bone1->m[0][2] * lerp1;
679 m.m[0][3] = bone1->m[0][3] * lerp1;
680 m.m[1][0] = bone1->m[1][0] * lerp1;
681 m.m[1][1] = bone1->m[1][1] * lerp1;
682 m.m[1][2] = bone1->m[1][2] * lerp1;
683 m.m[1][3] = bone1->m[1][3] * lerp1;
684 m.m[2][0] = bone1->m[2][0] * lerp1;
685 m.m[2][1] = bone1->m[2][1] * lerp1;
686 m.m[2][2] = bone1->m[2][2] * lerp1;
687 m.m[2][3] = bone1->m[2][3] * lerp1;
688 if (bone->parent >= 0)
689 R_ConcatTransforms(&zymbonepose[bone->parent].m[0][0], &m.m[0][0], &out->m[0][0]);
691 R_ConcatTransforms(&rootmatrix.m[0][0], &m.m[0][0], &out->m[0][0]);
699 for (i = 0, out = zymbonepose;i < count;i++, out++)
701 if (bone->parent >= 0)
702 R_ConcatTransforms(&zymbonepose[bone->parent].m[0][0], &bone1->m[0][0], &out->m[0][0]);
704 R_ConcatTransforms(&rootmatrix.m[0][0], &bone1->m[0][0], &out->m[0][0]);
713 void ZymoticTransformVerts(int vertcount, float *vertex, int *bonecounts, zymvertex_t *vert)
717 zymbonematrix *matrix;
721 // FIXME: validate bonecounts at load time (must be >= 1)
722 // FIXME: need 4th component in origin, for how much of the translate to blend in
725 matrix = &zymbonepose[vert->bonenum];
726 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];
727 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];
728 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];
736 matrix = &zymbonepose[vert->bonenum];
737 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];
738 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];
739 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];
747 void ZymoticCalcNormal3f(int vertcount, float *vertex3f, float *normal3f, int shadercount, int *renderlist)
750 float *out, v1[3], v2[3], normal[3], s;
753 memset(normal3f, 0, sizeof(float) * vertcount * 3);
754 memset(aliasvertusage, 0, sizeof(int) * vertcount);
755 // parse render list and accumulate surface normals
764 v1[0] = vertex3f[a+0] - vertex3f[b+0];
765 v1[1] = vertex3f[a+1] - vertex3f[b+1];
766 v1[2] = vertex3f[a+2] - vertex3f[b+2];
767 v2[0] = vertex3f[c+0] - vertex3f[b+0];
768 v2[1] = vertex3f[c+1] - vertex3f[b+1];
769 v2[2] = vertex3f[c+2] - vertex3f[b+2];
770 CrossProduct(v1, v2, normal);
771 VectorNormalizeFast(normal);
772 // add surface normal to vertices
773 a = renderlist[0] * 3;
774 normal3f[a+0] += normal[0];
775 normal3f[a+1] += normal[1];
776 normal3f[a+2] += normal[2];
777 aliasvertusage[renderlist[0]]++;
778 a = renderlist[1] * 3;
779 normal3f[a+0] += normal[0];
780 normal3f[a+1] += normal[1];
781 normal3f[a+2] += normal[2];
782 aliasvertusage[renderlist[1]]++;
783 a = renderlist[2] * 3;
784 normal3f[a+0] += normal[0];
785 normal3f[a+1] += normal[1];
786 normal3f[a+2] += normal[2];
787 aliasvertusage[renderlist[2]]++;
791 // FIXME: precalc this
792 // average surface normals
809 void R_DrawZymoticModelMeshCallback (const void *calldata1, int calldata2)
811 float fog, ifog, colorscale;
813 int i, *renderlist, *elements;
816 const entity_render_t *ent = calldata1;
817 int shadernum = calldata2;
818 int numverts, numtriangles;
820 R_Mesh_Matrix(&ent->matrix);
822 // find the vertex index list and texture
823 renderlist = ent->model->zymdata_renderlist;
824 for (i = 0;i < shadernum;i++)
825 renderlist += renderlist[0] * 3 + 1;
826 texture = ent->model->zymdata_textures[shadernum];
828 numverts = ent->model->zymnum_verts;
829 numtriangles = *renderlist++;
830 elements = renderlist;
832 expandaliasvert(numverts);
837 VectorSubtract(ent->origin, r_origin, diff);
838 fog = DotProduct(diff,diff);
841 fog = exp(fogdensity/fog);
846 // fog method: darken, additive fog
847 // 1. render model as normal, scaled by inverse of fog alpha (darkens it)
848 // 2. render fog as additive
852 memset(&mstate, 0, sizeof(mstate));
853 if (ent->effects & EF_ADDITIVE)
855 mstate.blendfunc1 = GL_SRC_ALPHA;
856 mstate.blendfunc2 = GL_ONE;
858 else if (ent->alpha != 1.0 || R_TextureHasAlpha(texture))
860 mstate.blendfunc1 = GL_SRC_ALPHA;
861 mstate.blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
865 mstate.blendfunc1 = GL_ONE;
866 mstate.blendfunc2 = GL_ZERO;
868 colorscale = r_colorscale;
869 if (gl_combine.integer)
871 mstate.texrgbscale[0] = 4;
874 mstate.tex[0] = R_GetTexture(texture);
875 R_Mesh_State(&mstate);
876 ZymoticLerpBones(ent->model->zymnum_bones, (zymbonematrix *) ent->model->zymdata_poses, ent->frameblend, ent->model->zymdata_bones);
878 R_Mesh_GetSpace(numverts);
879 ZymoticTransformVerts(numverts, varray_vertex3f, ent->model->zymdata_vertbonecounts, ent->model->zymdata_verts);
880 R_Mesh_CopyTexCoord2f(0, ent->model->zymdata_texcoords, ent->model->zymnum_verts);
881 ZymoticCalcNormal3f(numverts, varray_vertex3f, aliasvert_normal3f, ent->model->zymnum_shaders, ent->model->zymdata_renderlist);
882 R_LightModel(ent, numverts, varray_vertex3f, aliasvert_normal3f, varray_color4f, ifog * colorscale, ifog * colorscale, ifog * colorscale, false);
883 R_Mesh_Draw(numverts, numtriangles, elements);
884 c_alias_polys += numtriangles;
888 memset(&mstate, 0, sizeof(mstate));
889 mstate.blendfunc1 = GL_SRC_ALPHA;
890 mstate.blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
891 // FIXME: need alpha mask for fogging...
892 //mstate.tex[0] = R_GetTexture(texture);
893 R_Mesh_State(&mstate);
894 GL_Color(fogcolor[0] * r_colorscale, fogcolor[1] * r_colorscale, fogcolor[2] * r_colorscale, ent->alpha * fog);
895 R_Mesh_GetSpace(numverts);
896 ZymoticTransformVerts(numverts, varray_vertex3f, ent->model->zymdata_vertbonecounts, ent->model->zymdata_verts);
897 R_Mesh_Draw(numverts, numtriangles, elements);
898 c_alias_polys += numtriangles;
902 void R_Model_Zymotic_Draw(entity_render_t *ent)
906 if (ent->alpha < (1.0f / 64.0f))
907 return; // basically completely transparent
911 for (i = 0;i < ent->model->zymnum_shaders;i++)
913 if (ent->effects & EF_ADDITIVE || ent->alpha != 1.0 || R_TextureHasAlpha(ent->model->zymdata_textures[i]))
914 R_MeshQueue_AddTransparent(ent->origin, R_DrawZymoticModelMeshCallback, ent, i);
916 R_DrawZymoticModelMeshCallback(ent, i);
920 void R_Model_Zymotic_DrawFakeShadow(entity_render_t *ent)
925 void R_Model_Zymotic_DrawLight(entity_render_t *ent, vec3_t relativelightorigin, float lightradius2, float lightdistbias, float lightsubtract, float *lightcolor)
930 void R_Model_Zymotic_DrawOntoLight(entity_render_t *ent)