Fix two bugs (everything should behave as usual now, when you're not using menu rende...
[divverent/darkplaces.git] / meshqueue.c
1
2 #include "quakedef.h"
3 #include "meshqueue.h"
4
5 typedef struct meshqueue_s
6 {
7         struct meshqueue_s *next;
8         void (*callback)(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfaceindices);
9         const entity_render_t *ent;
10         int surfacenumber;
11         const rtlight_t *rtlight;
12         float dist;
13 }
14 meshqueue_t;
15
16 float mqt_viewplanedist;
17 float mqt_viewmaxdist;
18 meshqueue_t *mqt_array;
19 int mqt_count;
20 int mqt_total;
21
22 void R_MeshQueue_BeginScene(void)
23 {
24         mqt_count = 0;
25         mqt_viewplanedist = DotProduct(r_refdef.view.origin, r_refdef.view.forward);
26         mqt_viewmaxdist = 0;
27 }
28
29 void R_MeshQueue_AddTransparent(const vec3_t center, void (*callback)(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist), const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight)
30 {
31         meshqueue_t *mq;
32         if (mqt_count >= mqt_total || !mqt_array)
33         {
34                 int newtotal = max(1024, mqt_total * 2);
35                 meshqueue_t *newarray = (meshqueue_t *)Mem_Alloc(cls.permanentmempool, newtotal * sizeof(meshqueue_t));
36                 if (mqt_array)
37                 {
38                         memcpy(newarray, mqt_array, mqt_total * sizeof(meshqueue_t));
39                         Mem_Free(mqt_array);
40                 }
41                 mqt_array = newarray;
42                 mqt_total = newtotal;
43         }
44         mq = &mqt_array[mqt_count++];
45         mq->callback = callback;
46         mq->ent = ent;
47         mq->surfacenumber = surfacenumber;
48         mq->rtlight = rtlight;
49         mq->dist = DotProduct(center, r_refdef.view.forward) - mqt_viewplanedist;
50         mq->next = NULL;
51         mqt_viewmaxdist = max(mqt_viewmaxdist, mq->dist);
52 }
53
54 void R_MeshQueue_RenderTransparent(void)
55 {
56         int i;
57         int hashdist;
58         int batchnumsurfaces;
59         float distscale;
60         const entity_render_t *ent;
61         const rtlight_t *rtlight;
62         void (*callback)(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfaceindices);
63         meshqueue_t *mqt;
64         meshqueue_t *hash[4096], **hashpointer[4096];
65         int batchsurfaceindex[256];
66         if (!mqt_count)
67                 return;
68         memset(hash, 0, sizeof(hash));
69         for (i = 0;i < 4096;i++)
70                 hashpointer[i] = &hash[i];
71         distscale = 4095.0f / max(mqt_viewmaxdist, 4095);
72         for (i = 0, mqt = mqt_array;i < mqt_count;i++, mqt++)
73         {
74                 // generate index
75                 hashdist = (int) (mqt->dist * distscale);
76                 hashdist = bound(0, hashdist, 4095);
77                 // link to tail of hash chain (to preserve render order)
78                 mqt->next = NULL;
79                 *hashpointer[hashdist] = mqt;
80                 hashpointer[hashdist] = &mqt->next;
81         }
82         callback = NULL;
83         ent = NULL;
84         rtlight = NULL;
85         batchnumsurfaces = 0;
86         for (i = 4095;i >= 0;i--)
87         {
88                 if (hash[i])
89                 {
90                         for (mqt = hash[i];mqt;mqt = mqt->next)
91                         {
92                                 if (ent != mqt->ent || rtlight != mqt->rtlight || callback != mqt->callback || batchnumsurfaces >= 256)
93                                 {
94                                         if (batchnumsurfaces)
95                                                 callback(ent, rtlight, batchnumsurfaces, batchsurfaceindex);
96                                         batchnumsurfaces = 0;
97                                         ent = mqt->ent;
98                                         rtlight = mqt->rtlight;
99                                         callback = mqt->callback;
100                                 }
101                                 batchsurfaceindex[batchnumsurfaces++] = mqt->surfacenumber;
102                         }
103                 }
104         }
105         if (batchnumsurfaces)
106                 callback(ent, rtlight, batchnumsurfaces, batchsurfaceindex);
107         mqt_count = 0;
108 }