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 aliasskin_t *R_FetchAliasSkin(const entity_render_t *ent, const aliasmesh_t *mesh)
213 model_t *model = ent->model;
214 int s = ent->skinnum;
215 if ((unsigned int)s >= (unsigned int)model->numskins)
217 if (model->skinscenes[s].framecount > 1)
218 s = model->skinscenes[s].firstframe + (int) (cl.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
220 s = model->skinscenes[s].firstframe;
221 if (s >= mesh->num_skins)
223 return mesh->data_skins + s;
226 void R_DrawAliasModelCallback (const void *calldata1, int calldata2)
228 int c, fullbright, layernum;
229 float tint[3], fog, ifog, colorscale;
233 const entity_render_t *ent = calldata1;
234 aliasmesh_t *mesh = ent->model->aliasdata_meshes + calldata2;
238 R_Mesh_Matrix(&ent->matrix);
243 VectorSubtract(ent->origin, r_origin, diff);
244 fog = DotProduct(diff,diff);
247 fog = exp(fogdensity/fog);
252 // fog method: darken, additive fog
253 // 1. render model as normal, scaled by inverse of fog alpha (darkens it)
254 // 2. render fog as additive
258 memset(&m, 0, sizeof(m));
259 skin = R_FetchAliasSkin(ent, mesh);
260 for (layernum = 0, layer = skin->data_layers;layernum < skin->num_layers;layernum++, layer++)
262 if (((layer->flags & ALIASLAYER_NODRAW_IF_NOTCOLORMAPPED) && ent->colormap < 0)
263 || ((layer->flags & ALIASLAYER_NODRAW_IF_COLORMAPPED) && ent->colormap >= 0)
264 || (layer->flags & ALIASLAYER_DRAW_PER_LIGHT))
266 expandaliasvert(mesh->num_vertices);
267 if (layer->flags & ALIASLAYER_FOG)
269 m.blendfunc1 = GL_SRC_ALPHA;
270 m.blendfunc2 = GL_ONE;
271 colorscale = r_colorscale;
272 m.texrgbscale[0] = 1;
273 m.tex[0] = R_GetTexture(layer->texture);
275 GL_Color(fogcolor[0] * fog * colorscale, fogcolor[1] * fog * colorscale, fogcolor[2] * fog * colorscale, ent->alpha);
276 c_alias_polys += mesh->num_triangles;
277 R_Mesh_GetSpace(mesh->num_vertices);
278 R_Model_Alias_GetMesh_Vertex3f(ent, mesh, varray_vertex3f, aliasvert_normal3f, NULL, NULL);
279 if (layer->texture != NULL)
280 R_Mesh_CopyTexCoord2f(0, mesh->data_texcoord2f, mesh->num_vertices);
281 R_Mesh_Draw(mesh->num_vertices, mesh->num_triangles, mesh->data_element3i);
284 if ((layer->flags & ALIASLAYER_ADD) || ((layer->flags & ALIASLAYER_ALPHA) && (ent->effects & EF_ADDITIVE)))
286 m.blendfunc1 = GL_SRC_ALPHA;
287 m.blendfunc2 = GL_ONE;
289 else if ((layer->flags & ALIASLAYER_ALPHA) || ent->alpha != 1.0)
291 m.blendfunc1 = GL_SRC_ALPHA;
292 m.blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
296 m.blendfunc1 = GL_ONE;
297 m.blendfunc2 = GL_ZERO;
299 colorscale = r_colorscale;
300 m.texrgbscale[0] = 1;
301 if (gl_combine.integer)
304 m.texrgbscale[0] = 4;
306 m.tex[0] = R_GetTexture(layer->texture);
308 if (layer->flags & ALIASLAYER_COLORMAP_PANTS)
310 // 128-224 are backwards ranges
311 c = (ent->colormap & 0xF) << 4;c += (c >= 128 && c < 224) ? 4 : 12;
312 bcolor = (qbyte *) (&palette_complete[c]);
313 fullbright = c >= 224;
314 VectorScale(bcolor, (1.0f / 255.0f), tint);
316 else if (layer->flags & ALIASLAYER_COLORMAP_SHIRT)
318 // 128-224 are backwards ranges
319 c = (ent->colormap & 0xF0);c += (c >= 128 && c < 224) ? 4 : 12;
320 bcolor = (qbyte *) (&palette_complete[c]);
321 fullbright = c >= 224;
322 VectorScale(bcolor, (1.0f / 255.0f), tint);
326 tint[0] = tint[1] = tint[2] = 1;
329 VectorScale(tint, ifog * colorscale, tint);
330 if (!(layer->flags & ALIASLAYER_DIFFUSE))
332 if (ent->effects & EF_FULLBRIGHT)
334 c_alias_polys += mesh->num_triangles;
335 R_Mesh_GetSpace(mesh->num_vertices);
336 R_Model_Alias_GetMesh_Vertex3f(ent, mesh, varray_vertex3f, aliasvert_normal3f, NULL, NULL);
337 R_Mesh_CopyTexCoord2f(0, mesh->data_texcoord2f, mesh->num_vertices);
339 GL_Color(tint[0], tint[1], tint[2], ent->alpha);
341 R_LightModel(ent, mesh->num_vertices, varray_vertex3f, aliasvert_normal3f, varray_color4f, tint[0], tint[1], tint[2], false);
342 R_Mesh_Draw(mesh->num_vertices, mesh->num_triangles, mesh->data_element3i);
346 void R_Model_Alias_Draw(entity_render_t *ent)
350 if (ent->alpha < (1.0f / 64.0f))
351 return; // basically completely transparent
355 for (meshnum = 0, mesh = ent->model->aliasdata_meshes;meshnum < ent->model->aliasnum_meshes;meshnum++, mesh++)
357 if (ent->effects & EF_ADDITIVE || ent->alpha != 1.0 || R_FetchAliasSkin(ent, mesh)->flags & ALIASSKIN_TRANSPARENT)
358 R_MeshQueue_AddTransparent(ent->origin, R_DrawAliasModelCallback, ent, meshnum);
360 R_DrawAliasModelCallback(ent, meshnum);
364 void R_Model_Alias_DrawFakeShadow (entity_render_t *ent)
370 float *v, planenormal[3], planedist, dist, projection[3], floororigin[3], surfnormal[3], lightdirection[3], v2[3];
372 if ((ent->effects & EF_ADDITIVE) || ent->alpha < 1)
375 lightdirection[0] = 0.5;
376 lightdirection[1] = 0.2;
377 lightdirection[2] = -1;
378 VectorNormalizeFast(lightdirection);
380 VectorMA(ent->origin, 65536.0f, lightdirection, v2);
381 if (CL_TraceLine(ent->origin, v2, floororigin, surfnormal, 0, false, NULL) == 1)
384 R_Mesh_Matrix(&ent->matrix);
386 memset(&m, 0, sizeof(m));
387 m.blendfunc1 = GL_SRC_ALPHA;
388 m.blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
390 GL_Color(0, 0, 0, 0.5);
392 // put a light direction in the entity's coordinate space
393 Matrix4x4_Transform3x3(&ent->inversematrix, lightdirection, projection);
394 VectorNormalizeFast(projection);
396 // put the plane's normal in the entity's coordinate space
397 Matrix4x4_Transform3x3(&ent->inversematrix, surfnormal, planenormal);
398 VectorNormalizeFast(planenormal);
400 // put the plane's distance in the entity's coordinate space
401 VectorSubtract(floororigin, ent->origin, floororigin);
402 planedist = DotProduct(floororigin, surfnormal) + 2;
404 dist = -1.0f / DotProduct(projection, planenormal);
405 VectorScale(projection, dist, projection);
406 for (meshnum = 0, mesh = ent->model->aliasdata_meshes;meshnum < ent->model->aliasnum_meshes;meshnum++)
408 skin = R_FetchAliasSkin(ent, mesh);
409 if (skin->flags & ALIASSKIN_TRANSPARENT)
411 R_Mesh_GetSpace(mesh->num_vertices);
412 R_Model_Alias_GetMesh_Vertex3f(ent, mesh, varray_vertex3f, NULL, NULL, NULL);
413 for (i = 0, v = varray_vertex3f;i < mesh->num_vertices;i++, v += 3)
415 dist = DotProduct(v, planenormal) - planedist;
417 VectorMA(v, dist, projection, v);
419 c_alias_polys += mesh->num_triangles;
420 R_Mesh_Draw(mesh->num_vertices, mesh->num_triangles, mesh->data_element3i);
424 void R_Model_Alias_DrawShadowVolume(entity_render_t *ent, vec3_t relativelightorigin, float lightradius)
429 float projectdistance;
430 if (ent->effects & EF_ADDITIVE || ent->alpha < 1)
432 projectdistance = lightradius + ent->model->radius - sqrt(DotProduct(relativelightorigin, relativelightorigin));
433 if (projectdistance > 0.1)
435 R_Mesh_Matrix(&ent->matrix);
436 for (meshnum = 0, mesh = ent->model->aliasdata_meshes;meshnum < ent->model->aliasnum_meshes;meshnum++, mesh++)
438 skin = R_FetchAliasSkin(ent, mesh);
439 if (skin->flags & ALIASSKIN_TRANSPARENT)
441 R_Mesh_GetSpace(mesh->num_vertices * 2);
442 R_Model_Alias_GetMesh_Vertex3f(ent, mesh, varray_vertex3f, NULL, NULL, NULL);
443 R_Shadow_Volume(mesh->num_vertices, mesh->num_triangles, mesh->data_element3i, mesh->data_neighbor3i, relativelightorigin, lightradius, projectdistance);
448 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)
450 int c, meshnum, layernum;
451 float fog, ifog, lightcolor2[3], *vertices;
458 if (ent->effects & (EF_ADDITIVE | EF_FULLBRIGHT) || ent->alpha < 1)
461 R_Mesh_Matrix(&ent->matrix);
466 VectorSubtract(ent->origin, r_origin, diff);
467 fog = DotProduct(diff,diff);
470 fog = exp(fogdensity/fog);
475 // fog method: darken, additive fog
476 // 1. render model as normal, scaled by inverse of fog alpha (darkens it)
477 // 2. render fog as additive
481 for (meshnum = 0, mesh = ent->model->aliasdata_meshes;meshnum < ent->model->aliasnum_meshes;meshnum++, mesh++)
483 skin = R_FetchAliasSkin(ent, mesh);
484 if (skin->flags & ALIASSKIN_TRANSPARENT)
486 expandaliasvert(mesh->num_vertices);
487 vertices = R_Shadow_VertexBuffer(mesh->num_vertices);
488 R_Model_Alias_GetMesh_Vertex3f(ent, mesh, vertices, aliasvert_normal3f, aliasvert_svector3f, aliasvert_tvector3f);
489 for (layernum = 0, layer = skin->data_layers;layernum < skin->num_layers;layernum++, layer++)
491 if (!(layer->flags & ALIASLAYER_DRAW_PER_LIGHT)
492 || ((layer->flags & ALIASLAYER_NODRAW_IF_NOTCOLORMAPPED) && ent->colormap < 0)
493 || ((layer->flags & ALIASLAYER_NODRAW_IF_COLORMAPPED) && ent->colormap >= 0))
495 lightcolor2[0] = lightcolor[0] * ifog;
496 lightcolor2[1] = lightcolor[1] * ifog;
497 lightcolor2[2] = lightcolor[2] * ifog;
498 if (layer->flags & ALIASLAYER_SPECULAR)
500 c_alias_polys += mesh->num_triangles;
501 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);
503 else if (layer->flags & ALIASLAYER_DIFFUSE)
505 if (layer->flags & ALIASLAYER_COLORMAP_PANTS)
507 // 128-224 are backwards ranges
508 c = (ent->colormap & 0xF) << 4;c += (c >= 128 && c < 224) ? 4 : 12;
509 // fullbright passes were already taken care of, so skip them in realtime lighting passes
512 bcolor = (qbyte *) (&palette_complete[c]);
513 lightcolor2[0] *= bcolor[0] * (1.0f / 255.0f);
514 lightcolor2[1] *= bcolor[1] * (1.0f / 255.0f);
515 lightcolor2[2] *= bcolor[2] * (1.0f / 255.0f);
517 else if (layer->flags & ALIASLAYER_COLORMAP_SHIRT)
519 // 128-224 are backwards ranges
520 c = (ent->colormap & 0xF0);c += (c >= 128 && c < 224) ? 4 : 12;
521 // fullbright passes were already taken care of, so skip them in realtime lighting passes
524 bcolor = (qbyte *) (&palette_complete[c]);
525 lightcolor2[0] *= bcolor[0] * (1.0f / 255.0f);
526 lightcolor2[1] *= bcolor[1] * (1.0f / 255.0f);
527 lightcolor2[2] *= bcolor[2] * (1.0f / 255.0f);
529 c_alias_polys += mesh->num_triangles;
530 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);
536 int ZymoticLerpBones(int count, const zymbonematrix *bonebase, const frameblend_t *blend, const zymbone_t *bone)
539 float lerp1, lerp2, lerp3, lerp4;
540 zymbonematrix *out, rootmatrix, m;
541 const zymbonematrix *bone1, *bone2, *bone3, *bone4;
543 rootmatrix.m[0][0] = 1;
544 rootmatrix.m[0][1] = 0;
545 rootmatrix.m[0][2] = 0;
546 rootmatrix.m[0][3] = 0;
547 rootmatrix.m[1][0] = 0;
548 rootmatrix.m[1][1] = 1;
549 rootmatrix.m[1][2] = 0;
550 rootmatrix.m[1][3] = 0;
551 rootmatrix.m[2][0] = 0;
552 rootmatrix.m[2][1] = 0;
553 rootmatrix.m[2][2] = 1;
554 rootmatrix.m[2][3] = 0;
556 bone1 = bonebase + blend[0].frame * count;
557 lerp1 = blend[0].lerp;
560 bone2 = bonebase + blend[1].frame * count;
561 lerp2 = blend[1].lerp;
564 bone3 = bonebase + blend[2].frame * count;
565 lerp3 = blend[2].lerp;
569 bone4 = bonebase + blend[3].frame * count;
570 lerp4 = blend[3].lerp;
571 for (i = 0, out = zymbonepose;i < count;i++, out++)
573 // interpolate matrices
574 m.m[0][0] = bone1->m[0][0] * lerp1 + bone2->m[0][0] * lerp2 + bone3->m[0][0] * lerp3 + bone4->m[0][0] * lerp4;
575 m.m[0][1] = bone1->m[0][1] * lerp1 + bone2->m[0][1] * lerp2 + bone3->m[0][1] * lerp3 + bone4->m[0][1] * lerp4;
576 m.m[0][2] = bone1->m[0][2] * lerp1 + bone2->m[0][2] * lerp2 + bone3->m[0][2] * lerp3 + bone4->m[0][2] * lerp4;
577 m.m[0][3] = bone1->m[0][3] * lerp1 + bone2->m[0][3] * lerp2 + bone3->m[0][3] * lerp3 + bone4->m[0][3] * lerp4;
578 m.m[1][0] = bone1->m[1][0] * lerp1 + bone2->m[1][0] * lerp2 + bone3->m[1][0] * lerp3 + bone4->m[1][0] * lerp4;
579 m.m[1][1] = bone1->m[1][1] * lerp1 + bone2->m[1][1] * lerp2 + bone3->m[1][1] * lerp3 + bone4->m[1][1] * lerp4;
580 m.m[1][2] = bone1->m[1][2] * lerp1 + bone2->m[1][2] * lerp2 + bone3->m[1][2] * lerp3 + bone4->m[1][2] * lerp4;
581 m.m[1][3] = bone1->m[1][3] * lerp1 + bone2->m[1][3] * lerp2 + bone3->m[1][3] * lerp3 + bone4->m[1][3] * lerp4;
582 m.m[2][0] = bone1->m[2][0] * lerp1 + bone2->m[2][0] * lerp2 + bone3->m[2][0] * lerp3 + bone4->m[2][0] * lerp4;
583 m.m[2][1] = bone1->m[2][1] * lerp1 + bone2->m[2][1] * lerp2 + bone3->m[2][1] * lerp3 + bone4->m[2][1] * lerp4;
584 m.m[2][2] = bone1->m[2][2] * lerp1 + bone2->m[2][2] * lerp2 + bone3->m[2][2] * lerp3 + bone4->m[2][2] * lerp4;
585 m.m[2][3] = bone1->m[2][3] * lerp1 + bone2->m[2][3] * lerp2 + bone3->m[2][3] * lerp3 + bone4->m[2][3] * lerp4;
586 if (bone->parent >= 0)
587 R_ConcatTransforms(&zymbonepose[bone->parent].m[0][0], &m.m[0][0], &out->m[0][0]);
589 R_ConcatTransforms(&rootmatrix.m[0][0], &m.m[0][0], &out->m[0][0]);
600 for (i = 0, out = zymbonepose;i < count;i++, out++)
602 // interpolate matrices
603 m.m[0][0] = bone1->m[0][0] * lerp1 + bone2->m[0][0] * lerp2 + bone3->m[0][0] * lerp3;
604 m.m[0][1] = bone1->m[0][1] * lerp1 + bone2->m[0][1] * lerp2 + bone3->m[0][1] * lerp3;
605 m.m[0][2] = bone1->m[0][2] * lerp1 + bone2->m[0][2] * lerp2 + bone3->m[0][2] * lerp3;
606 m.m[0][3] = bone1->m[0][3] * lerp1 + bone2->m[0][3] * lerp2 + bone3->m[0][3] * lerp3;
607 m.m[1][0] = bone1->m[1][0] * lerp1 + bone2->m[1][0] * lerp2 + bone3->m[1][0] * lerp3;
608 m.m[1][1] = bone1->m[1][1] * lerp1 + bone2->m[1][1] * lerp2 + bone3->m[1][1] * lerp3;
609 m.m[1][2] = bone1->m[1][2] * lerp1 + bone2->m[1][2] * lerp2 + bone3->m[1][2] * lerp3;
610 m.m[1][3] = bone1->m[1][3] * lerp1 + bone2->m[1][3] * lerp2 + bone3->m[1][3] * lerp3;
611 m.m[2][0] = bone1->m[2][0] * lerp1 + bone2->m[2][0] * lerp2 + bone3->m[2][0] * lerp3;
612 m.m[2][1] = bone1->m[2][1] * lerp1 + bone2->m[2][1] * lerp2 + bone3->m[2][1] * lerp3;
613 m.m[2][2] = bone1->m[2][2] * lerp1 + bone2->m[2][2] * lerp2 + bone3->m[2][2] * lerp3;
614 m.m[2][3] = bone1->m[2][3] * lerp1 + bone2->m[2][3] * lerp2 + bone3->m[2][3] * lerp3;
615 if (bone->parent >= 0)
616 R_ConcatTransforms(&zymbonepose[bone->parent].m[0][0], &m.m[0][0], &out->m[0][0]);
618 R_ConcatTransforms(&rootmatrix.m[0][0], &m.m[0][0], &out->m[0][0]);
629 for (i = 0, out = zymbonepose;i < count;i++, out++)
631 // interpolate matrices
632 m.m[0][0] = bone1->m[0][0] * lerp1 + bone2->m[0][0] * lerp2;
633 m.m[0][1] = bone1->m[0][1] * lerp1 + bone2->m[0][1] * lerp2;
634 m.m[0][2] = bone1->m[0][2] * lerp1 + bone2->m[0][2] * lerp2;
635 m.m[0][3] = bone1->m[0][3] * lerp1 + bone2->m[0][3] * lerp2;
636 m.m[1][0] = bone1->m[1][0] * lerp1 + bone2->m[1][0] * lerp2;
637 m.m[1][1] = bone1->m[1][1] * lerp1 + bone2->m[1][1] * lerp2;
638 m.m[1][2] = bone1->m[1][2] * lerp1 + bone2->m[1][2] * lerp2;
639 m.m[1][3] = bone1->m[1][3] * lerp1 + bone2->m[1][3] * lerp2;
640 m.m[2][0] = bone1->m[2][0] * lerp1 + bone2->m[2][0] * lerp2;
641 m.m[2][1] = bone1->m[2][1] * lerp1 + bone2->m[2][1] * lerp2;
642 m.m[2][2] = bone1->m[2][2] * lerp1 + bone2->m[2][2] * lerp2;
643 m.m[2][3] = bone1->m[2][3] * lerp1 + bone2->m[2][3] * lerp2;
644 if (bone->parent >= 0)
645 R_ConcatTransforms(&zymbonepose[bone->parent].m[0][0], &m.m[0][0], &out->m[0][0]);
647 R_ConcatTransforms(&rootmatrix.m[0][0], &m.m[0][0], &out->m[0][0]);
660 for (i = 0, out = zymbonepose;i < count;i++, out++)
662 // interpolate matrices
663 m.m[0][0] = bone1->m[0][0] * lerp1;
664 m.m[0][1] = bone1->m[0][1] * lerp1;
665 m.m[0][2] = bone1->m[0][2] * lerp1;
666 m.m[0][3] = bone1->m[0][3] * lerp1;
667 m.m[1][0] = bone1->m[1][0] * lerp1;
668 m.m[1][1] = bone1->m[1][1] * lerp1;
669 m.m[1][2] = bone1->m[1][2] * lerp1;
670 m.m[1][3] = bone1->m[1][3] * lerp1;
671 m.m[2][0] = bone1->m[2][0] * lerp1;
672 m.m[2][1] = bone1->m[2][1] * lerp1;
673 m.m[2][2] = bone1->m[2][2] * lerp1;
674 m.m[2][3] = bone1->m[2][3] * lerp1;
675 if (bone->parent >= 0)
676 R_ConcatTransforms(&zymbonepose[bone->parent].m[0][0], &m.m[0][0], &out->m[0][0]);
678 R_ConcatTransforms(&rootmatrix.m[0][0], &m.m[0][0], &out->m[0][0]);
686 for (i = 0, out = zymbonepose;i < count;i++, out++)
688 if (bone->parent >= 0)
689 R_ConcatTransforms(&zymbonepose[bone->parent].m[0][0], &bone1->m[0][0], &out->m[0][0]);
691 R_ConcatTransforms(&rootmatrix.m[0][0], &bone1->m[0][0], &out->m[0][0]);
700 void ZymoticTransformVerts(int vertcount, float *vertex, int *bonecounts, zymvertex_t *vert)
704 zymbonematrix *matrix;
708 // FIXME: validate bonecounts at load time (must be >= 1)
709 // FIXME: need 4th component in origin, for how much of the translate to blend in
712 matrix = &zymbonepose[vert->bonenum];
713 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];
714 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];
715 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];
723 matrix = &zymbonepose[vert->bonenum];
724 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];
725 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];
726 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];
734 void ZymoticCalcNormal3f(int vertcount, float *vertex3f, float *normal3f, int shadercount, int *renderlist)
737 float *out, v1[3], v2[3], normal[3], s;
740 memset(normal3f, 0, sizeof(float) * vertcount * 3);
741 memset(aliasvertusage, 0, sizeof(int) * vertcount);
742 // parse render list and accumulate surface normals
751 v1[0] = vertex3f[a+0] - vertex3f[b+0];
752 v1[1] = vertex3f[a+1] - vertex3f[b+1];
753 v1[2] = vertex3f[a+2] - vertex3f[b+2];
754 v2[0] = vertex3f[c+0] - vertex3f[b+0];
755 v2[1] = vertex3f[c+1] - vertex3f[b+1];
756 v2[2] = vertex3f[c+2] - vertex3f[b+2];
757 CrossProduct(v1, v2, normal);
758 VectorNormalizeFast(normal);
759 // add surface normal to vertices
760 a = renderlist[0] * 3;
761 normal3f[a+0] += normal[0];
762 normal3f[a+1] += normal[1];
763 normal3f[a+2] += normal[2];
764 aliasvertusage[renderlist[0]]++;
765 a = renderlist[1] * 3;
766 normal3f[a+0] += normal[0];
767 normal3f[a+1] += normal[1];
768 normal3f[a+2] += normal[2];
769 aliasvertusage[renderlist[1]]++;
770 a = renderlist[2] * 3;
771 normal3f[a+0] += normal[0];
772 normal3f[a+1] += normal[1];
773 normal3f[a+2] += normal[2];
774 aliasvertusage[renderlist[2]]++;
778 // FIXME: precalc this
779 // average surface normals
796 void R_DrawZymoticModelMeshCallback (const void *calldata1, int calldata2)
798 float fog, ifog, colorscale;
800 int i, *renderlist, *elements;
803 const entity_render_t *ent = calldata1;
804 int shadernum = calldata2;
805 int numverts, numtriangles;
807 R_Mesh_Matrix(&ent->matrix);
809 // find the vertex index list and texture
810 renderlist = ent->model->zymdata_renderlist;
811 for (i = 0;i < shadernum;i++)
812 renderlist += renderlist[0] * 3 + 1;
813 texture = ent->model->zymdata_textures[shadernum];
815 numverts = ent->model->zymnum_verts;
816 numtriangles = *renderlist++;
817 elements = renderlist;
819 expandaliasvert(numverts);
824 VectorSubtract(ent->origin, r_origin, diff);
825 fog = DotProduct(diff,diff);
828 fog = exp(fogdensity/fog);
833 // fog method: darken, additive fog
834 // 1. render model as normal, scaled by inverse of fog alpha (darkens it)
835 // 2. render fog as additive
839 memset(&mstate, 0, sizeof(mstate));
840 if (ent->effects & EF_ADDITIVE)
842 mstate.blendfunc1 = GL_SRC_ALPHA;
843 mstate.blendfunc2 = GL_ONE;
845 else if (ent->alpha != 1.0 || R_TextureHasAlpha(texture))
847 mstate.blendfunc1 = GL_SRC_ALPHA;
848 mstate.blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
852 mstate.blendfunc1 = GL_ONE;
853 mstate.blendfunc2 = GL_ZERO;
855 colorscale = r_colorscale;
856 if (gl_combine.integer)
858 mstate.texrgbscale[0] = 4;
861 mstate.tex[0] = R_GetTexture(texture);
862 R_Mesh_State(&mstate);
863 ZymoticLerpBones(ent->model->zymnum_bones, (zymbonematrix *) ent->model->zymdata_poses, ent->frameblend, ent->model->zymdata_bones);
865 R_Mesh_GetSpace(numverts);
866 ZymoticTransformVerts(numverts, varray_vertex3f, ent->model->zymdata_vertbonecounts, ent->model->zymdata_verts);
867 R_Mesh_CopyTexCoord2f(0, ent->model->zymdata_texcoords, ent->model->zymnum_verts);
868 ZymoticCalcNormal3f(numverts, varray_vertex3f, aliasvert_normal3f, ent->model->zymnum_shaders, ent->model->zymdata_renderlist);
869 R_LightModel(ent, numverts, varray_vertex3f, aliasvert_normal3f, varray_color4f, ifog * colorscale, ifog * colorscale, ifog * colorscale, false);
870 R_Mesh_Draw(numverts, numtriangles, elements);
871 c_alias_polys += numtriangles;
875 memset(&mstate, 0, sizeof(mstate));
876 mstate.blendfunc1 = GL_SRC_ALPHA;
877 mstate.blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
878 // FIXME: need alpha mask for fogging...
879 //mstate.tex[0] = R_GetTexture(texture);
880 R_Mesh_State(&mstate);
881 GL_Color(fogcolor[0] * r_colorscale, fogcolor[1] * r_colorscale, fogcolor[2] * r_colorscale, ent->alpha * fog);
882 R_Mesh_GetSpace(numverts);
883 ZymoticTransformVerts(numverts, varray_vertex3f, ent->model->zymdata_vertbonecounts, ent->model->zymdata_verts);
884 R_Mesh_Draw(numverts, numtriangles, elements);
885 c_alias_polys += numtriangles;
889 void R_Model_Zymotic_Draw(entity_render_t *ent)
893 if (ent->alpha < (1.0f / 64.0f))
894 return; // basically completely transparent
898 for (i = 0;i < ent->model->zymnum_shaders;i++)
900 if (ent->effects & EF_ADDITIVE || ent->alpha != 1.0 || R_TextureHasAlpha(ent->model->zymdata_textures[i]))
901 R_MeshQueue_AddTransparent(ent->origin, R_DrawZymoticModelMeshCallback, ent, i);
903 R_DrawZymoticModelMeshCallback(ent, i);
907 void R_Model_Zymotic_DrawFakeShadow(entity_render_t *ent)
912 void R_Model_Zymotic_DrawLight(entity_render_t *ent, vec3_t relativelightorigin, float lightradius2, float lightdistbias, float lightsubtract, float *lightcolor)
917 void R_Model_Zymotic_DrawOntoLight(entity_render_t *ent)