4 #include "cl_collision.h"
6 #define CGVM_RENDERENTITIES 1024
8 static entity_render_t cgvm_renderentities[CGVM_RENDERENTITIES];
9 static int cgvm_renderentity;
11 static mempool_t *cgvm_mempool;
13 static void (*cgvm_networkcode[256])(unsigned char num);
15 static qbyte *cgvm_netbuffer;
16 static int cgvm_netbufferlength;
17 static int cgvm_netbufferpos;
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];
24 void CL_CGVM_Init(void)
26 cgvm_mempool = Mem_AllocPool("CGVM", 0, NULL);
29 void CL_CGVM_Shutdown(void)
31 Mem_FreePool (&cgvm_mempool);
34 void CL_CGVM_Clear(void)
36 Mem_EmptyPool(cgvm_mempool);
37 memset(cgvm_networkcode, 0, sizeof(cgvm_networkcode));
38 memset(cgvm_modelname, 0, sizeof(cgvm_modelname));
39 memset(cgvm_model, 0, sizeof(cgvm_model));
42 void CL_CGVM_Frame(void)
44 cgvm_renderentity = 0;
45 CG_Frame(cl.time); // API call
48 // starts the cgame code
49 void CL_CGVM_Start(void)
52 CG_Init(); // API call
55 void CL_CGVM_ParseNetwork(qbyte *netbuffer, int length)
58 cgvm_netbuffer = netbuffer;
59 cgvm_netbufferlength = length;
60 cgvm_netbufferpos = 0;
61 while (cgvm_netbufferpos < cgvm_netbufferlength)
63 num = CGVM_MSG_ReadByte();
64 if (cgvm_networkcode[num])
65 cgvm_networkcode[num]((qbyte)num);
67 Host_Error("CL_CGVM_ParseNetwork: unregistered network code %i", num);
78 void CGVM_RegisterNetworkCode(const unsigned char num, void (*netcode)(unsigned char num))
80 if (cgvm_networkcode[num])
81 Host_Error("CGVM_RegisterNetworkCode: value %i already registered", num);
82 cgvm_networkcode[num] = netcode;
85 unsigned char CGVM_MSG_ReadByte(void)
87 if (cgvm_netbufferpos < cgvm_netbufferlength)
88 return cgvm_netbuffer[cgvm_netbufferpos++];
93 short CGVM_MSG_ReadShort(void)
96 num = CGVM_MSG_ReadByte() | (CGVM_MSG_ReadByte() << 8);
100 int CGVM_MSG_ReadLong(void)
103 num = CGVM_MSG_ReadByte() | (CGVM_MSG_ReadByte() << 8) | (CGVM_MSG_ReadByte() << 16) | (CGVM_MSG_ReadByte() << 24);
107 float CGVM_MSG_ReadFloat(void)
110 num = CGVM_MSG_ReadByte() | (CGVM_MSG_ReadByte() << 8) | (CGVM_MSG_ReadByte() << 16) | (CGVM_MSG_ReadByte() << 24);
111 return *((float *)&num);
114 float CGVM_MSG_ReadCoord(void)
116 return CGVM_MSG_ReadFloat();
119 float CGVM_MSG_ReadAngle(void)
121 return CGVM_MSG_ReadByte() * 360.0f / 256.0f;
124 float CGVM_MSG_ReadPreciseAngle(void)
126 return ((unsigned short)CGVM_MSG_ReadShort()) * 360.0f / 65536.0f;
129 void CGVM_Draw_Entity(const cgdrawentity_t *e)
132 //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);
137 if (cgvm_renderentity >= CGVM_RENDERENTITIES
138 || r_refdef.numentities >= r_refdef.maxentities)
141 r = cgvm_renderentities + cgvm_renderentity;
142 VectorCopy(e->origin, r->origin);
143 VectorCopy(e->angles, r->angles);
146 if (e->model < 0 || e->model >= MAX_CGVM_MODELS || !cgvm_model[e->model])
148 Con_Printf("CGVM_Draw_Entity: invalid model index %i\n", e->model);
151 r->model = cgvm_model[e->model];
153 r->frame = e->frame2;
154 // FIXME: support colormapping?
156 // FIXME: support effects?
158 r->skinnum = e->skinnum;
159 // FIXME: any flags worth setting?
162 r->frame1 = e->frame1;
163 r->frame2 = e->frame2;
164 r->framelerp = e->framelerp;
168 r_refdef.entities[r_refdef.numentities++] = r;
173 void CGVM_Draw_Light(const cgdrawlight_t *l)
176 Matrix4x4_CreateTranslate(&matrix, l->origin[0], l->origin[1], l->origin[2]);
177 CL_AllocDlight(NULL, &matrix, l->radius, l->color[0], l->color[1], l->color[2], 0, 0, 0, -1, true, 1, 0.25, 0, 1, 1, LIGHTFLAG_NORMALMODE | LIGHTFLAG_REALTIMEMODE);
180 void *CGVM_Malloc(const int size)
182 return Mem_Alloc(cgvm_mempool, size);
185 void CGVM_Free(void *mem)
190 float CGVM_RandomRange(const float r1, const float r2)
192 return lhrandom(r1, r2);
195 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)
198 vec3_t start2, end2, middle;
199 // FIXME: do tracing agains network entities and physentities here
200 // placeholder world only code assuming 0 size
201 middle[0] = (worldmins[0] + worldmaxs[0]) * 0.5f;
202 middle[1] = (worldmins[1] + worldmaxs[1]) * 0.5f;
203 middle[2] = (worldmins[2] + worldmaxs[2]) * 0.5f;
204 VectorAdd(start, middle, start2);
205 VectorAdd(end, middle, end2);
206 frac = CL_TraceLine((float *)start2, (float *)end2, impactpos, impactnormal, true, NULL, SUPERCONTENTS_SOLID);
207 VectorSubtract(impactpos, middle, impactpos);
212 char *CGVM_GetCvarString(const char *name)
215 cvar = Cvar_FindVar((char *)name);
222 float CGVM_GetCvarFloat(const char *name)
225 cvar = Cvar_FindVar((char *)name);
232 int CGVM_GetCvarInt(const char *name)
235 cvar = Cvar_FindVar((char *)name);
237 return cvar->integer;
242 double CGVM_Time(void)
247 int CGVM_Model(const char *name)
251 if (strlen(name) > (MAX_CGVM_MODELNAME - 1))
253 for (i = 1;i < MAX_CGVM_MODELS;i++)
255 if (!cgvm_modelname[i][0])
257 if (!strcmp(name, cgvm_modelname[i]))
260 if (i >= MAX_CGVM_MODELS)
262 model = Mod_ForName((char *)name, false, false, false);
265 strcpy(cgvm_modelname[i], name);
266 cgvm_model[i] = model;
270 void CGVM_Stain(const float *origin, float radius, int cr1, int cg1, int cb1, int ca1, int cr2, int cg2, int cb2, int ca2)
272 if (cl_stainmaps.integer)
273 R_Stain((float *)origin, radius, cr1, cg1, cb1, ca1, cr2, cg2, cb2, ca2);