5 cvar_t r_meshqueue_entries = {CVAR_SAVE, "r_meshqueue_entries", "16"};
6 cvar_t r_meshqueue_immediaterender = {0, "r_meshqueue_immediaterender", "0"};
7 cvar_t r_meshqueue_sort = {0, "r_meshqueue_sort", "0"};
9 typedef struct meshqueue_s
11 struct meshqueue_s *next;
12 void (*callback)(void *data1, int data2);
19 float mqt_viewplanedist;
20 meshqueue_t *mq_array, *mqt_array, *mq_listhead;
21 int mq_count, mqt_count;
22 int mq_total, mqt_total;
24 mempool_t *meshqueuemempool;
26 void R_MeshQueue_Init(void)
28 Cvar_RegisterVariable(&r_meshqueue_entries);
29 Cvar_RegisterVariable(&r_meshqueue_immediaterender);
30 Cvar_RegisterVariable(&r_meshqueue_sort);
32 meshqueuemempool = Mem_AllocPool("R_MeshQueue");
39 static void R_MeshQueue_Render(void)
42 for (mq = mq_listhead;mq;mq = mq->next)
43 mq->callback(mq->data1, mq->data2);
48 static void R_MeshQueue_EnlargeTransparentArray(int newtotal)
50 meshqueue_t *newarray;
51 newarray = Mem_Alloc(meshqueuemempool, newtotal * sizeof(meshqueue_t));
54 memcpy(newarray, mqt_array, mqt_total * sizeof(meshqueue_t));
61 void R_MeshQueue_Add(void (*callback)(void *data1, int data2), void *data1, int data2)
63 meshqueue_t *mq, **mqnext;
64 if (r_meshqueue_immediaterender.integer)
66 callback(data1, data2);
69 if (mq_count >= mq_total)
71 mq = &mq_array[mq_count++];
72 mq->callback = callback;
76 // bubble-insert sort into meshqueue
77 mqnext = &mq_listhead;
78 if (r_meshqueue_sort.integer)
84 if (mq->callback == (*mqnext)->callback)
86 if (mq->data1 == (*mqnext)->data1)
88 if (mq->data2 <= (*mqnext)->data2)
91 else if (mq->data1 < (*mqnext)->data1)
94 else if (mq->callback < (*mqnext)->callback)
99 mqnext = &(*mqnext)->next;
106 void R_MeshQueue_AddTransparent(vec3_t center, void (*callback)(void *data1, int data2), void *data1, int data2)
109 if (mqt_count >= mqt_total)
110 R_MeshQueue_EnlargeTransparentArray(mqt_total + 100);
111 mq = &mqt_array[mqt_count++];
112 mq->callback = callback;
115 mq->dist = DotProduct(center, vpn) - mqt_viewplanedist;
119 static void R_MeshQueue_RenderTransparent(void)
124 meshqueue_t *hash[4096];
125 memset(hash, 0, 4096 * sizeof(meshqueue_t *));
126 for (i = 0, mqt = mqt_array;i < mqt_count;i++, mqt++)
129 hashdist = (int) (mqt->dist);
130 hashdist = bound(0, hashdist, 4095);
131 // reversed to simplify render loop
132 hashdist = 4095 - hashdist;
133 // link into hash chain
134 mqt->next = hash[hashdist];
135 hash[hashdist] = mqt;
137 for (i = 0;i < 4096;i++)
139 for (mqt = hash[i];mqt;mqt = mqt->next)
140 R_MeshQueue_Add(mqt->callback, mqt->data1, mqt->data2);
144 void R_MeshQueue_BeginScene(void)
146 if (r_meshqueue_entries.integer < 1)
147 Cvar_SetValueQuick(&r_meshqueue_entries, 1);
148 if (r_meshqueue_entries.integer > 65536)
149 Cvar_SetValueQuick(&r_meshqueue_entries, 65536);
151 if (mq_total != r_meshqueue_entries.integer || mq_array == NULL)
153 mq_total = r_meshqueue_entries.integer;
156 mq_array = Mem_Alloc(meshqueuemempool, mq_total * sizeof(meshqueue_t));
159 if (mqt_array == NULL)
160 mqt_array = Mem_Alloc(meshqueuemempool, mqt_total * sizeof(meshqueue_t));
165 mqt_viewplanedist = DotProduct(r_origin, vpn);
168 void R_MeshQueue_EndScene(void)
171 R_MeshQueue_RenderTransparent();
173 R_MeshQueue_Render();