vertex arrays renamed to varray_ and exposed to rest of engine
[divverent/darkplaces.git] / cgamevm.c
1
2 #include "quakedef.h"
3 #include "cgame_api.h"
4 #include "cl_collision.h"
5
6 #define CGVM_RENDERENTITIES 1024
7
8 static entity_render_t cgvm_renderentities[CGVM_RENDERENTITIES];
9 static int cgvm_renderentity;
10
11 static mempool_t *cgvm_mempool;
12
13 static void (*cgvm_networkcode[256])(unsigned char num);
14
15 static qbyte *cgvm_netbuffer;
16 static int cgvm_netbufferlength;
17 static int cgvm_netbufferpos;
18
19 #define MAX_CGVM_MODELS 128
20 #define MAX_CGVM_MODELNAME 32
21 static char cgvm_modelname[MAX_CGVM_MODELS][MAX_CGVM_MODELNAME];
22 static model_t *cgvm_model[MAX_CGVM_MODELS];
23
24 void CL_CGVM_Init(void)
25 {
26         cgvm_mempool = Mem_AllocPool("CGVM");
27 }
28
29 void CL_CGVM_Clear(void)
30 {
31         Mem_EmptyPool(cgvm_mempool);
32         memset(cgvm_networkcode, 0, sizeof(cgvm_networkcode));
33         memset(cgvm_modelname, 0, sizeof(cgvm_modelname));
34         memset(cgvm_model, 0, sizeof(cgvm_model));
35 }
36
37 void CL_CGVM_Frame(void)
38 {
39         cgvm_renderentity = 0;
40         CG_Frame(cl.time); // API call
41 }
42
43 // starts the cgame code
44 void CL_CGVM_Start(void)
45 {
46         CL_CGVM_Clear();
47         CG_Init(); // API call
48 }
49
50 void CL_CGVM_ParseNetwork(qbyte *netbuffer, int length)
51 {
52         int num;
53         cgvm_netbuffer = netbuffer;
54         cgvm_netbufferlength = length;
55         cgvm_netbufferpos = 0;
56         while (cgvm_netbufferpos < cgvm_netbufferlength)
57         {
58                 num = CGVM_MSG_ReadByte();
59                 if (cgvm_networkcode[num])
60                         cgvm_networkcode[num]((qbyte)num);
61                 else
62                         Host_Error("CL_CGVM_ParseNetwork: unregistered network code %i", num);
63         }
64 }
65
66
67
68
69
70
71
72
73 void CGVM_RegisterNetworkCode(const unsigned char num, void (*netcode)(unsigned char num))
74 {
75         if (cgvm_networkcode[num])
76                 Host_Error("CGVM_RegisterNetworkCode: value %i already registered", num);
77         cgvm_networkcode[num] = netcode;
78 }
79
80 unsigned char CGVM_MSG_ReadByte(void)
81 {
82         if (cgvm_netbufferpos < cgvm_netbufferlength)
83                 return cgvm_netbuffer[cgvm_netbufferpos++];
84         else
85                 return 0;
86 }
87
88 short CGVM_MSG_ReadShort(void)
89 {
90         int num;
91         num = CGVM_MSG_ReadByte() | (CGVM_MSG_ReadByte() << 8);
92         return num;
93 }
94
95 int CGVM_MSG_ReadLong(void)
96 {
97         int num;
98         num = CGVM_MSG_ReadByte() | (CGVM_MSG_ReadByte() << 8) | (CGVM_MSG_ReadByte() << 16) | (CGVM_MSG_ReadByte() << 24);
99         return num;
100 }
101
102 float CGVM_MSG_ReadFloat(void)
103 {
104         unsigned int num;
105         num = CGVM_MSG_ReadByte() | (CGVM_MSG_ReadByte() << 8) | (CGVM_MSG_ReadByte() << 16) | (CGVM_MSG_ReadByte() << 24);
106         return *((float *)&num);
107 }
108
109 float CGVM_MSG_ReadCoord(void)
110 {
111         return CGVM_MSG_ReadFloat();
112 }
113
114 float CGVM_MSG_ReadAngle(void)
115 {
116         return CGVM_MSG_ReadByte() * 360.0f / 256.0f;
117 }
118
119 float CGVM_MSG_ReadPreciseAngle(void)
120 {
121         return ((unsigned short)CGVM_MSG_ReadShort()) * 360.0f / 65536.0f;
122 }
123
124 void CGVM_Draw_Entity(const cgdrawentity_t *e)
125 {
126         entity_render_t *r;
127         //Con_Printf("CGVM_Draw_Entity: origin %f %f %f angles %f %f %f alpha %f scale %f model %i frame1 %i frame2 %i framelerp %f skinnum %i\n", e->origin[0], e->origin[1], e->origin[2], e->angles[0], e->angles[1], e->angles[2], e->alpha, e->scale, e->model, e->frame1, e->frame2, e->framelerp, e->skinnum);
128
129         if (!e->model)
130                 return;
131
132         if (cgvm_renderentity >= CGVM_RENDERENTITIES
133          || r_refdef.numentities >= r_refdef.maxentities)
134                 return;
135
136         r = cgvm_renderentities + cgvm_renderentity;
137         VectorCopy(e->origin, r->origin);
138         VectorCopy(e->angles, r->angles);
139         r->alpha = e->alpha;
140         r->scale = e->scale;
141         if (e->model < 0 || e->model >= MAX_CGVM_MODELS || !cgvm_model[e->model])
142         {
143                 Con_Printf("CGVM_Draw_Entity: invalid model index %i\n", e->model);
144                 return;
145         }
146         r->model = cgvm_model[e->model];
147
148         r->frame = e->frame2;
149         // FIXME: support colormapping?
150         r->colormap = -1;
151         // FIXME: support effects?
152         r->effects = 0;
153         r->skinnum = e->skinnum;
154         // FIXME: any flags worth setting?
155         r->flags = 0;
156
157         r->frame1 = e->frame1;
158         r->frame2 = e->frame2;
159         r->framelerp = e->framelerp;
160         r->frame1time = 0;
161         r->frame2time = 0;
162
163         r_refdef.entities[r_refdef.numentities++] = r;
164
165         cgvm_renderentity++;
166 }
167
168 void CGVM_Draw_Light(const cgdrawlight_t *l)
169 {
170         CL_AllocDlight(NULL, (float *) l->origin, 1, l->light[0], l->light[1], l->light[2], 0, 0);
171 }
172
173 void *CGVM_Malloc(const int size)
174 {
175         return Mem_Alloc(cgvm_mempool, size);
176 }
177
178 void CGVM_Free(void *mem)
179 {
180         Mem_Free(mem);
181 }
182
183 float CGVM_RandomRange(const float r1, const float r2)
184 {
185         return lhrandom(r1, r2);
186 }
187
188 float CGVM_TracePhysics(const float *start, const float *end, const float *worldmins, const float *worldmaxs, const float *entitymins, const float *entitymaxs, const cgphysentity_t *physentities, const int numphysentities, float *impactpos, float *impactnormal, int *impactentnum)
189 {
190         float frac;
191         vec3_t start2, end2, middle;
192         // FIXME: do tracing agains network entities and physentities here
193         // placeholder world only code assuming 0 size
194         middle[0] = (worldmins[0] + worldmaxs[0]) * 0.5f;
195         middle[1] = (worldmins[1] + worldmaxs[1]) * 0.5f;
196         middle[2] = (worldmins[2] + worldmaxs[2]) * 0.5f;
197         VectorAdd(start, middle, start2);
198         VectorAdd(end, middle, end2);
199         frac = CL_TraceLine((float *)start2, (float *)end2, impactpos, impactnormal, 0, true);
200         VectorSubtract(impactpos, middle, impactpos);
201         *impactentnum = -1;
202         return frac;
203 }
204
205 char *CGVM_GetCvarString(const char *name)
206 {
207         cvar_t *cvar;
208         cvar = Cvar_FindVar((char *)name);
209         if (cvar)
210                 return cvar->string;
211         else
212                 return 0;
213 }
214
215 float CGVM_GetCvarFloat(const char *name)
216 {
217         cvar_t *cvar;
218         cvar = Cvar_FindVar((char *)name);
219         if (cvar)
220                 return cvar->value;
221         else
222                 return 0;
223 }
224
225 int CGVM_GetCvarInt(const char *name)
226 {
227         cvar_t *cvar;
228         cvar = Cvar_FindVar((char *)name);
229         if (cvar)
230                 return cvar->integer;
231         else
232                 return 0;
233 }
234
235 double CGVM_Time(void)
236 {
237         return cl.time;
238 }
239
240 int CGVM_Model(const char *name)
241 {
242         int i;
243         model_t *model;
244         if (strlen(name) > (MAX_CGVM_MODELNAME - 1))
245                 return 0;
246         for (i = 1;i < MAX_CGVM_MODELS;i++)
247         {
248                 if (!cgvm_modelname[i][0])
249                         break;
250                 if (!strcmp(name, cgvm_modelname[i]))
251                         return i;
252         }
253         if (i >= MAX_CGVM_MODELS)
254                 return 0;
255         model = Mod_ForName((char *)name, false, false, false);
256         if (!model)
257                 return 0;
258         strcpy(cgvm_modelname[i], name);
259         cgvm_model[i] = model;
260         return i;
261 }
262
263 void CGVM_Stain(const float *origin, float radius, int cr1, int cg1, int cb1, int ca1, int cr2, int cg2, int cb2, int ca2)
264 {
265         if (cl_stainmaps.integer)
266                 R_Stain((float *)origin, radius, cr1, cg1, cb1, ca1, cr2, cg2, cb2, ca2);
267 }
268