added a mesh queue callback system (to allow mesh rendering things in different order...
authorhavoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Fri, 2 Aug 2002 18:11:23 +0000 (18:11 +0000)
committerhavoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Fri, 2 Aug 2002 18:11:23 +0000 (18:11 +0000)
git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@2170 d7cf8633-e32d-0410-b094-e92efae38249

darkplaces.dsp
makefile
makefile.mingw
meshqueue.c [new file with mode: 0644]
meshqueue.h [new file with mode: 0644]

index 309fe91..1e6e6ff 100644 (file)
@@ -248,6 +248,10 @@ SOURCE=.\menu.c
 # End Source File\r
 # Begin Source File\r
 \r
+SOURCE=.\meshqueue.c\r
+# End Source File\r
+# Begin Source File\r
+\r
 SOURCE=.\model_alias.c\r
 # End Source File\r
 # Begin Source File\r
@@ -544,6 +548,10 @@ SOURCE=.\menu.h
 # End Source File\r
 # Begin Source File\r
 \r
+SOURCE=.\meshqueue.h\r
+# End Source File\r
+# Begin Source File\r
+\r
 SOURCE=.\model_alias.h\r
 # End Source File\r
 # Begin Source File\r
index 8feb568..ebc44f0 100644 (file)
--- a/makefile
+++ b/makefile
@@ -22,7 +22,7 @@ SOUNDLIB=
 #if you want no CD audio
 CD=cd_null.o
 
-OBJECTS= builddate.o $(CD) $(SND) chase.o cl_demo.o cl_input.o cl_main.o cl_parse.o cl_tent.o cmd.o common.o console.o crc.o cvar.o fractalnoise.o gl_draw.o r_sky.o gl_rmain.o gl_rsurf.o host.o host_cmd.o image.o keys.o mathlib.o menu.o model_alias.o model_brush.o model_shared.o model_sprite.o net_bsd.o net_udp.o net_dgrm.o net_loop.o net_main.o pr_cmds.o pr_edict.o pr_exec.o r_light.o r_explosion.o sbar.o sv_main.o sv_move.o sv_phys.o sv_user.o sv_light.o sys_linux.o transform.o view.o wad.o world.o zone.o vid_shared.o palette.o r_crosshairs.o gl_textures.o gl_models.o r_sprites.o r_modules.o r_explosion.o r_lerpanim.o protocol.o quakeio.o r_clip.o ui.o portals.o sys_shared.o cl_light.o gl_backend.o cl_particles.o cl_screen.o cgamevm.o cgame.o filematch.o collision.o cl_collision.o matrixlib.o cl_video.o dpvsimpledecode.o wavefile.o
+OBJECTS= builddate.o $(CD) $(SND) chase.o cl_demo.o cl_input.o cl_main.o cl_parse.o cl_tent.o cmd.o common.o console.o crc.o cvar.o fractalnoise.o gl_draw.o r_sky.o gl_rmain.o gl_rsurf.o host.o host_cmd.o image.o keys.o mathlib.o menu.o model_alias.o model_brush.o model_shared.o model_sprite.o net_bsd.o net_udp.o net_dgrm.o net_loop.o net_main.o pr_cmds.o pr_edict.o pr_exec.o r_light.o r_explosion.o sbar.o sv_main.o sv_move.o sv_phys.o sv_user.o sv_light.o sys_linux.o transform.o view.o wad.o world.o zone.o vid_shared.o palette.o r_crosshairs.o gl_textures.o gl_models.o r_sprites.o r_modules.o r_explosion.o r_lerpanim.o protocol.o quakeio.o r_clip.o ui.o portals.o sys_shared.o cl_light.o gl_backend.o cl_particles.o cl_screen.o cgamevm.o cgame.o filematch.o collision.o cl_collision.o matrixlib.o cl_video.o dpvsimpledecode.o wavefile.o meshqueue.o
 
 #K6/athlon optimizations
 CPUOPTIMIZATIONS=-march=k6
index 937f24d..d306b4f 100644 (file)
@@ -1,5 +1,5 @@
 
-OBJECTS= builddate.o chase.o cl_demo.o cl_input.o cl_main.o cl_parse.o cl_tent.o cmd.o common.o console.o crc.o cvar.o fractalnoise.o gl_draw.o r_sky.o gl_rmain.o gl_rsurf.o host.o host_cmd.o image.o keys.o mathlib.o menu.o model_alias.o model_brush.o model_shared.o model_sprite.o net_dgrm.o net_loop.o net_main.o pr_cmds.o pr_edict.o pr_exec.o r_light.o r_explosion.o sbar.o snd_dma.o snd_mem.o snd_mix.o sv_main.o sv_move.o sv_phys.o sv_user.o sv_light.o transform.o view.o wad.o world.o zone.o vid_shared.o palette.o r_crosshairs.o gl_textures.o gl_models.o r_sprites.o r_modules.o r_explosion.o r_lerpanim.o protocol.o quakeio.o r_clip.o ui.o portals.o sys_shared.o cl_light.o gl_backend.o cl_particles.o cl_screen.o cgamevm.o cgame.o filematch.o collision.o cl_collision.o matrixlib.o cl_video.o dpvsimpledecode.o wavefile.o
+OBJECTS= builddate.o chase.o cl_demo.o cl_input.o cl_main.o cl_parse.o cl_tent.o cmd.o common.o console.o crc.o cvar.o fractalnoise.o gl_draw.o r_sky.o gl_rmain.o gl_rsurf.o host.o host_cmd.o image.o keys.o mathlib.o menu.o model_alias.o model_brush.o model_shared.o model_sprite.o net_dgrm.o net_loop.o net_main.o pr_cmds.o pr_edict.o pr_exec.o r_light.o r_explosion.o sbar.o snd_dma.o snd_mem.o snd_mix.o sv_main.o sv_move.o sv_phys.o sv_user.o sv_light.o transform.o view.o wad.o world.o zone.o vid_shared.o palette.o r_crosshairs.o gl_textures.o gl_models.o r_sprites.o r_modules.o r_explosion.o r_lerpanim.o protocol.o quakeio.o r_clip.o ui.o portals.o sys_shared.o cl_light.o gl_backend.o cl_particles.o cl_screen.o cgamevm.o cgame.o filematch.o collision.o cl_collision.o matrixlib.o cl_video.o dpvsimpledecode.o wavefile.o meshqueue.o
 
 #K6/athlon optimizations
 #CPUOPTIMIZATIONS=-march=k6
diff --git a/meshqueue.c b/meshqueue.c
new file mode 100644 (file)
index 0000000..e75bddd
--- /dev/null
@@ -0,0 +1,175 @@
+
+#include "quakedef.h"
+#include "meshqueue.h"
+
+cvar_t r_meshqueue_entries = {CVAR_SAVE, "r_meshqueue_entries", "16"};
+cvar_t r_meshqueue_immediaterender = {0, "r_meshqueue_immediaterender", "0"};
+cvar_t r_meshqueue_sort = {0, "r_meshqueue_sort", "0"};
+
+typedef struct meshqueue_s
+{
+       struct meshqueue_s *next;
+       void (*callback)(void *data1, int data2);
+       void *data1;
+       int data2;
+       float dist;
+}
+meshqueue_t;
+
+float mqt_viewplanedist;
+meshqueue_t *mq_array, *mqt_array, *mq_listhead;
+int mq_count, mqt_count;
+int mq_total, mqt_total;
+
+mempool_t *meshqueuemempool;
+
+void R_MeshQueue_Init(void)
+{
+       Cvar_RegisterVariable(&r_meshqueue_entries);
+       Cvar_RegisterVariable(&r_meshqueue_immediaterender);
+       Cvar_RegisterVariable(&r_meshqueue_sort);
+
+       meshqueuemempool = Mem_AllocPool("R_MeshQueue");
+       mq_total = 0;
+       mqt_total = 1000;
+       mq_array = NULL;
+       mqt_array = NULL;
+}
+
+static void R_MeshQueue_Render(void)
+{
+       meshqueue_t *mq;
+       for (mq = mq_listhead;mq;mq = mq->next)
+               mq->callback(mq->data1, mq->data2);
+       mq_count = 0;
+       mq_listhead = NULL;
+}
+
+static void R_MeshQueue_EnlargeTransparentArray(int newtotal)
+{
+       meshqueue_t *newarray;
+       newarray = Mem_Alloc(meshqueuemempool, newtotal * sizeof(meshqueue_t));
+       if (mqt_array)
+       {
+               memcpy(newarray, mqt_array, mqt_total * sizeof(meshqueue_t));
+               Mem_Free(mqt_array);
+       }
+       mqt_array = newarray;
+       mqt_total = newtotal;
+}
+
+void R_MeshQueue_Add(void (*callback)(void *data1, int data2), void *data1, int data2)
+{
+       meshqueue_t *mq, **mqnext;
+       if (r_meshqueue_immediaterender.integer)
+       {
+               callback(data1, data2);
+               return;
+       }
+       if (mq_count >= mq_total)
+               R_MeshQueue_Render();
+       mq = &mq_array[mq_count++];
+       mq->callback = callback;
+       mq->data1 = data1;
+       mq->data2 = data2;
+
+       // bubble-insert sort into meshqueue
+       mqnext = &mq_listhead;
+       if (r_meshqueue_sort.integer)
+       {
+               for(;;)
+               {
+                       if (*mqnext)
+                       {
+                               if (mq->callback == (*mqnext)->callback)
+                               {
+                                       if (mq->data1 == (*mqnext)->data1)
+                                       {
+                                               if (mq->data2 <= (*mqnext)->data2)
+                                                       break;
+                                       }
+                                       else if (mq->data1 < (*mqnext)->data1)
+                                               break;
+                               }
+                               else if (mq->callback < (*mqnext)->callback)
+                                       break;
+                       }
+                       else
+                               break;
+                       mqnext = &(*mqnext)->next;
+               }
+       }
+       mq->next = *mqnext;
+       *mqnext = mq;
+}
+
+void R_MeshQueue_AddTransparent(vec3_t center, void (*callback)(void *data1, int data2), void *data1, int data2)
+{
+       meshqueue_t *mq;
+       if (mqt_count >= mqt_total)
+               R_MeshQueue_EnlargeTransparentArray(mqt_total + 100);
+       mq = &mqt_array[mqt_count++];
+       mq->callback = callback;
+       mq->data1 = data1;
+       mq->data2 = data2;
+       mq->dist = DotProduct(center, vpn) - mqt_viewplanedist;
+       mq->next = NULL;
+}
+
+static void R_MeshQueue_RenderTransparent(void)
+{
+       int i;
+       int hashdist;
+       meshqueue_t *mqt;
+       meshqueue_t *hash[4096];
+       memset(hash, 0, 4096 * sizeof(meshqueue_t *));
+       for (i = 0, mqt = mqt_array;i < mqt_count;i++, mqt++)
+       {
+               // generate index
+               hashdist = (int) (mqt->dist);
+               hashdist = bound(0, hashdist, 4095);
+               // reversed to simplify render loop
+               hashdist = 4095 - hashdist;
+               // link into hash chain
+               mqt->next = hash[hashdist];
+               hash[hashdist] = mqt;
+       }
+       for (i = 0;i < 4096;i++)
+               if (hash[i])
+                       for (mqt = hash[i];mqt;mqt = mqt->next)
+                               R_MeshQueue_Add(mqt->callback, mqt->data1, mqt->data2);
+       mqt_count = 0;
+}
+
+void R_MeshQueue_BeginScene(void)
+{
+       if (r_meshqueue_entries.integer < 1)
+               Cvar_SetValueQuick(&r_meshqueue_entries, 1);
+       if (r_meshqueue_entries.integer > 65536)
+               Cvar_SetValueQuick(&r_meshqueue_entries, 65536);
+
+       if (mq_total != r_meshqueue_entries.integer || mq_array == NULL)
+       {
+               mq_total = r_meshqueue_entries.integer;
+               if (mq_array)
+                       Mem_Free(mq_array);
+               mq_array = Mem_Alloc(meshqueuemempool, mq_total * sizeof(meshqueue_t));
+       }
+
+       if (mqt_array == NULL)
+               mqt_array = Mem_Alloc(meshqueuemempool, mqt_total * sizeof(meshqueue_t));
+
+       mq_count = 0;
+       mqt_count = 0;
+       mq_listhead = NULL;
+       mqt_viewplanedist = DotProduct(r_origin, vpn);
+}
+
+void R_MeshQueue_EndScene(void)
+{
+       if (mqt_count)
+               R_MeshQueue_RenderTransparent();
+       if (mq_count)
+               R_MeshQueue_Render();
+}
+
diff --git a/meshqueue.h b/meshqueue.h
new file mode 100644 (file)
index 0000000..60b7aa4
--- /dev/null
@@ -0,0 +1,11 @@
+
+#ifndef MESHQUEUE_H
+#define MESHQUEUE_H
+
+void R_MeshQueue_Init(void);
+void R_MeshQueue_Add(void (*callback)(void *data1, int data2), void *data1, int data2);
+void R_MeshQueue_AddTransparent(vec3_t center, void (*callback)(void *data1, int data2), void *data1, int data2);
+void R_MeshQueue_BeginScene(void);
+void R_MeshQueue_EndScene(void);
+
+#endif