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