File: meshqueue.c

package info (click to toggle)
nexuiz 2.5.2-2
  • links: PTS, VCS
  • area: main
  • in suites: squeeze
  • size: 7,000 kB
  • ctags: 14,190
  • sloc: ansic: 120,037; pascal: 437; makefile: 252; objc: 245; sh: 28
file content (108 lines) | stat: -rw-r--r-- 2,987 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108

#include "quakedef.h"
#include "meshqueue.h"

typedef struct meshqueue_s
{
	struct meshqueue_s *next;
	void (*callback)(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfaceindices);
	const entity_render_t *ent;
	int surfacenumber;
	const rtlight_t *rtlight;
	float dist;
}
meshqueue_t;

float mqt_viewplanedist;
float mqt_viewmaxdist;
meshqueue_t *mqt_array;
int mqt_count;
int mqt_total;

void R_MeshQueue_BeginScene(void)
{
	mqt_count = 0;
	mqt_viewplanedist = DotProduct(r_refdef.view.origin, r_refdef.view.forward);
	mqt_viewmaxdist = 0;
}

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)
{
	meshqueue_t *mq;
	if (mqt_count >= mqt_total || !mqt_array)
	{
		int newtotal = max(1024, mqt_total * 2);
		meshqueue_t *newarray = (meshqueue_t *)Mem_Alloc(cls.permanentmempool, 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;
	}
	mq = &mqt_array[mqt_count++];
	mq->callback = callback;
	mq->ent = ent;
	mq->surfacenumber = surfacenumber;
	mq->rtlight = rtlight;
	mq->dist = DotProduct(center, r_refdef.view.forward) - mqt_viewplanedist;
	mq->next = NULL;
	mqt_viewmaxdist = max(mqt_viewmaxdist, mq->dist);
}

void R_MeshQueue_RenderTransparent(void)
{
	int i;
	int hashdist;
	int batchnumsurfaces;
	float distscale;
	const entity_render_t *ent;
	const rtlight_t *rtlight;
	void (*callback)(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfaceindices);
	meshqueue_t *mqt;
	meshqueue_t *hash[4096], **hashpointer[4096];
	int batchsurfaceindex[256];
	if (!mqt_count)
		return;
	memset(hash, 0, sizeof(hash));
	for (i = 0;i < 4096;i++)
		hashpointer[i] = &hash[i];
	distscale = 4095.0f / max(mqt_viewmaxdist, 4095);
	for (i = 0, mqt = mqt_array;i < mqt_count;i++, mqt++)
	{
		// generate index
		hashdist = (int) (mqt->dist * distscale);
		hashdist = bound(0, hashdist, 4095);
		// link to tail of hash chain (to preserve render order)
		mqt->next = NULL;
		*hashpointer[hashdist] = mqt;
		hashpointer[hashdist] = &mqt->next;
	}
	callback = NULL;
	ent = NULL;
	rtlight = NULL;
	batchnumsurfaces = 0;
	for (i = 4095;i >= 0;i--)
	{
		if (hash[i])
		{
			for (mqt = hash[i];mqt;mqt = mqt->next)
			{
				if (ent != mqt->ent || rtlight != mqt->rtlight || callback != mqt->callback || batchnumsurfaces >= 256)
				{
					if (batchnumsurfaces)
						callback(ent, rtlight, batchnumsurfaces, batchsurfaceindex);
					batchnumsurfaces = 0;
					ent = mqt->ent;
					rtlight = mqt->rtlight;
					callback = mqt->callback;
				}
				batchsurfaceindex[batchnumsurfaces++] = mqt->surfacenumber;
			}
		}
	}
	if (batchnumsurfaces)
		callback(ent, rtlight, batchnumsurfaces, batchsurfaceindex);
	mqt_count = 0;
}