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)(const 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 void R_MeshQueue_Init(void)
26 Cvar_RegisterVariable(&r_meshqueue_entries);
27 Cvar_RegisterVariable(&r_meshqueue_immediaterender);
28 Cvar_RegisterVariable(&r_meshqueue_sort);
36 void R_MeshQueue_Render(void)
41 for (mq = mq_listhead;mq;mq = mq->next)
42 mq->callback(mq->data1, mq->data2);
47 static void R_MeshQueue_EnlargeTransparentArray(int newtotal)
49 meshqueue_t *newarray;
50 newarray = Mem_Alloc(cl_mempool, newtotal * sizeof(meshqueue_t));
53 memcpy(newarray, mqt_array, mqt_total * sizeof(meshqueue_t));
60 void R_MeshQueue_Add(void (*callback)(const void *data1, int data2), const void *data1, int data2)
62 meshqueue_t *mq, **mqnext;
63 if (r_meshqueue_immediaterender.integer)
65 callback(data1, data2);
68 if (mq_count >= mq_total)
70 mq = &mq_array[mq_count++];
71 mq->callback = callback;
75 if (r_meshqueue_sort.integer)
77 // bubble-insert sort into meshqueue
78 for(mqnext = &mq_listhead;*mqnext;mqnext = &(*mqnext)->next)
80 if (mq->callback == (*mqnext)->callback)
82 if (mq->data1 == (*mqnext)->data1)
84 if (mq->data2 <= (*mqnext)->data2)
87 else if (mq->data1 < (*mqnext)->data1)
90 else if (mq->callback < (*mqnext)->callback)
97 for(mqnext = &mq_listhead;*mqnext;mqnext = &(*mqnext)->next);
103 void R_MeshQueue_AddTransparent(const vec3_t center, void (*callback)(const void *data1, int data2), const void *data1, int data2)
106 if (mqt_count >= mqt_total)
107 R_MeshQueue_EnlargeTransparentArray(mqt_total + 100);
108 mq = &mqt_array[mqt_count++];
109 mq->callback = callback;
112 mq->dist = DotProduct(center, r_viewforward) - mqt_viewplanedist;
116 void R_MeshQueue_RenderTransparent(void)
121 meshqueue_t *hash[4096], **hashpointer[4096];
123 R_MeshQueue_Render();
126 memset(hash, 0, sizeof(hash));
127 for (i = 0;i < 4096;i++)
128 hashpointer[i] = &hash[i];
129 for (i = 0, mqt = mqt_array;i < mqt_count;i++, mqt++)
132 hashdist = (int) (mqt->dist);
133 hashdist = bound(0, hashdist, 4095);
134 // link to tail of hash chain (to preserve render order)
136 *hashpointer[hashdist] = mqt;
137 hashpointer[hashdist] = &mqt->next;
139 for (i = 4095;i >= 0;i--)
141 for (mqt = hash[i];mqt;mqt = mqt->next)
142 mqt->callback(mqt->data1, mqt->data2);
146 void R_MeshQueue_BeginScene(void)
148 if (r_meshqueue_entries.integer < 1)
149 Cvar_SetValueQuick(&r_meshqueue_entries, 1);
150 if (r_meshqueue_entries.integer > 65536)
151 Cvar_SetValueQuick(&r_meshqueue_entries, 65536);
153 if (mq_total != r_meshqueue_entries.integer || mq_array == NULL)
155 mq_total = r_meshqueue_entries.integer;
158 mq_array = Mem_Alloc(cl_mempool, mq_total * sizeof(meshqueue_t));
161 if (mqt_array == NULL)
162 mqt_array = Mem_Alloc(cl_mempool, mqt_total * sizeof(meshqueue_t));
167 mqt_viewplanedist = DotProduct(r_vieworigin, r_viewforward);
170 void R_MeshQueue_EndScene(void)
174 Con_Printf("R_MeshQueue_EndScene: main mesh queue still has %i items left, flushing\n", mq_count);
175 R_MeshQueue_Render();
179 Con_Printf("R_MeshQueue_EndScene: transparent mesh queue still has %i items left, flushing\n", mqt_count);
180 R_MeshQueue_RenderTransparent();