]> icculus.org git repositories - divverent/darkplaces.git/blob - gl_models.c
some cleanups to hostcache (got rid of driver/address stuff and expanded the strings...
[divverent/darkplaces.git] / gl_models.c
1
2 #include "quakedef.h"
3 #include "cl_collision.h"
4 #include "r_shadow.h"
5
6 typedef struct
7 {
8         float m[3][4];
9 } zymbonematrix;
10
11 // LordHavoc: vertex arrays
12 int aliasvertmax = 0;
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;
19
20 float *aliasvertcolor2_4f = NULL;
21 int *aliasvertusage;
22 zymbonematrix *zymbonepose;
23
24 mempool_t *gl_models_mempool;
25
26 #define expandaliasvert(newmax) if ((newmax) > aliasvertmax) gl_models_allocarrays(newmax)
27
28 void gl_models_allocarrays(int newmax)
29 {
30         qbyte *data;
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]);
42 }
43
44 void gl_models_freearrays(void)
45 {
46         aliasvertmax = 0;
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;
56 }
57
58 void gl_models_start(void)
59 {
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);
64 }
65
66 void gl_models_shutdown(void)
67 {
68         gl_models_freearrays();
69         Mem_FreePool(&gl_models_mempool);
70 }
71
72 void gl_models_newmap(void)
73 {
74 }
75
76 void GL_Models_Init(void)
77 {
78         R_RegisterModule("GL_Models", gl_models_start, gl_models_shutdown, gl_models_newmap);
79 }
80
81 #define MODELARRAY_VERTEX 0
82 #define MODELARRAY_SVECTOR 1
83 #define MODELARRAY_TVECTOR 2
84 #define MODELARRAY_NORMAL 3
85
86 void R_Model_Alias_GetMesh_Array3f(const entity_render_t *ent, aliasmesh_t *mesh, int whicharray, float *out3f)
87 {
88         int i, vertcount;
89         float lerp1, lerp2, lerp3, lerp4;
90         const float *vertsbase, *verts1, *verts2, *verts3, *verts4;
91
92         switch(whicharray)
93         {
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;
98         default:
99                 Host_Error("R_Model_Alias_GetBlendedArray: unknown whicharray %i\n", whicharray);
100                 return;
101         }
102
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)
107         {
108                 verts2 = vertsbase + ent->frameblend[1].frame * vertcount * 3;
109                 lerp2 = ent->frameblend[1].lerp;
110                 if (ent->frameblend[2].lerp)
111                 {
112                         verts3 = vertsbase + ent->frameblend[2].frame * vertcount * 3;
113                         lerp3 = ent->frameblend[2].lerp;
114                         if (ent->frameblend[3].lerp)
115                         {
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);
120                         }
121                         else
122                                 for (i = 0;i < vertcount * 3;i++)
123                                         VectorMAMAM(lerp1, verts1 + i, lerp2, verts2 + i, lerp3, verts3 + i, out3f + i);
124                 }
125                 else
126                         for (i = 0;i < vertcount * 3;i++)
127                                 VectorMAM(lerp1, verts1 + i, lerp2, verts2 + i, out3f + i);
128         }
129         else
130                 memcpy(out3f, verts1, vertcount * sizeof(float[3]));
131 }
132
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)
136 {
137         model_t *model = ent->model;
138         if (model->numskins)
139         {
140                 int s = ent->skinnum;
141                 if ((unsigned int)s >= (unsigned int)model->numskins)
142                         s = 0;
143                 if (model->skinscenes[s].framecount > 1)
144                         s = model->skinscenes[s].firstframe + (int) (cl.time * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
145                 else
146                         s = model->skinscenes[s].firstframe;
147                 if (s >= mesh->num_skins)
148                         s = 0;
149                 return mesh->data_skins + s;
150         }
151         else
152         {
153                 r_aliasnoskinlayers[0].texture = r_notexture;
154                 return &r_aliasnoskin;
155         }
156 }
157
158 void R_DrawAliasModelCallback (const void *calldata1, int calldata2)
159 {
160         int c, fullbright, layernum, firstpass;
161         float tint[3], fog, ifog, colorscale, ambientcolor4f[4];
162         vec3_t diff;
163         qbyte *bcolor;
164         rmeshstate_t m;
165         const entity_render_t *ent = calldata1;
166         aliasmesh_t *mesh = ent->model->aliasdata_meshes + calldata2;
167         aliaslayer_t *layer;
168         aliasskin_t *skin;
169         rcachearrayrequest_t request;
170
171         R_Mesh_Matrix(&ent->matrix);
172
173         fog = 0;
174         if (fogenabled)
175         {
176                 VectorSubtract(ent->origin, r_origin, diff);
177                 fog = DotProduct(diff,diff);
178                 if (fog < 0.01f)
179                         fog = 0.01f;
180                 fog = exp(fogdensity/fog);
181                 if (fog > 1)
182                         fog = 1;
183                 if (fog < 0.01f)
184                         fog = 0;
185                 // fog method: darken, additive fog
186                 // 1. render model as normal, scaled by inverse of fog alpha (darkens it)
187                 // 2. render fog as additive
188         }
189         ifog = 1 - fog;
190
191         firstpass = true;
192         skin = R_FetchAliasSkin(ent, mesh);
193         for (layernum = 0, layer = skin->data_layers;layernum < skin->num_layers;layernum++, layer++)
194         {
195                 if (!(layer->flags & ALIASLAYER_FORCEDRAW_IF_FIRSTPASS) || !firstpass)
196                 {
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))))
202                                 continue;
203                 }
204                 memset(&m, 0, sizeof(m));
205                 if (!firstpass || (ent->effects & EF_ADDITIVE))
206                 {
207                         m.blendfunc1 = GL_SRC_ALPHA;
208                         m.blendfunc2 = GL_ONE;
209                 }
210                 else if ((skin->flags & ALIASSKIN_TRANSPARENT) || ent->alpha != 1.0)
211                 {
212                         m.blendfunc1 = GL_SRC_ALPHA;
213                         m.blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
214                 }
215                 else
216                 {
217                         m.blendfunc1 = GL_ONE;
218                         m.blendfunc2 = GL_ZERO;
219                 }
220                 firstpass = false;
221                 expandaliasvert(mesh->num_vertices);
222                 colorscale = r_colorscale;
223                 m.texrgbscale[0] = 1;
224                 m.tex[0] = R_GetTexture(layer->texture);
225                 if (gl_combine.integer && layer->flags & (ALIASLAYER_DIFFUSE | ALIASLAYER_SPECULAR))
226                 {
227                         colorscale *= 0.25f;
228                         m.texrgbscale[0] = 4;
229                 }
230                 c_alias_polys += mesh->num_triangles;
231                 if (gl_mesh_copyarrays.integer)
232                 {
233                         R_Mesh_State(&m);
234                         R_Mesh_GetSpace(mesh->num_vertices);
235                         if (layer->texture != NULL)
236                                 R_Mesh_CopyTexCoord2f(0, mesh->data_texcoord2f, mesh->num_vertices);
237                         R_Model_Alias_GetMesh_Array3f(ent, mesh, MODELARRAY_VERTEX, varray_vertex3f);
238                 }
239                 else
240                 {
241                         m.pointervertexcount = mesh->num_vertices;
242                         memset(&request, 0, sizeof(request));
243                         request.data_size = mesh->num_vertices * sizeof(float[3]);
244                         request.id_pointer2 = mesh->data_aliasvertex3f;
245                         request.id_number1 = layernum;
246                         request.id_number2 = 0;
247                         request.id_number3 = CRC_Block((void *)ent->frameblend, sizeof(ent->frameblend));
248                         if (R_Mesh_CacheArray(&request))
249                                 R_Model_Alias_GetMesh_Array3f(ent, mesh, MODELARRAY_VERTEX, request.data);
250                         m.pointer_vertex = request.data;
251                         m.pointer_texcoord[0] = layer->texture != NULL ? mesh->data_texcoord2f : NULL;
252                 }
253                 if (layer->flags & ALIASLAYER_FOG)
254                 {
255                         colorscale *= fog;
256                         GL_Color(fogcolor[0] * colorscale, fogcolor[1] * colorscale, fogcolor[2] * colorscale, ent->alpha);
257                 }
258                 else
259                 {
260                         if (layer->flags & (ALIASLAYER_COLORMAP_PANTS | ALIASLAYER_COLORMAP_SHIRT))
261                         {
262                                 // 128-224 are backwards ranges
263                                 if (layer->flags & ALIASLAYER_COLORMAP_PANTS)
264                                         c = (ent->colormap & 0xF) << 4;
265                                 else //if (layer->flags & ALIASLAYER_COLORMAP_SHIRT)
266                                         c = (ent->colormap & 0xF0);
267                                 c += (c >= 128 && c < 224) ? 4 : 12;
268                                 bcolor = (qbyte *) (&palette_complete[c]);
269                                 fullbright = c >= 224;
270                                 VectorScale(bcolor, (1.0f / 255.0f), tint);
271                         }
272                         else
273                         {
274                                 tint[0] = tint[1] = tint[2] = 1;
275                                 fullbright = false;
276                         }
277                         colorscale *= ifog;
278                         if (fullbright || !(layer->flags & ALIASLAYER_DIFFUSE) || r_fullbright.integer || (ent->effects & EF_FULLBRIGHT))
279                                 GL_Color(tint[0] * colorscale, tint[1] * colorscale, tint[2] * colorscale, ent->alpha);
280                         else if (r_shadow_realtime_world.integer)
281                         {
282                                 colorscale *= r_ambient.value * (2.0f / 128.0f);
283                                 GL_Color(tint[0] * colorscale, tint[1] * colorscale, tint[2] * colorscale, ent->alpha);
284                         }
285                         else
286                         {
287                                 if (R_LightModel(ambientcolor4f, ent, tint[0] * colorscale, tint[1] * colorscale, tint[2] * colorscale, ent->alpha, false))
288                                 {
289                                         GL_UseColorArray();
290                                         if (gl_mesh_copyarrays.integer)
291                                         {
292                                                 R_Model_Alias_GetMesh_Array3f(ent, mesh, MODELARRAY_NORMAL, aliasvert_normal3f);
293                                                 R_LightModel_CalcVertexColors(ambientcolor4f, mesh->num_vertices, varray_vertex3f, aliasvert_normal3f, varray_color4f);
294                                         }
295                                         else
296                                         {
297                                                 // request color4f cache
298                                                 request.data_size = mesh->num_vertices * sizeof(float[4]);
299                                                 request.id_pointer1 = ent;
300                                                 request.id_number2 = 2;
301                                                 request.id_number3 = CRC_Block((void *)ent->frameblend, sizeof(ent->frameblend)) + CRC_Block((void *)&ent->entlightstime, sizeof(ent->entlightstime));
302                                                 if (R_Mesh_CacheArray(&request))
303                                                 {
304                                                         // save off the color pointer before we blow away the request
305                                                         m.pointer_color = request.data;
306                                                         // request normal3f cache
307                                                         request.data_size = mesh->num_vertices * sizeof(float[3]);
308                                                         request.id_pointer1 = NULL;
309                                                         request.id_number2 = 3;
310                                                         request.id_number3 = CRC_Block((void *)ent->frameblend, sizeof(ent->frameblend));
311                                                         if (R_Mesh_CacheArray(&request))
312                                                                 R_Model_Alias_GetMesh_Array3f(ent, mesh, MODELARRAY_NORMAL, request.data);
313                                                         R_LightModel_CalcVertexColors(ambientcolor4f, mesh->num_vertices, m.pointer_vertex, request.data, m.pointer_color);
314                                                 }
315                                                 else
316                                                         m.pointer_color = request.data;
317                                         }
318                                 }
319                                 else
320                                         GL_Color(ambientcolor4f[0], ambientcolor4f[1], ambientcolor4f[2], ambientcolor4f[3]);
321                         }
322                 }
323                 if (!gl_mesh_copyarrays.integer)
324                         R_Mesh_State(&m);
325                 R_Mesh_Draw(mesh->num_vertices, mesh->num_triangles, mesh->data_element3i);
326         }
327 }
328
329 void R_Model_Alias_Draw(entity_render_t *ent)
330 {
331         int meshnum;
332         aliasmesh_t *mesh;
333         if (ent->alpha < (1.0f / 64.0f))
334                 return; // basically completely transparent
335
336         c_models++;
337
338         for (meshnum = 0, mesh = ent->model->aliasdata_meshes;meshnum < ent->model->aliasnum_meshes;meshnum++, mesh++)
339         {
340                 if (ent->effects & EF_ADDITIVE || ent->alpha != 1.0 || R_FetchAliasSkin(ent, mesh)->flags & ALIASSKIN_TRANSPARENT)
341                         R_MeshQueue_AddTransparent(ent->origin, R_DrawAliasModelCallback, ent, meshnum);
342                 else
343                         R_DrawAliasModelCallback(ent, meshnum);
344         }
345 }
346
347 void R_Model_Alias_DrawFakeShadow (entity_render_t *ent)
348 {
349         int i, meshnum;
350         aliasmesh_t *mesh;
351         aliasskin_t *skin;
352         rmeshstate_t m;
353         float *v, plane[4], dist, projection[3], floororigin[3], surfnormal[3], lightdirection[3], v2[3];
354         rcachearrayrequest_t request;
355
356         if ((ent->effects & EF_ADDITIVE) || ent->alpha < 1)
357                 return;
358
359         lightdirection[0] = 0.5;
360         lightdirection[1] = 0.2;
361         lightdirection[2] = -1;
362         VectorNormalizeFast(lightdirection);
363
364         VectorMA(ent->origin, 65536.0f, lightdirection, v2);
365         if (CL_TraceLine(ent->origin, v2, floororigin, surfnormal, 0, false, NULL) == 1)
366                 return;
367
368         R_Mesh_Matrix(&ent->matrix);
369
370         memset(&m, 0, sizeof(m));
371         m.blendfunc1 = GL_SRC_ALPHA;
372         m.blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
373         if (gl_mesh_copyarrays.integer)
374                 R_Mesh_State(&m);
375         GL_Color(0, 0, 0, 0.5);
376
377         // put a light direction in the entity's coordinate space
378         Matrix4x4_Transform3x3(&ent->inversematrix, lightdirection, projection);
379         VectorNormalizeFast(projection);
380
381         // put the plane's normal in the entity's coordinate space
382         Matrix4x4_Transform3x3(&ent->inversematrix, surfnormal, plane);
383         VectorNormalizeFast(plane);
384
385         // put the plane's distance in the entity's coordinate space
386         VectorSubtract(floororigin, ent->origin, floororigin);
387         plane[3] = DotProduct(floororigin, surfnormal) + 2;
388
389         dist = -1.0f / DotProduct(projection, plane);
390         VectorScale(projection, dist, projection);
391         memset(&request, 0, sizeof(request));
392         for (meshnum = 0, mesh = ent->model->aliasdata_meshes;meshnum < ent->model->aliasnum_meshes;meshnum++)
393         {
394                 skin = R_FetchAliasSkin(ent, mesh);
395                 if (skin->flags & ALIASSKIN_TRANSPARENT)
396                         continue;
397                 if (gl_mesh_copyarrays.integer)
398                 {
399                         R_Mesh_GetSpace(mesh->num_vertices);
400                         R_Model_Alias_GetMesh_Array3f(ent, mesh, MODELARRAY_VERTEX, varray_vertex3f);
401                         for (i = 0, v = varray_vertex3f;i < mesh->num_vertices;i++, v += 3)
402                         {
403                                 dist = DotProduct(v, plane) - plane[3];
404                                 if (dist > 0)
405                                         VectorMA(v, dist, projection, v);
406                         }
407                 }
408                 else
409                 {
410                         request.data_size = mesh->num_vertices * sizeof(float[3]);
411                         request.id_pointer1 = mesh;
412                         request.id_number1 = CRC_Block((void *)&ent->matrix, sizeof(ent->matrix));
413                         request.id_number2 = CRC_Block((void *)&plane, sizeof(plane));
414                         request.id_number3 = CRC_Block((void *)&ent->frameblend, sizeof(ent->frameblend));
415                         m.pointervertexcount = mesh->num_vertices;
416                         if (R_Mesh_CacheArray(&request))
417                         {
418                                 R_Model_Alias_GetMesh_Array3f(ent, mesh, MODELARRAY_VERTEX, request.data);
419                                 for (i = 0, v = request.data;i < mesh->num_vertices;i++, v += 3)
420                                 {
421                                         dist = DotProduct(v, plane) - plane[3];
422                                         if (dist > 0)
423                                                 VectorMA(v, dist, projection, v);
424                                 }
425                         }
426                         m.pointer_vertex = request.data;
427                         R_Mesh_State(&m);
428                 }
429                 c_alias_polys += mesh->num_triangles;
430                 R_Mesh_Draw(mesh->num_vertices, mesh->num_triangles, mesh->data_element3i);
431         }
432 }
433
434 void R_Model_Alias_DrawShadowVolume(entity_render_t *ent, vec3_t relativelightorigin, float lightradius)
435 {
436         int meshnum;
437         aliasmesh_t *mesh;
438         aliasskin_t *skin;
439         float projectdistance;
440         if (ent->effects & EF_ADDITIVE || ent->alpha < 1)
441                 return;
442         projectdistance = lightradius + ent->model->radius - sqrt(DotProduct(relativelightorigin, relativelightorigin));
443         if (projectdistance > 0.1)
444         {
445                 R_Mesh_Matrix(&ent->matrix);
446                 for (meshnum = 0, mesh = ent->model->aliasdata_meshes;meshnum < ent->model->aliasnum_meshes;meshnum++, mesh++)
447                 {
448                         skin = R_FetchAliasSkin(ent, mesh);
449                         if (skin->flags & ALIASSKIN_TRANSPARENT)
450                                 continue;
451                         R_Mesh_GetSpace(mesh->num_vertices * 2);
452                         R_Model_Alias_GetMesh_Array3f(ent, mesh, MODELARRAY_VERTEX, varray_vertex3f);
453                         R_Shadow_Volume(mesh->num_vertices, mesh->num_triangles, mesh->data_element3i, mesh->data_neighbor3i, relativelightorigin, lightradius, projectdistance);
454                 }
455         }
456 }
457
458 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)
459 {
460         int c, meshnum, layernum;
461         float fog, ifog, lightcolor2[3], *vertices;
462         vec3_t diff;
463         qbyte *bcolor;
464         aliasmesh_t *mesh;
465         aliaslayer_t *layer;
466         aliasskin_t *skin;
467
468         if (ent->effects & (EF_ADDITIVE | EF_FULLBRIGHT) || ent->alpha < 1)
469                 return;
470
471         R_Mesh_Matrix(&ent->matrix);
472
473         fog = 0;
474         if (fogenabled)
475         {
476                 VectorSubtract(ent->origin, r_origin, diff);
477                 fog = DotProduct(diff,diff);
478                 if (fog < 0.01f)
479                         fog = 0.01f;
480                 fog = exp(fogdensity/fog);
481                 if (fog > 1)
482                         fog = 1;
483                 if (fog < 0.01f)
484                         fog = 0;
485                 // fog method: darken, additive fog
486                 // 1. render model as normal, scaled by inverse of fog alpha (darkens it)
487                 // 2. render fog as additive
488         }
489         ifog = 1 - fog;
490
491         for (meshnum = 0, mesh = ent->model->aliasdata_meshes;meshnum < ent->model->aliasnum_meshes;meshnum++, mesh++)
492         {
493                 skin = R_FetchAliasSkin(ent, mesh);
494                 if (skin->flags & ALIASSKIN_TRANSPARENT)
495                         continue;
496                 expandaliasvert(mesh->num_vertices);
497                 vertices = R_Shadow_VertexBuffer(mesh->num_vertices);
498                 R_Model_Alias_GetMesh_Array3f(ent, mesh, MODELARRAY_VERTEX, vertices);
499                 R_Model_Alias_GetMesh_Array3f(ent, mesh, MODELARRAY_SVECTOR, aliasvert_svector3f);
500                 R_Model_Alias_GetMesh_Array3f(ent, mesh, MODELARRAY_TVECTOR, aliasvert_tvector3f);
501                 R_Model_Alias_GetMesh_Array3f(ent, mesh, MODELARRAY_NORMAL, aliasvert_normal3f);
502                 for (layernum = 0, layer = skin->data_layers;layernum < skin->num_layers;layernum++, layer++)
503                 {
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))
507                                 continue;
508                         lightcolor2[0] = lightcolor[0] * ifog;
509                         lightcolor2[1] = lightcolor[1] * ifog;
510                         lightcolor2[2] = lightcolor[2] * ifog;
511                         if (layer->flags & ALIASLAYER_SPECULAR)
512                         {
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);
515                         }
516                         else if (layer->flags & ALIASLAYER_DIFFUSE)
517                         {
518                                 if (layer->flags & ALIASLAYER_COLORMAP_PANTS)
519                                 {
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
523                                         if (c >= 224)
524                                                 continue;
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);
529                                 }
530                                 else if (layer->flags & ALIASLAYER_COLORMAP_SHIRT)
531                                 {
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
535                                         if (c >= 224)
536                                                 continue;
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);
541                                 }
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);
544                         }
545                 }
546         }
547 }
548
549 int ZymoticLerpBones(int count, const zymbonematrix *bonebase, const frameblend_t *blend, const zymbone_t *bone)
550 {
551         int i;
552         float lerp1, lerp2, lerp3, lerp4;
553         zymbonematrix *out, rootmatrix, m;
554         const zymbonematrix *bone1, *bone2, *bone3, *bone4;
555
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;
568
569         bone1 = bonebase + blend[0].frame * count;
570         lerp1 = blend[0].lerp;
571         if (blend[1].lerp)
572         {
573                 bone2 = bonebase + blend[1].frame * count;
574                 lerp2 = blend[1].lerp;
575                 if (blend[2].lerp)
576                 {
577                         bone3 = bonebase + blend[2].frame * count;
578                         lerp3 = blend[2].lerp;
579                         if (blend[3].lerp)
580                         {
581                                 // 4 poses
582                                 bone4 = bonebase + blend[3].frame * count;
583                                 lerp4 = blend[3].lerp;
584                                 for (i = 0, out = zymbonepose;i < count;i++, out++)
585                                 {
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]);
601                                         else
602                                                 R_ConcatTransforms(&rootmatrix.m[0][0], &m.m[0][0], &out->m[0][0]);
603                                         bone1++;
604                                         bone2++;
605                                         bone3++;
606                                         bone4++;
607                                         bone++;
608                                 }
609                         }
610                         else
611                         {
612                                 // 3 poses
613                                 for (i = 0, out = zymbonepose;i < count;i++, out++)
614                                 {
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]);
630                                         else
631                                                 R_ConcatTransforms(&rootmatrix.m[0][0], &m.m[0][0], &out->m[0][0]);
632                                         bone1++;
633                                         bone2++;
634                                         bone3++;
635                                         bone++;
636                                 }
637                         }
638                 }
639                 else
640                 {
641                         // 2 poses
642                         for (i = 0, out = zymbonepose;i < count;i++, out++)
643                         {
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]);
659                                 else
660                                         R_ConcatTransforms(&rootmatrix.m[0][0], &m.m[0][0], &out->m[0][0]);
661                                 bone1++;
662                                 bone2++;
663                                 bone++;
664                         }
665                 }
666         }
667         else
668         {
669                 // 1 pose
670                 if (lerp1 != 1)
671                 {
672                         // lerp != 1.0
673                         for (i = 0, out = zymbonepose;i < count;i++, out++)
674                         {
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]);
690                                 else
691                                         R_ConcatTransforms(&rootmatrix.m[0][0], &m.m[0][0], &out->m[0][0]);
692                                 bone1++;
693                                 bone++;
694                         }
695                 }
696                 else
697                 {
698                         // lerp == 1.0
699                         for (i = 0, out = zymbonepose;i < count;i++, out++)
700                         {
701                                 if (bone->parent >= 0)
702                                         R_ConcatTransforms(&zymbonepose[bone->parent].m[0][0], &bone1->m[0][0], &out->m[0][0]);
703                                 else
704                                         R_ConcatTransforms(&rootmatrix.m[0][0], &bone1->m[0][0], &out->m[0][0]);
705                                 bone1++;
706                                 bone++;
707                         }
708                 }
709         }
710         return true;
711 }
712
713 void ZymoticTransformVerts(int vertcount, float *vertex, int *bonecounts, zymvertex_t *vert)
714 {
715         int c;
716         float *out = vertex;
717         zymbonematrix *matrix;
718         while(vertcount--)
719         {
720                 c = *bonecounts++;
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
723                 if (c == 1)
724                 {
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];
729                         vert++;
730                 }
731                 else
732                 {
733                         VectorClear(out);
734                         while(c--)
735                         {
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];
740                                 vert++;
741                         }
742                 }
743                 out += 3;
744         }
745 }
746
747 void ZymoticCalcNormal3f(int vertcount, float *vertex3f, float *normal3f, int shadercount, int *renderlist)
748 {
749         int a, b, c, d;
750         float *out, v1[3], v2[3], normal[3], s;
751         int *u;
752         // clear normals
753         memset(normal3f, 0, sizeof(float) * vertcount * 3);
754         memset(aliasvertusage, 0, sizeof(int) * vertcount);
755         // parse render list and accumulate surface normals
756         while(shadercount--)
757         {
758                 d = *renderlist++;
759                 while (d--)
760                 {
761                         a = renderlist[0]*4;
762                         b = renderlist[1]*4;
763                         c = renderlist[2]*4;
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]]++;
788                         renderlist += 3;
789                 }
790         }
791         // FIXME: precalc this
792         // average surface normals
793         out = normal3f;
794         u = aliasvertusage;
795         while(vertcount--)
796         {
797                 if (*u > 1)
798                 {
799                         s = ixtable[*u];
800                         out[0] *= s;
801                         out[1] *= s;
802                         out[2] *= s;
803                 }
804                 u++;
805                 out += 3;
806         }
807 }
808
809 void R_DrawZymoticModelMeshCallback (const void *calldata1, int calldata2)
810 {
811         float fog, ifog, colorscale, ambientcolor4f[4];
812         vec3_t diff;
813         int i, *renderlist, *elements;
814         rtexture_t *texture;
815         rmeshstate_t mstate;
816         const entity_render_t *ent = calldata1;
817         int shadernum = calldata2;
818         int numverts, numtriangles;
819
820         R_Mesh_Matrix(&ent->matrix);
821
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];
827
828         numverts = ent->model->zymnum_verts;
829         numtriangles = *renderlist++;
830         elements = renderlist;
831
832         expandaliasvert(numverts);
833
834         fog = 0;
835         if (fogenabled)
836         {
837                 VectorSubtract(ent->origin, r_origin, diff);
838                 fog = DotProduct(diff,diff);
839                 if (fog < 0.01f)
840                         fog = 0.01f;
841                 fog = exp(fogdensity/fog);
842                 if (fog > 1)
843                         fog = 1;
844                 if (fog < 0.01f)
845                         fog = 0;
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
849         }
850         ifog = 1 - fog;
851
852         memset(&mstate, 0, sizeof(mstate));
853         if (ent->effects & EF_ADDITIVE)
854         {
855                 mstate.blendfunc1 = GL_SRC_ALPHA;
856                 mstate.blendfunc2 = GL_ONE;
857         }
858         else if (ent->alpha != 1.0 || R_TextureHasAlpha(texture))
859         {
860                 mstate.blendfunc1 = GL_SRC_ALPHA;
861                 mstate.blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
862         }
863         else
864         {
865                 mstate.blendfunc1 = GL_ONE;
866                 mstate.blendfunc2 = GL_ZERO;
867         }
868         colorscale = r_colorscale;
869         if (gl_combine.integer)
870         {
871                 mstate.texrgbscale[0] = 4;
872                 colorscale *= 0.25f;
873         }
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);
877
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         if (R_LightModel(ambientcolor4f, ent, ifog * colorscale, ifog * colorscale, ifog * colorscale, ent->alpha, false))
883         {
884                 GL_UseColorArray();
885                 R_LightModel_CalcVertexColors(ambientcolor4f, numverts, varray_vertex3f, aliasvert_normal3f, varray_color4f);
886         }
887         else
888                 GL_Color(ambientcolor4f[0], ambientcolor4f[1], ambientcolor4f[2], ambientcolor4f[3]);
889         R_Mesh_Draw(numverts, numtriangles, elements);
890         c_alias_polys += numtriangles;
891
892         if (fog)
893         {
894                 memset(&mstate, 0, sizeof(mstate));
895                 mstate.blendfunc1 = GL_SRC_ALPHA;
896                 mstate.blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
897                 // FIXME: need alpha mask for fogging...
898                 //mstate.tex[0] = R_GetTexture(texture);
899                 R_Mesh_State(&mstate);
900                 GL_Color(fogcolor[0] * r_colorscale, fogcolor[1] * r_colorscale, fogcolor[2] * r_colorscale, ent->alpha * fog);
901                 R_Mesh_GetSpace(numverts);
902                 ZymoticTransformVerts(numverts, varray_vertex3f, ent->model->zymdata_vertbonecounts, ent->model->zymdata_verts);
903                 R_Mesh_Draw(numverts, numtriangles, elements);
904                 c_alias_polys += numtriangles;
905         }
906 }
907
908 void R_Model_Zymotic_Draw(entity_render_t *ent)
909 {
910         int i;
911
912         if (ent->alpha < (1.0f / 64.0f))
913                 return; // basically completely transparent
914
915         c_models++;
916
917         for (i = 0;i < ent->model->zymnum_shaders;i++)
918         {
919                 if (ent->effects & EF_ADDITIVE || ent->alpha != 1.0 || R_TextureHasAlpha(ent->model->zymdata_textures[i]))
920                         R_MeshQueue_AddTransparent(ent->origin, R_DrawZymoticModelMeshCallback, ent, i);
921                 else
922                         R_DrawZymoticModelMeshCallback(ent, i);
923         }
924 }
925
926 void R_Model_Zymotic_DrawFakeShadow(entity_render_t *ent)
927 {
928         // FIXME
929 }
930
931 void R_Model_Zymotic_DrawLight(entity_render_t *ent, vec3_t relativelightorigin, float lightradius2, float lightdistbias, float lightsubtract, float *lightcolor)
932 {
933         // FIXME
934 }
935
936 void R_Model_Zymotic_DrawOntoLight(entity_render_t *ent)
937 {
938         // FIXME
939 }
940