#include "cl_collision.h"
#include "r_shadow.h"
+/* Per-VM scenes */
+renderscene_t* renderscenes[PRVM_MAXPROGS];
+#define RENDERSCENE (*renderscenes[prognum])
+
//============================================================================
// Client
//[515]: unsolved PROBLEMS
}
// #2 void(entity e, vector o) setorigin
-static void VM_CL_setorigin (void)
+void VM_CL_setorigin (void)
{
prvm_edict_t *e;
float *org;
}
// #3 void(entity e, string m) setmodel
-static void VM_CL_setmodel (void)
+void VM_CL_setmodel (void)
{
prvm_edict_t *e;
const char *m;
// #20 void(string s) precache_model
-static void VM_CL_precache_model (void)
+void VM_CL_precache_model (void)
{
const char *name;
int i;
//============================================================================
//[515]: SCENE MANAGER builtins
-extern qboolean CSQC_AddRenderEdict (prvm_edict_t *ed);//csprogs.c
+extern qboolean CSQC_AddRenderEdict (renderscene_t* scene, prvm_edict_t *ed);//csprogs.c
static void CSQC_R_RecalcView (void)
{
void CL_RelinkLightFlashes(void);
//#300 void() clearscene (EXT_CSQC)
-static void VM_CL_R_ClearScene (void)
+void VM_CL_R_ClearScene (void)
{
VM_SAFEPARMCOUNT(0, VM_CL_R_ClearScene);
// clear renderable entity and light lists
//#301 void(float mask) addentities (EXT_CSQC)
extern void CSQC_Predraw (prvm_edict_t *ed);//csprogs.c
extern void CSQC_Think (prvm_edict_t *ed);//csprogs.c
-static void VM_CL_R_AddEntities (void)
+void VM_CL_R_AddEntities (void)
{
int i, drawmask;
prvm_edict_t *ed;
}
//#302 void(entity ent) addentity (EXT_CSQC)
-static void VM_CL_R_AddEntity (void)
+void VM_CL_R_AddEntity (void)
{
VM_SAFEPARMCOUNT(1, VM_CL_R_AddEntity);
CSQC_AddRenderEdict(PRVM_G_EDICT(OFS_PARM0));
}
//#303 float(float property, ...) setproperty (EXT_CSQC)
-static void VM_CL_R_SetView (void)
+void VM_CL_R_SetView (void)
{
int c;
float *f;
}
//#304 void() renderscene (EXT_CSQC)
-static void VM_CL_R_RenderScene (void)
+void VM_CL_R_RenderScene (void)
{
VM_SAFEPARMCOUNT(0, VM_CL_R_RenderScene);
// we need to update any RENDER_VIEWMODEL entities at this point because
}
//#305 void(vector org, float radius, vector lightcolours) adddynamiclight (EXT_CSQC)
-static void VM_CL_R_AddDynamicLight (void)
+void VM_CL_R_AddDynamicLight (void)
{
float *pos, *col;
matrix4x4_t matrix;
unsigned char flags; //[515]: + VM_POLYGON_2D and VM_POLYGON_FL4V flags
}vm_polygon_t;
-//static float vm_polygon_linewidth = 1;
-static mempool_t *vm_polygons_pool = NULL;
-static unsigned char vm_current_vertices = 0;
-static qboolean vm_polygons_initialized = false;
-static vm_polygon_t *vm_polygons = NULL;
-static unsigned long vm_polygons_num = 0, vm_drawpolygons_num = 0; //[515]: ok long on 64bit ?
-static qboolean vm_polygonbegin = false; //[515]: for "no-crap-on-the-screen" check
+typedef struct vmpolygons_s
+{
+ //static float vm_polygon_linewidth = 1;
+ mempool_t *pool;
+ unsigned char current_vertices;
+ qboolean initialized;
+ vm_polygon_t *polygons;
+ unsigned long polygons_num, drawpolygons_num; //[515]: ok long on 64bit ?
+ qboolean polygonbegin; //[515]: for "no-crap-on-the-screen" check
+} vmpolygons_t;
+vmpolygons_t vmpolygons[PRVM_MAXPROGS];
#define VM_DEFPOLYNUM 64 //[515]: enough for default ?
#define VM_POLYGON_FL3V 16 //more than 2 vertices (used only for lines)
#define VM_POLYGON_FL2D 64
#define VM_POLYGON_FL4V 128 //4 vertices
-static void VM_InitPolygons (void)
+static void VM_InitPolygons (vmpolygons_t* polys)
{
- vm_polygons_pool = Mem_AllocPool("VMPOLY", 0, NULL);
- vm_polygons = (vm_polygon_t *)Mem_Alloc(vm_polygons_pool, VM_DEFPOLYNUM*sizeof(vm_polygon_t));
- memset(vm_polygons, 0, VM_DEFPOLYNUM*sizeof(vm_polygon_t));
- vm_polygons_num = VM_DEFPOLYNUM;
- vm_drawpolygons_num = 0;
- vm_polygonbegin = false;
- vm_polygons_initialized = true;
+ polys->pool = Mem_AllocPool("VMPOLY", 0, NULL);
+ polys->polygons = (vm_polygon_t *)Mem_Alloc(polys->pool, VM_DEFPOLYNUM*sizeof(vm_polygon_t));
+ memset(polys->polygons, 0, VM_DEFPOLYNUM*sizeof(vm_polygon_t));
+ polys->polygons_num = VM_DEFPOLYNUM;
+ polys->drawpolygons_num = 0;
+ polys->polygonbegin = false;
+ polys->initialized = true;
}
static void VM_DrawPolygonCallback (const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
{
int surfacelistindex;
+ vmpolygons_t* polys = vmpolygons + PRVM_GetProgNr();
+
// LordHavoc: FIXME: this is stupid code
for (surfacelistindex = 0;surfacelistindex < numsurfaces;surfacelistindex++)
{
- const vm_polygon_t *p = &vm_polygons[surfacelist[surfacelistindex]];
+ const vm_polygon_t *p = &polys->polygons[surfacelist[surfacelistindex]];
int flags = p->flags & 0x0f;
if(flags == DRAWFLAG_ADDITIVE)
{
drawqueuemesh_t mesh;
static int picelements[6] = {0, 1, 2, 0, 2, 3};
-
mesh.texture = p->tex;
mesh.data_element3i = picelements;
mesh.data_vertex3f = p->data;
void VM_CL_AddPolygonsToMeshQueue (void)
{
int i;
- if(!vm_drawpolygons_num)
+ vmpolygons_t* polys = vmpolygons + PRVM_GetProgNr();
+
+ if(!polys->drawpolygons_num)
return;
R_Mesh_Matrix(&identitymatrix);
GL_CullFace(GL_NONE);
- for(i = 0;i < (int)vm_drawpolygons_num;i++)
+ for(i = 0;i < (int)polys->drawpolygons_num;i++)
VM_DrawPolygonCallback(NULL, NULL, 1, &i);
- vm_drawpolygons_num = 0;
+ polys->drawpolygons_num = 0;
}
//void(string texturename, float flag[, float 2d[, float lines]]) R_BeginPolygon
-static void VM_CL_R_PolygonBegin (void)
+void VM_CL_R_PolygonBegin (void)
{
vm_polygon_t *p;
const char *picname;
+ vmpolygons_t* polys = vmpolygons + PRVM_GetProgNr();
+
VM_SAFEPARMCOUNTRANGE(2, 4, VM_CL_R_PolygonBegin);
- if(!vm_polygons_initialized)
- VM_InitPolygons();
- if(vm_polygonbegin)
+ if(!polys->initialized)
+ VM_InitPolygons(polys);
+ if(polys->polygonbegin)
{
VM_Warning("VM_CL_R_PolygonBegin: called twice without VM_CL_R_PolygonEnd after first\n");
return;
}
- if(vm_drawpolygons_num >= vm_polygons_num)
+ if(polys->drawpolygons_num >= polys->polygons_num)
{
- p = (vm_polygon_t *)Mem_Alloc(vm_polygons_pool, 2 * vm_polygons_num * sizeof(vm_polygon_t));
- memset(p, 0, 2 * vm_polygons_num * sizeof(vm_polygon_t));
- memcpy(p, vm_polygons, vm_polygons_num * sizeof(vm_polygon_t));
- Mem_Free(vm_polygons);
- vm_polygons = p;
- vm_polygons_num *= 2;
+ p = (vm_polygon_t *)Mem_Alloc(polys->pool, 2 * polys->polygons_num * sizeof(vm_polygon_t));
+ memset(p, 0, 2 * polys->polygons_num * sizeof(vm_polygon_t));
+ memcpy(p, polys->polygons, polys->polygons_num * sizeof(vm_polygon_t));
+ Mem_Free(polys->polygons);
+ polys->polygons = p;
+ polys->polygons_num *= 2;
}
- p = &vm_polygons[vm_drawpolygons_num];
+ p = &polys->polygons[polys->drawpolygons_num];
picname = PRVM_G_STRING(OFS_PARM0);
if(picname[0])
p->tex = Draw_CachePic(picname, true)->tex;
else
p->tex = r_texture_white;
p->flags = (unsigned char)PRVM_G_FLOAT(OFS_PARM1);
- vm_current_vertices = 0;
- vm_polygonbegin = true;
+ polys->current_vertices = 0;
+ polys->polygonbegin = true;
if(prog->argc >= 3)
{
if(PRVM_G_FLOAT(OFS_PARM2))
}
//void(vector org, vector texcoords, vector rgb, float alpha) R_PolygonVertex
-static void VM_CL_R_PolygonVertex (void)
+void VM_CL_R_PolygonVertex (void)
{
float *coords, *tx, *rgb, alpha;
vm_polygon_t *p;
+ vmpolygons_t* polys = vmpolygons + PRVM_GetProgNr();
+
VM_SAFEPARMCOUNT(4, VM_CL_R_PolygonVertex);
- if(!vm_polygonbegin)
+ if(!polys->polygonbegin)
{
VM_Warning("VM_CL_R_PolygonVertex: VM_CL_R_PolygonBegin wasn't called\n");
return;
rgb = PRVM_G_VECTOR(OFS_PARM2);
alpha = PRVM_G_FLOAT(OFS_PARM3);
- p = &vm_polygons[vm_drawpolygons_num];
- if(vm_current_vertices > 4)
+ p = &polys->polygons[polys->drawpolygons_num];
+ if(polys->current_vertices > 4)
{
VM_Warning("VM_CL_R_PolygonVertex: may have 4 vertices max\n");
return;
}
- p->data[vm_current_vertices*3] = coords[0];
- p->data[1+vm_current_vertices*3] = coords[1];
- p->data[2+vm_current_vertices*3] = coords[2];
+ p->data[polys->current_vertices*3] = coords[0];
+ p->data[1+polys->current_vertices*3] = coords[1];
+ p->data[2+polys->current_vertices*3] = coords[2];
- p->data[12+vm_current_vertices*2] = tx[0];
+ p->data[12+polys->current_vertices*2] = tx[0];
if(!(p->flags & VM_POLYGON_FLLINES))
- p->data[13+vm_current_vertices*2] = tx[1];
+ p->data[13+polys->current_vertices*2] = tx[1];
- p->data[20+vm_current_vertices*4] = rgb[0];
- p->data[21+vm_current_vertices*4] = rgb[1];
- p->data[22+vm_current_vertices*4] = rgb[2];
- p->data[23+vm_current_vertices*4] = alpha;
+ p->data[20+polys->current_vertices*4] = rgb[0];
+ p->data[21+polys->current_vertices*4] = rgb[1];
+ p->data[22+polys->current_vertices*4] = rgb[2];
+ p->data[23+polys->current_vertices*4] = alpha;
- vm_current_vertices++;
- if(vm_current_vertices == 4)
+ polys->current_vertices++;
+ if(polys->current_vertices == 4)
p->flags |= VM_POLYGON_FL4V;
else
- if(vm_current_vertices == 3)
+ if(polys->current_vertices == 3)
p->flags |= VM_POLYGON_FL3V;
}
//void() R_EndPolygon
-static void VM_CL_R_PolygonEnd (void)
+void VM_CL_R_PolygonEnd (void)
{
+ vmpolygons_t* polys = vmpolygons + PRVM_GetProgNr();
+
VM_SAFEPARMCOUNT(0, VM_CL_R_PolygonEnd);
- if(!vm_polygonbegin)
+ if(!polys->polygonbegin)
{
VM_Warning("VM_CL_R_PolygonEnd: VM_CL_R_PolygonBegin wasn't called\n");
return;
}
- vm_polygonbegin = false;
- if(vm_current_vertices > 2 || (vm_current_vertices >= 2 && vm_polygons[vm_drawpolygons_num].flags & VM_POLYGON_FLLINES))
+ polys->polygonbegin = false;
+ if(polys->current_vertices > 2 || (polys->current_vertices >= 2 && polys->polygons[polys->drawpolygons_num].flags & VM_POLYGON_FLLINES))
{
- if(vm_polygons[vm_drawpolygons_num].flags & VM_POLYGON_FL2D) //[515]: don't use qcpolygons memory if 2D
- VM_CL_AddPolygonTo2DScene(&vm_polygons[vm_drawpolygons_num]);
+ if(polys->polygons[polys->drawpolygons_num].flags & VM_POLYGON_FL2D) //[515]: don't use qcpolygons memory if 2D
+ VM_CL_AddPolygonTo2DScene(&polys->polygons[polys->drawpolygons_num]);
else
- vm_drawpolygons_num++;
+ polys->drawpolygons_num++;
}
else
- VM_Warning("VM_CL_R_PolygonEnd: %i vertices isn't a good choice\n", vm_current_vertices);
+ VM_Warning("VM_CL_R_PolygonEnd: %i vertices isn't a good choice\n", polys->current_vertices);
}
+static vmpolygons_t debugPolys;
+
void Debug_PolygonBegin(const char *picname, int flags, qboolean draw2d, float linewidth)
{
vm_polygon_t *p;
- if(!vm_polygons_initialized)
- VM_InitPolygons();
- if(vm_polygonbegin)
+ if(!debugPolys.initialized)
+ VM_InitPolygons(&debugPolys);
+ if(debugPolys.polygonbegin)
{
Con_Printf("Debug_PolygonBegin: called twice without Debug_PolygonEnd after first\n");
return;
}
// limit polygons to a vaguely sane amount, beyond this each one just
// replaces the last one
- vm_drawpolygons_num = min(vm_drawpolygons_num, (1<<20)-1);
- if(vm_drawpolygons_num >= vm_polygons_num)
+ debugPolys.drawpolygons_num = min(debugPolys.drawpolygons_num, (1<<20)-1);
+ if(debugPolys.drawpolygons_num >= debugPolys.polygons_num)
{
- p = (vm_polygon_t *)Mem_Alloc(vm_polygons_pool, 2 * vm_polygons_num * sizeof(vm_polygon_t));
- memset(p, 0, 2 * vm_polygons_num * sizeof(vm_polygon_t));
- memcpy(p, vm_polygons, vm_polygons_num * sizeof(vm_polygon_t));
- Mem_Free(vm_polygons);
- vm_polygons = p;
- vm_polygons_num *= 2;
+ p = (vm_polygon_t *)Mem_Alloc(debugPolys.pool, 2 * debugPolys.polygons_num * sizeof(vm_polygon_t));
+ memset(p, 0, 2 * debugPolys.polygons_num * sizeof(vm_polygon_t));
+ memcpy(p, debugPolys.polygons, debugPolys.polygons_num * sizeof(vm_polygon_t));
+ Mem_Free(debugPolys.polygons);
+ debugPolys.polygons = p;
+ debugPolys.polygons_num *= 2;
}
- p = &vm_polygons[vm_drawpolygons_num];
+ p = &debugPolys.polygons[debugPolys.drawpolygons_num];
if(picname && picname[0])
p->tex = Draw_CachePic(picname, true)->tex;
else
p->tex = r_texture_white;
p->flags = flags;
- vm_current_vertices = 0;
- vm_polygonbegin = true;
+ debugPolys.current_vertices = 0;
+ debugPolys.polygonbegin = true;
if(draw2d)
p->flags |= VM_POLYGON_FL2D;
if(linewidth)
{
vm_polygon_t *p;
- if(!vm_polygonbegin)
+ if(!debugPolys.polygonbegin)
{
Con_Printf("Debug_PolygonVertex: Debug_PolygonBegin wasn't called\n");
return;
}
- p = &vm_polygons[vm_drawpolygons_num];
- if(vm_current_vertices > 4)
+ p = &debugPolys.polygons[debugPolys.drawpolygons_num];
+ if(debugPolys.current_vertices > 4)
{
Con_Printf("Debug_PolygonVertex: may have 4 vertices max\n");
return;
}
- p->data[vm_current_vertices*3] = x;
- p->data[1+vm_current_vertices*3] = y;
- p->data[2+vm_current_vertices*3] = z;
+ p->data[debugPolys.current_vertices*3] = x;
+ p->data[1+debugPolys.current_vertices*3] = y;
+ p->data[2+debugPolys.current_vertices*3] = z;
- p->data[12+vm_current_vertices*2] = s;
+ p->data[12+debugPolys.current_vertices*2] = s;
if(!(p->flags & VM_POLYGON_FLLINES))
- p->data[13+vm_current_vertices*2] = t;
+ p->data[13+debugPolys.current_vertices*2] = t;
- p->data[20+vm_current_vertices*4] = r;
- p->data[21+vm_current_vertices*4] = g;
- p->data[22+vm_current_vertices*4] = b;
- p->data[23+vm_current_vertices*4] = a;
+ p->data[20+debugPolys.current_vertices*4] = r;
+ p->data[21+debugPolys.current_vertices*4] = g;
+ p->data[22+debugPolys.current_vertices*4] = b;
+ p->data[23+debugPolys.current_vertices*4] = a;
- vm_current_vertices++;
- if(vm_current_vertices == 4)
+ debugPolys.current_vertices++;
+ if(debugPolys.current_vertices == 4)
p->flags |= VM_POLYGON_FL4V;
else
- if(vm_current_vertices == 3)
+ if(debugPolys.current_vertices == 3)
p->flags |= VM_POLYGON_FL3V;
}
void Debug_PolygonEnd(void)
{
- if(!vm_polygonbegin)
+ if(!debugPolys.polygonbegin)
{
Con_Printf("Debug_PolygonEnd: Debug_PolygonBegin wasn't called\n");
return;
}
- vm_polygonbegin = false;
- if(vm_current_vertices > 2 || (vm_current_vertices >= 2 && vm_polygons[vm_drawpolygons_num].flags & VM_POLYGON_FLLINES))
+ debugPolys.polygonbegin = false;
+ if(debugPolys.current_vertices > 2 || (debugPolys.current_vertices >= 2 && debugPolys.polygons[debugPolys.drawpolygons_num].flags & VM_POLYGON_FLLINES))
{
- if(vm_polygons[vm_drawpolygons_num].flags & VM_POLYGON_FL2D) //[515]: don't use qcpolygons memory if 2D
- VM_CL_AddPolygonTo2DScene(&vm_polygons[vm_drawpolygons_num]);
+ if(debugPolys.polygons[debugPolys.drawpolygons_num].flags & VM_POLYGON_FL2D) //[515]: don't use qcpolygons memory if 2D
+ VM_CL_AddPolygonTo2DScene(&debugPolys.polygons[debugPolys.drawpolygons_num]);
else
- vm_drawpolygons_num++;
+ debugPolys.drawpolygons_num++;
}
else
- Con_Printf("Debug_PolygonEnd: %i vertices isn't a good choice\n", vm_current_vertices);
+ Con_Printf("Debug_PolygonEnd: %i vertices isn't a good choice\n", debugPolys.current_vertices);
}
/*
VM_CL_R_PolygonBegin, // #306 void(string texturename, float flag[, float is2d, float lines]) R_BeginPolygon
VM_CL_R_PolygonVertex, // #307 void(vector org, vector texcoords, vector rgb, float alpha) R_PolygonVertex
VM_CL_R_PolygonEnd, // #308 void() R_EndPolygon
-NULL, // #309
+NULL /* R_LoadWorldModel in menu VM, should stay unassigned in client*/, // #309
VM_CL_unproject, // #310 vector (vector v) cs_unproject (EXT_CSQC)
VM_CL_project, // #311 vector (vector v) cs_project (EXT_CSQC)
NULL, // #312
const int vm_cl_numbuiltins = sizeof(vm_cl_builtins) / sizeof(prvm_builtin_t);
-void VM_CL_Cmd_Init(void)
+void VM_Polygons_Reset(void)
{
- VM_Cmd_Init();
+ vmpolygons_t* polys = vmpolygons + PRVM_GetProgNr();
+
// TODO: replace vm_polygons stuff with a more general debugging polygon system, and make vm_polygons functions use that system
- if(vm_polygons_initialized)
+ if(polys->initialized)
{
- Mem_FreePool(&vm_polygons_pool);
- vm_polygons_initialized = false;
+ Mem_FreePool(&polys->pool);
+ polys->initialized = false;
}
}
+void VM_CL_Cmd_Init(void)
+{
+ VM_Cmd_Init();
+ VM_Polygons_Reset();
+ renderscenes[PRVM_CLIENTPROG] = &client_scene;
+}
+
void VM_CL_Cmd_Reset(void)
{
VM_Cmd_Reset();
- if(vm_polygons_initialized)
- {
- Mem_FreePool(&vm_polygons_pool);
- vm_polygons_initialized = false;
- }
+ VM_Polygons_Reset();
}
+