From c0df2977521335251d0c84ca87ec47bfdfde4065 Mon Sep 17 00:00:00 2001 From: black Date: Sat, 5 Jan 2008 22:46:48 +0000 Subject: [PATCH] Add CSQC rendering support to the menu (uses the same interface as the CSQC VM). Move temp entities to the renderer code (because only temporary render entities are needed). Rework the polygon code to support multiple VMs. Credits and thanks to res2k (and me ;)). git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@7922 d7cf8633-e32d-0410-b094-e92efae38249 --- cl_main.c | 100 ++++++++++----------- client.h | 10 ++- clvm_cmds.c | 252 +++++++++++++++++++++++++++------------------------- clvm_cmds.h | 21 +++++ csprogs.c | 68 +++++++------- menu.c | 16 ++++ menu.h | 1 + mvm_cmds.c | 58 +++++++++--- 8 files changed, 306 insertions(+), 220 deletions(-) diff --git a/cl_main.c b/cl_main.c index 3b659c59..17ccc17a 100644 --- a/cl_main.c +++ b/cl_main.c @@ -124,13 +124,11 @@ void CL_ClearState(void) cl.num_entities = 0; cl.num_static_entities = 0; - cl.num_temp_entities = 0; cl.num_brushmodel_entities = 0; // tweak these if the game runs out cl.max_entities = 256; cl.max_static_entities = 256; - cl.max_temp_entities = 512; cl.max_effects = 256; cl.max_beams = 256; cl.max_dlights = MAX_DLIGHTS; @@ -156,7 +154,6 @@ void CL_ClearState(void) cl.entities = (entity_t *)Mem_Alloc(cls.levelmempool, cl.max_entities * sizeof(entity_t)); cl.entities_active = (unsigned char *)Mem_Alloc(cls.levelmempool, cl.max_brushmodel_entities * sizeof(unsigned char)); cl.static_entities = (entity_t *)Mem_Alloc(cls.levelmempool, cl.max_static_entities * sizeof(entity_t)); - cl.temp_entities = (entity_t *)Mem_Alloc(cls.levelmempool, cl.max_temp_entities * sizeof(entity_t)); cl.effects = (cl_effect_t *)Mem_Alloc(cls.levelmempool, cl.max_effects * sizeof(cl_effect_t)); cl.beams = (beam_t *)Mem_Alloc(cls.levelmempool, cl.max_beams * sizeof(beam_t)); cl.dlights = (dlight_t *)Mem_Alloc(cls.levelmempool, cl.max_dlights * sizeof(dlight_t)); @@ -607,24 +604,24 @@ static float CL_LerpPoint(void) void CL_ClearTempEntities (void) { - cl.num_temp_entities = 0; + r_refdef.numtempentities = 0; } -entity_t *CL_NewTempEntity(void) +entity_render_t *CL_NewTempEntity(void) { - entity_t *ent; + entity_render_t *render; if (r_refdef.numentities >= r_refdef.maxentities) return NULL; - if (cl.num_temp_entities >= cl.max_temp_entities) + if (r_refdef.numtempentities >= r_refdef.maxtempentities) return NULL; - ent = &cl.temp_entities[cl.num_temp_entities++]; - memset (ent, 0, sizeof(*ent)); - r_refdef.entities[r_refdef.numentities++] = &ent->render; + render = &r_refdef.tempentities[r_refdef.numtempentities++]; + memset (render, 0, sizeof(*render)); + r_refdef.entities[r_refdef.numentities++] = render; - ent->render.alpha = 1; - VectorSet(ent->render.colormod, 1, 1, 1); - return ent; + render->alpha = 1; + VectorSet(render->colormod, 1, 1, 1); + return render; } void CL_Effect(vec3_t org, int modelindex, int startframe, int framecount, float framerate) @@ -797,7 +794,7 @@ void CL_RelinkLightFlashes(void) void CL_AddQWCTFFlagModel(entity_t *player, int skin) { float f; - entity_t *flag; + entity_render_t *flagrender; matrix4x4_t flagmatrix; // this code taken from QuakeWorld @@ -832,18 +829,18 @@ void CL_AddQWCTFFlagModel(entity_t *player, int skin) } // end of code taken from QuakeWorld - flag = CL_NewTempEntity(); - if (!flag) + flagrender = CL_NewTempEntity(); + if (!flagrender) return; - flag->render.model = cl.model_precache[cl.qw_modelindex_flag]; - flag->render.skinnum = skin; - flag->render.alpha = 1; - VectorSet(flag->render.colormod, 1, 1, 1); + flagrender->model = cl.model_precache[cl.qw_modelindex_flag]; + flagrender->skinnum = skin; + flagrender->alpha = 1; + VectorSet(flagrender->colormod, 1, 1, 1); // attach the flag to the player matrix Matrix4x4_CreateFromQuakeEntity(&flagmatrix, -f, -22, 0, 0, 0, -45, 1); - Matrix4x4_Concat(&flag->render.matrix, &player->render.matrix, &flagmatrix); - CL_UpdateRenderEntity(&flag->render); + Matrix4x4_Concat(&flagrender->matrix, &player->render.matrix, &flagmatrix); + CL_UpdateRenderEntity(flagrender); } matrix4x4_t viewmodelmatrix; @@ -1513,7 +1510,7 @@ static void CL_RelinkEffects(void) { int i, intframe; cl_effect_t *e; - entity_t *ent; + entity_render_t *entrender; float frame; for (i = 0, e = cl.effects;i < cl.num_effects;i++, e++) @@ -1539,27 +1536,27 @@ static void CL_RelinkEffects(void) // if we're drawing effects, get a new temp entity // (NewTempEntity adds it to the render entities list for us) - if (r_draweffects.integer && (ent = CL_NewTempEntity())) + if (r_draweffects.integer && (entrender = CL_NewTempEntity())) { // interpolation stuff - ent->render.frame1 = intframe; - ent->render.frame2 = intframe + 1; - if (ent->render.frame2 >= e->endframe) - ent->render.frame2 = -1; // disappear - ent->render.framelerp = frame - intframe; - ent->render.frame1time = e->frame1time; - ent->render.frame2time = e->frame2time; + entrender->frame1 = intframe; + entrender->frame2 = intframe + 1; + if (entrender->frame2 >= e->endframe) + entrender->frame2 = -1; // disappear + entrender->framelerp = frame - intframe; + entrender->frame1time = e->frame1time; + entrender->frame2time = e->frame2time; // normal stuff if(e->modelindex < MAX_MODELS) - ent->render.model = cl.model_precache[e->modelindex]; + entrender->model = cl.model_precache[e->modelindex]; else - ent->render.model = cl.csqc_model_precache[-(e->modelindex+1)]; - ent->render.alpha = 1; - VectorSet(ent->render.colormod, 1, 1, 1); + entrender->model = cl.csqc_model_precache[-(e->modelindex+1)]; + entrender->alpha = 1; + VectorSet(entrender->colormod, 1, 1, 1); - Matrix4x4_CreateFromQuakeEntity(&ent->render.matrix, e->origin[0], e->origin[1], e->origin[2], 0, 0, 0, 1); - CL_UpdateRenderEntity(&ent->render); + Matrix4x4_CreateFromQuakeEntity(&entrender->matrix, e->origin[0], e->origin[1], e->origin[2], 0, 0, 0, 1); + CL_UpdateRenderEntity(entrender); } } } @@ -1604,7 +1601,7 @@ void CL_RelinkBeams(void) beam_t *b; vec3_t dist, org, start, end; float d; - entity_t *ent; + entity_render_t *entrender; double yaw, pitch; float forward; matrix4x4_t tempmatrix; @@ -1663,17 +1660,17 @@ void CL_RelinkBeams(void) d = VectorNormalizeLength(dist); while (d > 0) { - ent = CL_NewTempEntity (); - if (!ent) + entrender = CL_NewTempEntity (); + if (!entrender) return; //VectorCopy (org, ent->render.origin); - ent->render.model = b->model; + entrender->model = b->model; //ent->render.effects = EF_FULLBRIGHT; //ent->render.angles[0] = pitch; //ent->render.angles[1] = yaw; //ent->render.angles[2] = rand()%360; - Matrix4x4_CreateFromQuakeEntity(&ent->render.matrix, org[0], org[1], org[2], -pitch, yaw, lhrandom(0, 360), 1); - CL_UpdateRenderEntity(&ent->render); + Matrix4x4_CreateFromQuakeEntity(&entrender->matrix, org[0], org[1], org[2], -pitch, yaw, lhrandom(0, 360), 1); + CL_UpdateRenderEntity(entrender); VectorMA(org, 30, dist, org); d -= 30; } @@ -1687,7 +1684,7 @@ static void CL_RelinkQWNails(void) { int i; vec_t *v; - entity_t *ent; + entity_render_t *entrender; for (i = 0;i < cl.qw_num_nails;i++) { @@ -1695,16 +1692,16 @@ static void CL_RelinkQWNails(void) // if we're drawing effects, get a new temp entity // (NewTempEntity adds it to the render entities list for us) - if (!(ent = CL_NewTempEntity())) + if (!(entrender = CL_NewTempEntity())) continue; // normal stuff - ent->render.model = cl.model_precache[cl.qw_modelindex_spike]; - ent->render.alpha = 1; - VectorSet(ent->render.colormod, 1, 1, 1); + entrender->model = cl.model_precache[cl.qw_modelindex_spike]; + entrender->alpha = 1; + VectorSet(entrender->colormod, 1, 1, 1); - Matrix4x4_CreateFromQuakeEntity(&ent->render.matrix, v[0], v[1], v[2], v[3], v[4], v[5], 1); - CL_UpdateRenderEntity(&ent->render); + Matrix4x4_CreateFromQuakeEntity(&entrender->matrix, v[0], v[1], v[2], v[3], v[4], v[5], 1); + CL_UpdateRenderEntity(entrender); } } @@ -2233,6 +2230,9 @@ void CL_Init (void) r_refdef.maxentities = MAX_EDICTS + 256 + 512; r_refdef.entities = (entity_render_t **)Mem_Alloc(cls.permanentmempool, sizeof(entity_render_t *) * r_refdef.maxentities); + r_refdef.maxtempentities = 512; + r_refdef.tempentities = (entity_render_t *)Mem_Alloc(cls.permanentmempool, sizeof(entity_render_t) * r_refdef.maxtempentities); + CL_InitInput (); // diff --git a/client.h b/client.h index bc1952fc..37793899 100644 --- a/client.h +++ b/client.h @@ -921,7 +921,6 @@ typedef struct client_state_s int max_entities; int max_static_entities; - int max_temp_entities; int max_effects; int max_beams; int max_dlights; @@ -934,7 +933,6 @@ typedef struct client_state_s entity_t *entities; unsigned char *entities_active; entity_t *static_entities; - entity_t *temp_entities; cl_effect_t *effects; beam_t *beams; dlight_t *dlights; @@ -946,7 +944,6 @@ typedef struct client_state_s int num_entities; int num_static_entities; - int num_temp_entities; int num_brushmodel_entities; int num_effects; int num_beams; @@ -1168,7 +1165,7 @@ void CL_Beam_CalculatePositions (const beam_t *b, vec3_t start, vec3_t end); void CL_ClientMovement_Replay(void); void CL_ClearTempEntities (void); -entity_t *CL_NewTempEntity (void); +entity_render_t *CL_NewTempEntity (void); void CL_Effect(vec3_t org, int modelindex, int startframe, int framecount, float framerate); @@ -1464,6 +1461,11 @@ typedef struct r_refdef_s int numentities; int maxentities; + // field of temporary entities that is reset each (client) frame + entity_render_t *tempentities; + int numtempentities; + int maxtempentities; + // renderable dynamic lights rtlight_t lights[MAX_DLIGHTS]; int numlights; diff --git a/clvm_cmds.c b/clvm_cmds.c index c077f287..0f1e5be4 100644 --- a/clvm_cmds.c +++ b/clvm_cmds.c @@ -26,11 +26,6 @@ void CSQC_RelinkAllEntities (int drawmask); void CSQC_RelinkCSQCEntities (void); const char *Key_GetBind (int key); - - - - - // #1 void(vector ang) makevectors static void VM_CL_makevectors (void) { @@ -39,7 +34,7 @@ static void VM_CL_makevectors (void) } // #2 void(entity e, vector o) setorigin -static void VM_CL_setorigin (void) +void VM_CL_setorigin (void) { prvm_edict_t *e; float *org; @@ -62,7 +57,7 @@ static void VM_CL_setorigin (void) } // #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; @@ -339,7 +334,7 @@ static void VM_CL_tracetoss (void) // #20 void(string s) precache_model -static void VM_CL_precache_model (void) +void VM_CL_precache_model (void) { const char *name; int i; @@ -647,7 +642,7 @@ 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 @@ -678,7 +673,7 @@ static void VM_CL_R_ClearScene (void) //#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; @@ -707,14 +702,14 @@ static void VM_CL_R_AddEntities (void) } //#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; @@ -830,7 +825,7 @@ static void VM_CL_R_SetView (void) } //#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 @@ -841,7 +836,7 @@ static void VM_CL_R_RenderScene (void) } //#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; @@ -2239,13 +2234,17 @@ typedef struct 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) @@ -2253,24 +2252,26 @@ static qboolean vm_polygonbegin = false; //[515]: for "no-crap-on-the-screen" #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) @@ -2345,7 +2346,6 @@ static void VM_CL_AddPolygonTo2DScene (vm_polygon_t *p) { 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; @@ -2370,47 +2370,51 @@ static void VM_CL_AddPolygonTo2DScene (vm_polygon_t *p) 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)) @@ -2424,13 +2428,15 @@ static void VM_CL_R_PolygonBegin (void) } //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; @@ -2440,86 +2446,90 @@ static void VM_CL_R_PolygonVertex (void) 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) @@ -2533,57 +2543,57 @@ void Debug_PolygonVertex(float x, float y, float z, float s, float t, float r, f { 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); } /* @@ -3163,7 +3173,7 @@ VM_CL_R_AddDynamicLight, // #305 void(vector org, float radius, vector lightcol 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 @@ -3367,24 +3377,28 @@ NULL, // #499 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(); +} + 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(); } + diff --git a/clvm_cmds.h b/clvm_cmds.h index 58928c2f..8ec57742 100644 --- a/clvm_cmds.h +++ b/clvm_cmds.h @@ -3,4 +3,25 @@ int CL_GetTagMatrix (matrix4x4_t *out, prvm_edict_t *ent, int tagindex); +/* These are VM built-ins that originate in the client-side programs support + but are reused by the other programs (usually the menu). */ + +void VM_CL_setmodel (void); +void VM_CL_precache_model (void); +void VM_CL_setorigin (void); + +void VM_CL_R_AddDynamicLight (void); +void VM_CL_R_ClearScene (void); +void VM_CL_R_AddEntities (void); +void VM_CL_R_AddEntity (void); +void VM_CL_R_SetView (void); +void VM_CL_R_RenderScene (void); +void VM_CL_R_LoadWorldModel (void); + +void VM_CL_R_PolygonBegin (void); +void VM_CL_R_PolygonVertex (void); +void VM_CL_R_PolygonEnd (void); +/* VMs exposing the polygon calls must call this on Init/Reset */ +void VM_Polygons_Reset(); + #endif /* __CLVM_CMDS_H__ */ diff --git a/csprogs.c b/csprogs.c index 995c0ed1..8627ea8f 100644 --- a/csprogs.c +++ b/csprogs.c @@ -129,7 +129,7 @@ qboolean CSQC_AddRenderEdict(prvm_edict_t *ed) int c; float scale; prvm_eval_t *val; - entity_t *e; + entity_render_t *entrender; model_t *model; matrix4x4_t tagmatrix, matrix2; @@ -137,20 +137,20 @@ qboolean CSQC_AddRenderEdict(prvm_edict_t *ed) if (!model) return false; - e = CL_NewTempEntity(); - if (!e) + entrender = CL_NewTempEntity(); + if (!entrender) return false; - e->render.model = model; - e->render.skinnum = (int)ed->fields.client->skin; - e->render.effects |= e->render.model->effects; + entrender->model = model; + entrender->skinnum = (int)ed->fields.client->skin; + entrender->effects |= entrender->model->effects; scale = 1; renderflags = 0; if((val = PRVM_EDICTFIELDVALUE(ed, prog->fieldoffsets.renderflags)) && val->_float) renderflags = (int)val->_float; - if((val = PRVM_EDICTFIELDVALUE(ed, prog->fieldoffsets.alpha)) && val->_float) e->render.alpha = val->_float; - if((val = PRVM_EDICTFIELDVALUE(ed, prog->fieldoffsets.scale)) && val->_float) e->render.scale = scale = val->_float; - if((val = PRVM_EDICTFIELDVALUE(ed, prog->fieldoffsets.colormod)) && VectorLength2(val->vector)) VectorCopy(val->vector, e->render.colormod); - if((val = PRVM_EDICTFIELDVALUE(ed, prog->fieldoffsets.effects)) && val->_float) e->render.effects |= (int)val->_float; + if((val = PRVM_EDICTFIELDVALUE(ed, prog->fieldoffsets.alpha)) && val->_float) entrender->alpha = val->_float; + if((val = PRVM_EDICTFIELDVALUE(ed, prog->fieldoffsets.scale)) && val->_float) entrender->scale = scale = val->_float; + if((val = PRVM_EDICTFIELDVALUE(ed, prog->fieldoffsets.colormod)) && VectorLength2(val->vector)) VectorCopy(val->vector, entrender->colormod); + if((val = PRVM_EDICTFIELDVALUE(ed, prog->fieldoffsets.effects)) && val->_float) entrender->effects |= (int)val->_float; if((val = PRVM_EDICTFIELDVALUE(ed, prog->fieldoffsets.tag_entity)) && val->edict) { int tagentity; @@ -175,7 +175,7 @@ qboolean CSQC_AddRenderEdict(prvm_edict_t *ed) vec3_t angles; VectorCopy(ed->fields.client->angles, angles); // if model is alias, reverse pitch direction - if (e->render.model->type == mod_alias) + if (entrender->model->type == mod_alias) angles[0] = -angles[0]; // set up the render matrix @@ -187,45 +187,45 @@ qboolean CSQC_AddRenderEdict(prvm_edict_t *ed) // self.frame1time is the animation base time for the interpolation target // self.frame2 is the interpolation start (previous frame) // self.frame2time is the animation base time for the interpolation start - e->render.frame1 = e->render.frame2 = ed->fields.client->frame; - if ((val = PRVM_EDICTFIELDVALUE(ed, prog->fieldoffsets.frame2))) e->render.frame2 = val->_float; - if ((val = PRVM_EDICTFIELDVALUE(ed, prog->fieldoffsets.frame1time))) e->render.frame2time = val->_float; - if ((val = PRVM_EDICTFIELDVALUE(ed, prog->fieldoffsets.frame2time))) e->render.frame1time = val->_float; - if ((val = PRVM_EDICTFIELDVALUE(ed, prog->fieldoffsets.lerpfrac))) e->render.framelerp = val->_float; + entrender->frame1 = entrender->frame2 = ed->fields.client->frame; + if ((val = PRVM_EDICTFIELDVALUE(ed, prog->fieldoffsets.frame2))) entrender->frame2 = val->_float; + if ((val = PRVM_EDICTFIELDVALUE(ed, prog->fieldoffsets.frame1time))) entrender->frame2time = val->_float; + if ((val = PRVM_EDICTFIELDVALUE(ed, prog->fieldoffsets.frame2time))) entrender->frame1time = val->_float; + if ((val = PRVM_EDICTFIELDVALUE(ed, prog->fieldoffsets.lerpfrac))) entrender->framelerp = val->_float; // concat the matrices to make the entity relative to its tag - Matrix4x4_Concat(&e->render.matrix, &tagmatrix, &matrix2); + Matrix4x4_Concat(&entrender->matrix, &tagmatrix, &matrix2); if(renderflags) { - if(renderflags & RF_VIEWMODEL) e->render.flags |= RENDER_VIEWMODEL; - if(renderflags & RF_EXTERNALMODEL)e->render.flags |= RENDER_EXTERIORMODEL; - if(renderflags & RF_DEPTHHACK) e->render.effects |= EF_NODEPTHTEST; - if(renderflags & RF_ADDITIVE) e->render.effects |= EF_ADDITIVE; + if(renderflags & RF_VIEWMODEL) entrender->flags |= RENDER_VIEWMODEL; + if(renderflags & RF_EXTERNALMODEL)entrender->flags |= RENDER_EXTERIORMODEL; + if(renderflags & RF_DEPTHHACK) entrender->effects |= EF_NODEPTHTEST; + if(renderflags & RF_ADDITIVE) entrender->effects |= EF_ADDITIVE; } c = (int)ed->fields.client->colormap; if (c <= 0) - CL_SetEntityColormapColors(&e->render, -1); + CL_SetEntityColormapColors(entrender, -1); else if (c <= cl.maxclients && cl.scores != NULL) - CL_SetEntityColormapColors(&e->render, cl.scores[c-1].colors); + CL_SetEntityColormapColors(entrender, cl.scores[c-1].colors); else - CL_SetEntityColormapColors(&e->render, c); + CL_SetEntityColormapColors(entrender, c); // either fullbright or lit - if (!(e->render.effects & EF_FULLBRIGHT) && !r_fullbright.integer) - e->render.flags |= RENDER_LIGHT; + if (!(entrender->effects & EF_FULLBRIGHT) && !r_fullbright.integer) + entrender->flags |= RENDER_LIGHT; // hide player shadow during intermission or nehahra movie - if (!(e->render.effects & (EF_NOSHADOW | EF_ADDITIVE | EF_NODEPTHTEST)) - && (e->render.alpha >= 1) - && !(e->render.flags & RENDER_VIEWMODEL) - && (!(e->render.flags & RENDER_EXTERIORMODEL) || (!cl.intermission && cls.protocol != PROTOCOL_NEHAHRAMOVIE && !cl_noplayershadow.integer))) - e->render.flags |= RENDER_SHADOW; - if (e->render.flags & RENDER_VIEWMODEL) - e->render.flags |= RENDER_NOSELFSHADOW; + if (!(entrender->effects & (EF_NOSHADOW | EF_ADDITIVE | EF_NODEPTHTEST)) + && (entrender->alpha >= 1) + && !(entrender->flags & RENDER_VIEWMODEL) + && (!(entrender->flags & RENDER_EXTERIORMODEL) || (!cl.intermission && cls.protocol != PROTOCOL_NEHAHRAMOVIE && !cl_noplayershadow.integer))) + entrender->flags |= RENDER_SHADOW; + if (entrender->flags & RENDER_VIEWMODEL) + entrender->flags |= RENDER_NOSELFSHADOW; // make the other useful stuff - CL_UpdateRenderEntity(&e->render); + CL_UpdateRenderEntity(entrender); return true; } diff --git a/menu.c b/menu.c index 29467965..ec465305 100644 --- a/menu.c +++ b/menu.c @@ -5070,12 +5070,28 @@ void MP_KeyEvent (int key, char ascii, qboolean downevent) void MP_Draw (void) { + extern r_refdef_t menu_refdef; + + static r_refdef_t clientrefdef; + clientrefdef = r_refdef; + r_refdef = menu_refdef; + + // reset the temp entities each frame + r_refdef.numtempentities = 0; + + R_UpdateVariables(); + PRVM_Begin; PRVM_SetProg(PRVM_MENUPROG); + // FIXME: this really shouldnt error out lest we have a very broken refdef state...? + // or does it kill the server too? PRVM_ExecuteProgram(prog->funcoffsets.m_draw,"m_draw() required"); PRVM_End; + + menu_refdef = r_refdef; + r_refdef = clientrefdef; } void MP_ToggleMenu_f (void) diff --git a/menu.h b/menu.h index 85833341..0e52ef4a 100644 --- a/menu.h +++ b/menu.h @@ -76,6 +76,7 @@ void MP_Shutdown (void);*/ // // menu router // + void MR_Init_Commands (void); void MR_Init (void); void MR_Restart (void); diff --git a/mvm_cmds.c b/mvm_cmds.c index 11d0ddc9..1509c1b9 100644 --- a/mvm_cmds.c +++ b/mvm_cmds.c @@ -1,6 +1,7 @@ #include "quakedef.h" #include "prvm_cmds.h" +#include "clvm_cmds.h" #include "menu.h" //============================================================================ @@ -23,6 +24,7 @@ char *vm_m_extensions = #ifdef SUPPORT_GECKO "DP_GECKO_SUPPORT " #endif +"DP_QC_RENDER_SCENE" ; /* @@ -872,9 +874,9 @@ VM_altstr_ins, // #86 VM_findflags, // #87 VM_findchainflags, // #88 VM_cvar_defstring, // #89 -NULL, // #90 -NULL, // #91 -NULL, // #92 +VM_CL_setmodel, // #90 void(entity e, string m) setmodel (QUAKE) +VM_CL_precache_model, // #91 void(string s) precache_model (QUAKE) +VM_CL_setorigin, // #92 void(entity e, vector o) setorigin (QUAKE) NULL, // #93 NULL, // #94 NULL, // #95 @@ -1082,16 +1084,17 @@ NULL, // #296 NULL, // #297 NULL, // #298 NULL, // #299 -NULL, // #300 -NULL, // #301 -NULL, // #302 -NULL, // #303 -NULL, // #304 -NULL, // #305 -NULL, // #306 -NULL, // #307 -NULL, // #308 -NULL, // #309 +// CSQC range #300-#399 +VM_CL_R_ClearScene, // #300 void() clearscene (DP_QC_RENDER_SCENE) +VM_CL_R_AddEntities, // #301 void(float mask) addentities (DP_QC_RENDER_SCENE) +VM_CL_R_AddEntity, // #302 void(entity ent) addentity (DP_QC_RENDER_SCENE) +VM_CL_R_SetView, // #303 float(float property, ...) setproperty (DP_QC_RENDER_SCENE) +VM_CL_R_RenderScene, // #304 void() renderscene (DP_QC_RENDER_SCENE) +VM_CL_R_AddDynamicLight, // #305 void(vector org, float radius, vector lightcolours) adddynamiclight (DP_QC_RENDER_SCENE) +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/*VM_CL_R_LoadWorldModel*/, // #309 void(string modelname) R_LoadWorldModel NULL, // #310 NULL, // #311 NULL, // #312 @@ -1421,13 +1424,42 @@ VM_M_getextresponse // #624 const int vm_m_numbuiltins = sizeof(vm_m_builtins) / sizeof(prvm_builtin_t); +r_refdef_t menu_refdef; + void VM_M_Cmd_Init(void) { VM_Cmd_Init(); + VM_Polygons_Reset(); + + memset (&menu_refdef, 0, sizeof (r_refdef_t)); + + menu_refdef.maxtempentities = 128; + menu_refdef.tempentities = (entity_render_t*) Mem_Alloc(prog->progs_mempool, sizeof(entity_render_t) * menu_refdef.maxtempentities); + + menu_refdef.frustumscale_x = 1; + menu_refdef.frustumscale_y = 1; + menu_refdef.maxentities = MAX_EDICTS + 256 + 512; + menu_refdef.entities = (entity_render_t **)Mem_Alloc(cls.permanentmempool, sizeof(entity_render_t *) * menu_refdef.maxentities); + + menu_refdef.view.width = vid.width; + menu_refdef.view.height = vid.height; + menu_refdef.view.depth = 1; + menu_refdef.view.x = 0; + menu_refdef.view.y = 0; + menu_refdef.view.z = 0; + menu_refdef.view.colormask[0] = true; + menu_refdef.view.colormask[1] = true; + menu_refdef.view.colormask[2] = true; + menu_refdef.view.colormask[3] = true; + + menu_refdef.view.useperspective = true; + menu_refdef.view.frustum_y = tan(scr_fov.value * M_PI / 360.0) * (3.0/4.0); + menu_refdef.view.frustum_x = menu_refdef.view.frustum_y * (float)menu_refdef.view.width / (float)menu_refdef.view.height / vid_pixelheight.value; } void VM_M_Cmd_Reset(void) { //VM_Cmd_Init(); VM_Cmd_Reset(); + VM_Polygons_Reset(); } -- 2.39.2