Add CSQC rendering support to the menu (uses the same interface as the CSQC VM).
authorblack <black@d7cf8633-e32d-0410-b094-e92efae38249>
Sat, 5 Jan 2008 22:46:48 +0000 (22:46 +0000)
committerblack <black@d7cf8633-e32d-0410-b094-e92efae38249>
Sat, 5 Jan 2008 22:46:48 +0000 (22:46 +0000)
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
client.h
clvm_cmds.c
clvm_cmds.h
csprogs.c
menu.c
menu.h
mvm_cmds.c

index 3b659c5..17ccc17 100644 (file)
--- 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 ();
 
 //
index bc1952f..3779389 100644 (file)
--- 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;
index c077f28..0f1e5be 100644 (file)
@@ -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();
 }
 
+
index 58928c2..8ec5774 100644 (file)
@@ -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__ */
index 995c0ed..8627ea8 100644 (file)
--- 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 2946796..ec46530 100644 (file)
--- 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 8583334..0e52ef4 100644 (file)
--- 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);
index 11d0ddc..1509c1b 100644 (file)
@@ -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();
 }