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_vertex3f = NULL;
17 float *aliasvert_svector3f = NULL;
18 float *aliasvert_tvector3f = NULL;
19 float *aliasvert_normal3f = NULL;
21 float *aliasvertcolor2_4f = NULL;
23 zymbonematrix *zymbonepose;
25 mempool_t *gl_models_mempool;
27 #define expandaliasvert(newmax) if ((newmax) > aliasvertmax) gl_models_allocarrays(newmax)
29 void gl_models_allocarrays(int newmax)
32 aliasvertmax = newmax;
33 if (aliasvertarrays != NULL)
34 Mem_Free(aliasvertarrays);
35 aliasvertarrays = Mem_Alloc(gl_models_mempool, aliasvertmax * (sizeof(float[4+4+3+3+3+3]) + sizeof(int[3])));
36 data = aliasvertarrays;
37 aliasvertcolor4f = aliasvertcolor4fbuf = (void *)data;data += aliasvertmax * sizeof(float[4]);
38 aliasvertcolor2_4f = (void *)data;data += aliasvertmax * sizeof(float[4]); // used temporarily for tinted coloring
39 aliasvert_vertex3f = (void *)data;data += aliasvertmax * sizeof(float[3]);
40 aliasvert_svector3f = (void *)data;data += aliasvertmax * sizeof(float[3]);
41 aliasvert_tvector3f = (void *)data;data += aliasvertmax * sizeof(float[3]);
42 aliasvert_normal3f = (void *)data;data += aliasvertmax * sizeof(float[3]);
43 aliasvertusage = (void *)data;data += aliasvertmax * sizeof(int[3]);
46 void gl_models_freearrays(void)
49 if (aliasvertarrays != NULL)
50 Mem_Free(aliasvertarrays);
51 aliasvertarrays = NULL;
52 aliasvertcolor4f = aliasvertcolor4fbuf = NULL;
53 aliasvertcolor2_4f = NULL;
54 aliasvert_vertex3f = NULL;
55 aliasvert_svector3f = NULL;
56 aliasvert_tvector3f = NULL;
57 aliasvert_normal3f = NULL;
58 aliasvertusage = NULL;
61 void gl_models_start(void)
63 // allocate vertex processing arrays
64 gl_models_mempool = Mem_AllocPool("GL_Models");
65 zymbonepose = Mem_Alloc(gl_models_mempool, sizeof(zymbonematrix[256]));
66 gl_models_allocarrays(4096);
69 void gl_models_shutdown(void)
71 gl_models_freearrays();
72 Mem_FreePool(&gl_models_mempool);
75 void gl_models_newmap(void)
79 void GL_Models_Init(void)
81 R_RegisterModule("GL_Models", gl_models_start, gl_models_shutdown, gl_models_newmap);
84 #define MODELARRAY_VERTEX 0
85 #define MODELARRAY_SVECTOR 1
86 #define MODELARRAY_TVECTOR 2
87 #define MODELARRAY_NORMAL 3
89 void R_Model_Alias_GetMesh_Array3f(const entity_render_t *ent, aliasmesh_t *mesh, int whicharray, float *out3f)
92 float lerp1, lerp2, lerp3, lerp4;
93 const float *vertsbase, *verts1, *verts2, *verts3, *verts4;
97 case MODELARRAY_VERTEX:vertsbase = mesh->data_aliasvertex3f;break;
98 case MODELARRAY_SVECTOR:vertsbase = mesh->data_aliassvector3f;break;
99 case MODELARRAY_TVECTOR:vertsbase = mesh->data_aliastvector3f;break;
100 case MODELARRAY_NORMAL:vertsbase = mesh->data_aliasnormal3f;break;
102 Host_Error("R_Model_Alias_GetBlendedArray: unknown whicharray %i\n", whicharray);
106 vertcount = mesh->num_vertices;
107 verts1 = vertsbase + ent->frameblend[0].frame * vertcount * 3;
108 lerp1 = ent->frameblend[0].lerp;
109 if (ent->frameblend[1].lerp)
111 verts2 = vertsbase + ent->frameblend[1].frame * vertcount * 3;
112 lerp2 = ent->frameblend[1].lerp;
113 if (ent->frameblend[2].lerp)
115 verts3 = vertsbase + ent->frameblend[2].frame * vertcount * 3;
116 lerp3 = ent->frameblend[2].lerp;
117 if (ent->frameblend[3].lerp)
119 verts4 = vertsbase + ent->frameblend[3].frame * vertcount * 3;
120 lerp4 = ent->frameblend[3].lerp;
121 for (i = 0;i < vertcount * 3;i++)
122 VectorMAMAMAM(lerp1, verts1 + i, lerp2, verts2 + i, lerp3, verts3 + i, lerp4, verts4 + i, out3f + i);
125 for (i = 0;i < vertcount * 3;i++)
126 VectorMAMAM(lerp1, verts1 + i, lerp2, verts2 + i, lerp3, verts3 + i, out3f + i);
129 for (i = 0;i < vertcount * 3;i++)
130 VectorMAM(lerp1, verts1 + i, lerp2, verts2 + i, out3f + i);
133 memcpy(out3f, verts1, vertcount * sizeof(float[3]));
136 aliaslayer_t r_aliasnoskinlayers[2] = {{ALIASLAYER_DIFFUSE, NULL, NULL}, {ALIASLAYER_FOG | ALIASLAYER_FORCEDRAW_IF_FIRSTPASS, NULL, NULL}};
137 aliasskin_t r_aliasnoskin = {0, 2, r_aliasnoskinlayers};
138 aliasskin_t *R_FetchAliasSkin(const entity_render_t *ent, const aliasmesh_t *mesh)
140 model_t *model = ent->model;
143 int s = ent->skinnum;
144 if ((unsigned int)s >= (unsigned int)model->numskins)
146 if (model->skinscenes[s].framecount > 1)
147 s = model->skinscenes[s].firstframe + (int) (cl.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
149 s = model->skinscenes[s].firstframe;
150 if (s >= mesh->num_skins)
152 return mesh->data_skins + s;
156 r_aliasnoskinlayers[0].texture = r_notexture;
157 return &r_aliasnoskin;
161 void R_DrawAliasModelCallback (const void *calldata1, int calldata2)
163 int c, fullbright, layernum, firstpass;
164 float tint[3], fog, ifog, colorscale, ambientcolor4f[4];
168 const entity_render_t *ent = calldata1;
169 aliasmesh_t *mesh = ent->model->aliasdata_meshes + calldata2;
172 rcachearrayrequest_t request;
174 R_Mesh_Matrix(&ent->matrix);
179 VectorSubtract(ent->origin, r_origin, diff);
180 fog = DotProduct(diff,diff);
183 fog = exp(fogdensity/fog);
188 // fog method: darken, additive fog
189 // 1. render model as normal, scaled by inverse of fog alpha (darkens it)
190 // 2. render fog as additive
195 skin = R_FetchAliasSkin(ent, mesh);
196 for (layernum = 0, layer = skin->data_layers;layernum < skin->num_layers;layernum++, layer++)
198 if (!(layer->flags & ALIASLAYER_FORCEDRAW_IF_FIRSTPASS) || !firstpass)
200 if (((layer->flags & ALIASLAYER_NODRAW_IF_NOTCOLORMAPPED) && ent->colormap < 0)
201 || ((layer->flags & ALIASLAYER_NODRAW_IF_COLORMAPPED) && ent->colormap >= 0)
202 || ((layer->flags & ALIASLAYER_FOG) && !fogenabled)
203 || (layer->flags & ALIASLAYER_SPECULAR)
204 || ((layer->flags & ALIASLAYER_DIFFUSE) && (r_shadow_realtime_world.integer && r_ambient.integer <= 0 && r_fullbright.integer == 0 && !(ent->effects & EF_FULLBRIGHT))))
207 memset(&m, 0, sizeof(m));
208 if (!firstpass || (ent->effects & EF_ADDITIVE))
210 m.blendfunc1 = GL_SRC_ALPHA;
211 m.blendfunc2 = GL_ONE;
213 else if ((skin->flags & ALIASSKIN_TRANSPARENT) || ent->alpha != 1.0)
215 m.blendfunc1 = GL_SRC_ALPHA;
216 m.blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
220 m.blendfunc1 = GL_ONE;
221 m.blendfunc2 = GL_ZERO;
224 expandaliasvert(mesh->num_vertices);
225 colorscale = r_colorscale;
226 m.texrgbscale[0] = 1;
227 m.tex[0] = R_GetTexture(layer->texture);
228 if (gl_combine.integer && layer->flags & (ALIASLAYER_DIFFUSE | ALIASLAYER_SPECULAR))
231 m.texrgbscale[0] = 4;
233 c_alias_polys += mesh->num_triangles;
234 if (gl_mesh_copyarrays.integer)
237 R_Mesh_GetSpace(mesh->num_vertices);
238 if (layer->texture != NULL)
239 R_Mesh_CopyTexCoord2f(0, mesh->data_texcoord2f, mesh->num_vertices);
240 R_Model_Alias_GetMesh_Array3f(ent, mesh, MODELARRAY_VERTEX, varray_vertex3f);
244 m.pointervertexcount = mesh->num_vertices;
245 memset(&request, 0, sizeof(request));
246 request.data_size = mesh->num_vertices * sizeof(float[3]);
247 request.id_pointer2 = mesh->data_aliasvertex3f;
248 request.id_number1 = layernum;
249 request.id_number2 = 0;
250 request.id_number3 = CRC_Block((void *)ent->frameblend, sizeof(ent->frameblend));
251 if (R_Mesh_CacheArray(&request))
252 R_Model_Alias_GetMesh_Array3f(ent, mesh, MODELARRAY_VERTEX, request.data);
253 m.pointer_vertex = request.data;
254 m.pointer_texcoord[0] = layer->texture != NULL ? mesh->data_texcoord2f : NULL;
256 if (layer->flags & ALIASLAYER_FOG)
259 GL_Color(fogcolor[0] * colorscale, fogcolor[1] * colorscale, fogcolor[2] * colorscale, ent->alpha);
263 if (layer->flags & (ALIASLAYER_COLORMAP_PANTS | ALIASLAYER_COLORMAP_SHIRT))
265 // 128-224 are backwards ranges
266 if (layer->flags & ALIASLAYER_COLORMAP_PANTS)
267 c = (ent->colormap & 0xF) << 4;
268 else //if (layer->flags & ALIASLAYER_COLORMAP_SHIRT)
269 c = (ent->colormap & 0xF0);
270 c += (c >= 128 && c < 224) ? 4 : 12;
271 bcolor = (qbyte *) (&palette_complete[c]);
272 fullbright = c >= 224;
273 VectorScale(bcolor, (1.0f / 255.0f), tint);
277 tint[0] = tint[1] = tint[2] = 1;
281 if (fullbright || !(layer->flags & ALIASLAYER_DIFFUSE) || r_fullbright.integer || (ent->effects & EF_FULLBRIGHT))
282 GL_Color(tint[0] * colorscale, tint[1] * colorscale, tint[2] * colorscale, ent->alpha);
283 else if (r_shadow_realtime_world.integer)
285 colorscale *= r_ambient.value * (2.0f / 128.0f);
286 GL_Color(tint[0] * colorscale, tint[1] * colorscale, tint[2] * colorscale, ent->alpha);
290 if (R_LightModel(ambientcolor4f, ent, tint[0] * colorscale, tint[1] * colorscale, tint[2] * colorscale, ent->alpha, false))
293 if (gl_mesh_copyarrays.integer)
295 R_Model_Alias_GetMesh_Array3f(ent, mesh, MODELARRAY_NORMAL, aliasvert_normal3f);
296 R_LightModel_CalcVertexColors(ambientcolor4f, mesh->num_vertices, varray_vertex3f, aliasvert_normal3f, varray_color4f);
300 // request color4f cache
301 request.data_size = mesh->num_vertices * sizeof(float[4]);
302 request.id_pointer1 = ent;
303 request.id_number2 = 2;
304 request.id_number3 = CRC_Block((void *)ent->frameblend, sizeof(ent->frameblend)) + CRC_Block((void *)&ent->entlightstime, sizeof(ent->entlightstime));
305 if (R_Mesh_CacheArray(&request))
307 // save off the color pointer before we blow away the request
308 m.pointer_color = request.data;
309 // request normal3f cache
310 request.data_size = mesh->num_vertices * sizeof(float[3]);
311 request.id_pointer1 = NULL;
312 request.id_number2 = 3;
313 request.id_number3 = CRC_Block((void *)ent->frameblend, sizeof(ent->frameblend));
314 if (R_Mesh_CacheArray(&request))
315 R_Model_Alias_GetMesh_Array3f(ent, mesh, MODELARRAY_NORMAL, request.data);
316 R_LightModel_CalcVertexColors(ambientcolor4f, mesh->num_vertices, m.pointer_vertex, request.data, m.pointer_color);
319 m.pointer_color = request.data;
323 GL_Color(ambientcolor4f[0], ambientcolor4f[1], ambientcolor4f[2], ambientcolor4f[3]);
326 if (!gl_mesh_copyarrays.integer)
328 R_Mesh_Draw(mesh->num_vertices, mesh->num_triangles, mesh->data_element3i);
332 void R_Model_Alias_Draw(entity_render_t *ent)
336 if (ent->alpha < (1.0f / 64.0f))
337 return; // basically completely transparent
341 for (meshnum = 0, mesh = ent->model->aliasdata_meshes;meshnum < ent->model->aliasnum_meshes;meshnum++, mesh++)
343 if (ent->effects & EF_ADDITIVE || ent->alpha != 1.0 || R_FetchAliasSkin(ent, mesh)->flags & ALIASSKIN_TRANSPARENT)
344 R_MeshQueue_AddTransparent(ent->origin, R_DrawAliasModelCallback, ent, meshnum);
346 R_DrawAliasModelCallback(ent, meshnum);
350 void R_Model_Alias_DrawFakeShadow (entity_render_t *ent)
356 float *v, plane[4], dist, projection[3], floororigin[3], surfnormal[3], lightdirection[3], v2[3];
357 rcachearrayrequest_t request;
359 if ((ent->effects & EF_ADDITIVE) || ent->alpha < 1)
362 lightdirection[0] = 0.5;
363 lightdirection[1] = 0.2;
364 lightdirection[2] = -1;
365 VectorNormalizeFast(lightdirection);
367 VectorMA(ent->origin, 65536.0f, lightdirection, v2);
368 if (CL_TraceLine(ent->origin, v2, floororigin, surfnormal, 0, false, NULL) == 1)
371 R_Mesh_Matrix(&ent->matrix);
373 memset(&m, 0, sizeof(m));
374 m.blendfunc1 = GL_SRC_ALPHA;
375 m.blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
376 if (gl_mesh_copyarrays.integer)
378 GL_Color(0, 0, 0, 0.5);
380 // put a light direction in the entity's coordinate space
381 Matrix4x4_Transform3x3(&ent->inversematrix, lightdirection, projection);
382 VectorNormalizeFast(projection);
384 // put the plane's normal in the entity's coordinate space
385 Matrix4x4_Transform3x3(&ent->inversematrix, surfnormal, plane);
386 VectorNormalizeFast(plane);
388 // put the plane's distance in the entity's coordinate space
389 VectorSubtract(floororigin, ent->origin, floororigin);
390 plane[3] = DotProduct(floororigin, surfnormal) + 2;
392 dist = -1.0f / DotProduct(projection, plane);
393 VectorScale(projection, dist, projection);
394 memset(&request, 0, sizeof(request));
395 for (meshnum = 0, mesh = ent->model->aliasdata_meshes;meshnum < ent->model->aliasnum_meshes;meshnum++)
397 skin = R_FetchAliasSkin(ent, mesh);
398 if (skin->flags & ALIASSKIN_TRANSPARENT)
400 if (gl_mesh_copyarrays.integer)
402 R_Mesh_GetSpace(mesh->num_vertices);
403 R_Model_Alias_GetMesh_Array3f(ent, mesh, MODELARRAY_VERTEX, varray_vertex3f);
404 for (i = 0, v = varray_vertex3f;i < mesh->num_vertices;i++, v += 3)
406 dist = DotProduct(v, plane) - plane[3];
408 VectorMA(v, dist, projection, v);
413 request.data_size = mesh->num_vertices * sizeof(float[3]);
414 request.id_pointer1 = mesh;
415 request.id_number1 = CRC_Block((void *)&ent->matrix, sizeof(ent->matrix));
416 request.id_number2 = CRC_Block((void *)&plane, sizeof(plane));
417 request.id_number3 = CRC_Block((void *)&ent->frameblend, sizeof(ent->frameblend));
418 m.pointervertexcount = mesh->num_vertices;
419 if (R_Mesh_CacheArray(&request))
421 R_Model_Alias_GetMesh_Array3f(ent, mesh, MODELARRAY_VERTEX, request.data);
422 for (i = 0, v = request.data;i < mesh->num_vertices;i++, v += 3)
424 dist = DotProduct(v, plane) - plane[3];
426 VectorMA(v, dist, projection, v);
429 m.pointer_vertex = request.data;
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_Array3f(ent, mesh, MODELARRAY_VERTEX, varray_vertex3f);
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];
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 R_Model_Alias_GetMesh_Array3f(ent, mesh, MODELARRAY_VERTEX, aliasvert_vertex3f);
501 R_Model_Alias_GetMesh_Array3f(ent, mesh, MODELARRAY_SVECTOR, aliasvert_svector3f);
502 R_Model_Alias_GetMesh_Array3f(ent, mesh, MODELARRAY_TVECTOR, aliasvert_tvector3f);
503 R_Model_Alias_GetMesh_Array3f(ent, mesh, MODELARRAY_NORMAL, aliasvert_normal3f);
504 for (layernum = 0, layer = skin->data_layers;layernum < skin->num_layers;layernum++, layer++)
506 if (!(layer->flags & (ALIASLAYER_DIFFUSE | ALIASLAYER_SPECULAR))
507 || ((layer->flags & ALIASLAYER_NODRAW_IF_NOTCOLORMAPPED) && ent->colormap < 0)
508 || ((layer->flags & ALIASLAYER_NODRAW_IF_COLORMAPPED) && ent->colormap >= 0))
510 lightcolor2[0] = lightcolor[0] * ifog;
511 lightcolor2[1] = lightcolor[1] * ifog;
512 lightcolor2[2] = lightcolor[2] * ifog;
513 if (layer->flags & ALIASLAYER_SPECULAR)
515 c_alias_polys += mesh->num_triangles;
516 R_Shadow_SpecularLighting(mesh->num_vertices, mesh->num_triangles, mesh->data_element3i, aliasvert_vertex3f, aliasvert_svector3f, aliasvert_tvector3f, aliasvert_normal3f, mesh->data_texcoord2f, relativelightorigin, relativeeyeorigin, lightradius, lightcolor2, matrix_modeltofilter, matrix_modeltoattenuationxyz, matrix_modeltoattenuationz, layer->texture, layer->nmap, NULL);
518 else if (layer->flags & ALIASLAYER_DIFFUSE)
520 if (layer->flags & ALIASLAYER_COLORMAP_PANTS)
522 // 128-224 are backwards ranges
523 c = (ent->colormap & 0xF) << 4;c += (c >= 128 && c < 224) ? 4 : 12;
524 // fullbright passes were already taken care of, so skip them in realtime lighting passes
527 bcolor = (qbyte *) (&palette_complete[c]);
528 lightcolor2[0] *= bcolor[0] * (1.0f / 255.0f);
529 lightcolor2[1] *= bcolor[1] * (1.0f / 255.0f);
530 lightcolor2[2] *= bcolor[2] * (1.0f / 255.0f);
532 else if (layer->flags & ALIASLAYER_COLORMAP_SHIRT)
534 // 128-224 are backwards ranges
535 c = (ent->colormap & 0xF0);c += (c >= 128 && c < 224) ? 4 : 12;
536 // fullbright passes were already taken care of, so skip them in realtime lighting passes
539 bcolor = (qbyte *) (&palette_complete[c]);
540 lightcolor2[0] *= bcolor[0] * (1.0f / 255.0f);
541 lightcolor2[1] *= bcolor[1] * (1.0f / 255.0f);
542 lightcolor2[2] *= bcolor[2] * (1.0f / 255.0f);
544 c_alias_polys += mesh->num_triangles;
545 R_Shadow_DiffuseLighting(mesh->num_vertices, mesh->num_triangles, mesh->data_element3i, aliasvert_vertex3f, aliasvert_svector3f, aliasvert_tvector3f, aliasvert_normal3f, mesh->data_texcoord2f, relativelightorigin, lightradius, lightcolor2, matrix_modeltofilter, matrix_modeltoattenuationxyz, matrix_modeltoattenuationz, layer->texture, layer->nmap, NULL);
551 int ZymoticLerpBones(int count, const zymbonematrix *bonebase, const frameblend_t *blend, const zymbone_t *bone)
554 float lerp1, lerp2, lerp3, lerp4;
555 zymbonematrix *out, rootmatrix, m;
556 const zymbonematrix *bone1, *bone2, *bone3, *bone4;
558 rootmatrix.m[0][0] = 1;
559 rootmatrix.m[0][1] = 0;
560 rootmatrix.m[0][2] = 0;
561 rootmatrix.m[0][3] = 0;
562 rootmatrix.m[1][0] = 0;
563 rootmatrix.m[1][1] = 1;
564 rootmatrix.m[1][2] = 0;
565 rootmatrix.m[1][3] = 0;
566 rootmatrix.m[2][0] = 0;
567 rootmatrix.m[2][1] = 0;
568 rootmatrix.m[2][2] = 1;
569 rootmatrix.m[2][3] = 0;
571 bone1 = bonebase + blend[0].frame * count;
572 lerp1 = blend[0].lerp;
575 bone2 = bonebase + blend[1].frame * count;
576 lerp2 = blend[1].lerp;
579 bone3 = bonebase + blend[2].frame * count;
580 lerp3 = blend[2].lerp;
584 bone4 = bonebase + blend[3].frame * count;
585 lerp4 = blend[3].lerp;
586 for (i = 0, out = zymbonepose;i < count;i++, out++)
588 // interpolate matrices
589 m.m[0][0] = bone1->m[0][0] * lerp1 + bone2->m[0][0] * lerp2 + bone3->m[0][0] * lerp3 + bone4->m[0][0] * lerp4;
590 m.m[0][1] = bone1->m[0][1] * lerp1 + bone2->m[0][1] * lerp2 + bone3->m[0][1] * lerp3 + bone4->m[0][1] * lerp4;
591 m.m[0][2] = bone1->m[0][2] * lerp1 + bone2->m[0][2] * lerp2 + bone3->m[0][2] * lerp3 + bone4->m[0][2] * lerp4;
592 m.m[0][3] = bone1->m[0][3] * lerp1 + bone2->m[0][3] * lerp2 + bone3->m[0][3] * lerp3 + bone4->m[0][3] * lerp4;
593 m.m[1][0] = bone1->m[1][0] * lerp1 + bone2->m[1][0] * lerp2 + bone3->m[1][0] * lerp3 + bone4->m[1][0] * lerp4;
594 m.m[1][1] = bone1->m[1][1] * lerp1 + bone2->m[1][1] * lerp2 + bone3->m[1][1] * lerp3 + bone4->m[1][1] * lerp4;
595 m.m[1][2] = bone1->m[1][2] * lerp1 + bone2->m[1][2] * lerp2 + bone3->m[1][2] * lerp3 + bone4->m[1][2] * lerp4;
596 m.m[1][3] = bone1->m[1][3] * lerp1 + bone2->m[1][3] * lerp2 + bone3->m[1][3] * lerp3 + bone4->m[1][3] * lerp4;
597 m.m[2][0] = bone1->m[2][0] * lerp1 + bone2->m[2][0] * lerp2 + bone3->m[2][0] * lerp3 + bone4->m[2][0] * lerp4;
598 m.m[2][1] = bone1->m[2][1] * lerp1 + bone2->m[2][1] * lerp2 + bone3->m[2][1] * lerp3 + bone4->m[2][1] * lerp4;
599 m.m[2][2] = bone1->m[2][2] * lerp1 + bone2->m[2][2] * lerp2 + bone3->m[2][2] * lerp3 + bone4->m[2][2] * lerp4;
600 m.m[2][3] = bone1->m[2][3] * lerp1 + bone2->m[2][3] * lerp2 + bone3->m[2][3] * lerp3 + bone4->m[2][3] * lerp4;
601 if (bone->parent >= 0)
602 R_ConcatTransforms(&zymbonepose[bone->parent].m[0][0], &m.m[0][0], &out->m[0][0]);
604 R_ConcatTransforms(&rootmatrix.m[0][0], &m.m[0][0], &out->m[0][0]);
615 for (i = 0, out = zymbonepose;i < count;i++, out++)
617 // interpolate matrices
618 m.m[0][0] = bone1->m[0][0] * lerp1 + bone2->m[0][0] * lerp2 + bone3->m[0][0] * lerp3;
619 m.m[0][1] = bone1->m[0][1] * lerp1 + bone2->m[0][1] * lerp2 + bone3->m[0][1] * lerp3;
620 m.m[0][2] = bone1->m[0][2] * lerp1 + bone2->m[0][2] * lerp2 + bone3->m[0][2] * lerp3;
621 m.m[0][3] = bone1->m[0][3] * lerp1 + bone2->m[0][3] * lerp2 + bone3->m[0][3] * lerp3;
622 m.m[1][0] = bone1->m[1][0] * lerp1 + bone2->m[1][0] * lerp2 + bone3->m[1][0] * lerp3;
623 m.m[1][1] = bone1->m[1][1] * lerp1 + bone2->m[1][1] * lerp2 + bone3->m[1][1] * lerp3;
624 m.m[1][2] = bone1->m[1][2] * lerp1 + bone2->m[1][2] * lerp2 + bone3->m[1][2] * lerp3;
625 m.m[1][3] = bone1->m[1][3] * lerp1 + bone2->m[1][3] * lerp2 + bone3->m[1][3] * lerp3;
626 m.m[2][0] = bone1->m[2][0] * lerp1 + bone2->m[2][0] * lerp2 + bone3->m[2][0] * lerp3;
627 m.m[2][1] = bone1->m[2][1] * lerp1 + bone2->m[2][1] * lerp2 + bone3->m[2][1] * lerp3;
628 m.m[2][2] = bone1->m[2][2] * lerp1 + bone2->m[2][2] * lerp2 + bone3->m[2][2] * lerp3;
629 m.m[2][3] = bone1->m[2][3] * lerp1 + bone2->m[2][3] * lerp2 + bone3->m[2][3] * lerp3;
630 if (bone->parent >= 0)
631 R_ConcatTransforms(&zymbonepose[bone->parent].m[0][0], &m.m[0][0], &out->m[0][0]);
633 R_ConcatTransforms(&rootmatrix.m[0][0], &m.m[0][0], &out->m[0][0]);
644 for (i = 0, out = zymbonepose;i < count;i++, out++)
646 // interpolate matrices
647 m.m[0][0] = bone1->m[0][0] * lerp1 + bone2->m[0][0] * lerp2;
648 m.m[0][1] = bone1->m[0][1] * lerp1 + bone2->m[0][1] * lerp2;
649 m.m[0][2] = bone1->m[0][2] * lerp1 + bone2->m[0][2] * lerp2;
650 m.m[0][3] = bone1->m[0][3] * lerp1 + bone2->m[0][3] * lerp2;
651 m.m[1][0] = bone1->m[1][0] * lerp1 + bone2->m[1][0] * lerp2;
652 m.m[1][1] = bone1->m[1][1] * lerp1 + bone2->m[1][1] * lerp2;
653 m.m[1][2] = bone1->m[1][2] * lerp1 + bone2->m[1][2] * lerp2;
654 m.m[1][3] = bone1->m[1][3] * lerp1 + bone2->m[1][3] * lerp2;
655 m.m[2][0] = bone1->m[2][0] * lerp1 + bone2->m[2][0] * lerp2;
656 m.m[2][1] = bone1->m[2][1] * lerp1 + bone2->m[2][1] * lerp2;
657 m.m[2][2] = bone1->m[2][2] * lerp1 + bone2->m[2][2] * lerp2;
658 m.m[2][3] = bone1->m[2][3] * lerp1 + bone2->m[2][3] * lerp2;
659 if (bone->parent >= 0)
660 R_ConcatTransforms(&zymbonepose[bone->parent].m[0][0], &m.m[0][0], &out->m[0][0]);
662 R_ConcatTransforms(&rootmatrix.m[0][0], &m.m[0][0], &out->m[0][0]);
675 for (i = 0, out = zymbonepose;i < count;i++, out++)
677 // interpolate matrices
678 m.m[0][0] = bone1->m[0][0] * lerp1;
679 m.m[0][1] = bone1->m[0][1] * lerp1;
680 m.m[0][2] = bone1->m[0][2] * lerp1;
681 m.m[0][3] = bone1->m[0][3] * lerp1;
682 m.m[1][0] = bone1->m[1][0] * lerp1;
683 m.m[1][1] = bone1->m[1][1] * lerp1;
684 m.m[1][2] = bone1->m[1][2] * lerp1;
685 m.m[1][3] = bone1->m[1][3] * lerp1;
686 m.m[2][0] = bone1->m[2][0] * lerp1;
687 m.m[2][1] = bone1->m[2][1] * lerp1;
688 m.m[2][2] = bone1->m[2][2] * lerp1;
689 m.m[2][3] = bone1->m[2][3] * lerp1;
690 if (bone->parent >= 0)
691 R_ConcatTransforms(&zymbonepose[bone->parent].m[0][0], &m.m[0][0], &out->m[0][0]);
693 R_ConcatTransforms(&rootmatrix.m[0][0], &m.m[0][0], &out->m[0][0]);
701 for (i = 0, out = zymbonepose;i < count;i++, out++)
703 if (bone->parent >= 0)
704 R_ConcatTransforms(&zymbonepose[bone->parent].m[0][0], &bone1->m[0][0], &out->m[0][0]);
706 R_ConcatTransforms(&rootmatrix.m[0][0], &bone1->m[0][0], &out->m[0][0]);
715 void ZymoticTransformVerts(int vertcount, float *vertex, int *bonecounts, zymvertex_t *vert)
719 zymbonematrix *matrix;
723 // FIXME: validate bonecounts at load time (must be >= 1)
724 // FIXME: need 4th component in origin, for how much of the translate to blend in
727 matrix = &zymbonepose[vert->bonenum];
728 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];
729 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];
730 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];
738 matrix = &zymbonepose[vert->bonenum];
739 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];
740 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];
741 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];
749 void ZymoticCalcNormal3f(int vertcount, float *vertex3f, float *normal3f, int shadercount, int *renderlist)
752 float *out, v1[3], v2[3], normal[3], s;
755 memset(normal3f, 0, sizeof(float) * vertcount * 3);
756 memset(aliasvertusage, 0, sizeof(int) * vertcount);
757 // parse render list and accumulate surface normals
766 v1[0] = vertex3f[a+0] - vertex3f[b+0];
767 v1[1] = vertex3f[a+1] - vertex3f[b+1];
768 v1[2] = vertex3f[a+2] - vertex3f[b+2];
769 v2[0] = vertex3f[c+0] - vertex3f[b+0];
770 v2[1] = vertex3f[c+1] - vertex3f[b+1];
771 v2[2] = vertex3f[c+2] - vertex3f[b+2];
772 CrossProduct(v1, v2, normal);
773 VectorNormalizeFast(normal);
774 // add surface normal to vertices
775 a = renderlist[0] * 3;
776 normal3f[a+0] += normal[0];
777 normal3f[a+1] += normal[1];
778 normal3f[a+2] += normal[2];
779 aliasvertusage[renderlist[0]]++;
780 a = renderlist[1] * 3;
781 normal3f[a+0] += normal[0];
782 normal3f[a+1] += normal[1];
783 normal3f[a+2] += normal[2];
784 aliasvertusage[renderlist[1]]++;
785 a = renderlist[2] * 3;
786 normal3f[a+0] += normal[0];
787 normal3f[a+1] += normal[1];
788 normal3f[a+2] += normal[2];
789 aliasvertusage[renderlist[2]]++;
793 // FIXME: precalc this
794 // average surface normals
811 void R_DrawZymoticModelMeshCallback (const void *calldata1, int calldata2)
813 float fog, ifog, colorscale, ambientcolor4f[4];
815 int i, *renderlist, *elements;
818 const entity_render_t *ent = calldata1;
819 int shadernum = calldata2;
820 int numverts, numtriangles;
822 R_Mesh_Matrix(&ent->matrix);
824 // find the vertex index list and texture
825 renderlist = ent->model->zymdata_renderlist;
826 for (i = 0;i < shadernum;i++)
827 renderlist += renderlist[0] * 3 + 1;
828 texture = ent->model->zymdata_textures[shadernum];
830 numverts = ent->model->zymnum_verts;
831 numtriangles = *renderlist++;
832 elements = renderlist;
834 expandaliasvert(numverts);
839 VectorSubtract(ent->origin, r_origin, diff);
840 fog = DotProduct(diff,diff);
843 fog = exp(fogdensity/fog);
848 // fog method: darken, additive fog
849 // 1. render model as normal, scaled by inverse of fog alpha (darkens it)
850 // 2. render fog as additive
854 memset(&mstate, 0, sizeof(mstate));
855 if (ent->effects & EF_ADDITIVE)
857 mstate.blendfunc1 = GL_SRC_ALPHA;
858 mstate.blendfunc2 = GL_ONE;
860 else if (ent->alpha != 1.0 || R_TextureHasAlpha(texture))
862 mstate.blendfunc1 = GL_SRC_ALPHA;
863 mstate.blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
867 mstate.blendfunc1 = GL_ONE;
868 mstate.blendfunc2 = GL_ZERO;
870 colorscale = r_colorscale;
871 if (gl_combine.integer)
873 mstate.texrgbscale[0] = 4;
876 mstate.tex[0] = R_GetTexture(texture);
877 R_Mesh_State(&mstate);
878 ZymoticLerpBones(ent->model->zymnum_bones, (zymbonematrix *) ent->model->zymdata_poses, ent->frameblend, ent->model->zymdata_bones);
880 R_Mesh_GetSpace(numverts);
881 ZymoticTransformVerts(numverts, varray_vertex3f, ent->model->zymdata_vertbonecounts, ent->model->zymdata_verts);
882 R_Mesh_CopyTexCoord2f(0, ent->model->zymdata_texcoords, ent->model->zymnum_verts);
883 ZymoticCalcNormal3f(numverts, varray_vertex3f, aliasvert_normal3f, ent->model->zymnum_shaders, ent->model->zymdata_renderlist);
884 if (R_LightModel(ambientcolor4f, ent, ifog * colorscale, ifog * colorscale, ifog * colorscale, ent->alpha, false))
887 R_LightModel_CalcVertexColors(ambientcolor4f, numverts, varray_vertex3f, aliasvert_normal3f, varray_color4f);
890 GL_Color(ambientcolor4f[0], ambientcolor4f[1], ambientcolor4f[2], ambientcolor4f[3]);
891 R_Mesh_Draw(numverts, numtriangles, elements);
892 c_alias_polys += numtriangles;
896 memset(&mstate, 0, sizeof(mstate));
897 mstate.blendfunc1 = GL_SRC_ALPHA;
898 mstate.blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
899 // FIXME: need alpha mask for fogging...
900 //mstate.tex[0] = R_GetTexture(texture);
901 R_Mesh_State(&mstate);
902 GL_Color(fogcolor[0] * r_colorscale, fogcolor[1] * r_colorscale, fogcolor[2] * r_colorscale, ent->alpha * fog);
903 R_Mesh_GetSpace(numverts);
904 ZymoticTransformVerts(numverts, varray_vertex3f, ent->model->zymdata_vertbonecounts, ent->model->zymdata_verts);
905 R_Mesh_Draw(numverts, numtriangles, elements);
906 c_alias_polys += numtriangles;
910 void R_Model_Zymotic_Draw(entity_render_t *ent)
914 if (ent->alpha < (1.0f / 64.0f))
915 return; // basically completely transparent
919 for (i = 0;i < ent->model->zymnum_shaders;i++)
921 if (ent->effects & EF_ADDITIVE || ent->alpha != 1.0 || R_TextureHasAlpha(ent->model->zymdata_textures[i]))
922 R_MeshQueue_AddTransparent(ent->origin, R_DrawZymoticModelMeshCallback, ent, i);
924 R_DrawZymoticModelMeshCallback(ent, i);
928 void R_Model_Zymotic_DrawFakeShadow(entity_render_t *ent)
933 void R_Model_Zymotic_DrawLight(entity_render_t *ent, vec3_t relativelightorigin, float lightradius2, float lightdistbias, float lightsubtract, float *lightcolor)
938 void R_Model_Zymotic_DrawOntoLight(entity_render_t *ent)