X-Git-Url: http://de.git.xonotic.org/?p=xonotic%2Fdarkplaces.git;a=blobdiff_plain;f=clvm_cmds.c;h=0d30689c41dd3cc00780318b5825d155ef4d7e3a;hp=b566f0521451c4bb055898eaf4f07f8fe1df5e4f;hb=971ad66cc21064832305abca4e356213dd513d9b;hpb=d8c070909c9525c027065995333c6a173413a956 diff --git a/clvm_cmds.c b/clvm_cmds.c index b566f052..0d30689c 100644 --- a/clvm_cmds.c +++ b/clvm_cmds.c @@ -4,6 +4,8 @@ #include "csprogs.h" #include "cl_collision.h" #include "r_shadow.h" +#include "jpeg.h" +#include "image.h" //============================================================================ // Client @@ -19,7 +21,7 @@ //4 feature darkplaces csqc: add builtins to clientside qc for gl calls sfx_t *S_FindName(const char *name); -int Sbar_GetPlayer (int index); +int Sbar_GetSortedPlayerIndex (int index); void Sbar_SortFrags (void); void CL_FindNonSolidLocation(const vec3_t in, vec3_t out, vec_t radius); void CSQC_RelinkAllEntities (int drawmask); @@ -77,45 +79,50 @@ void VM_CL_setmodel (void) { prvm_edict_t *e; const char *m; - model_t *mod; + dp_model_t *mod; int i; VM_SAFEPARMCOUNT(2, VM_CL_setmodel); e = PRVM_G_EDICT(OFS_PARM0); + e->fields.client->modelindex = 0; + e->fields.client->model = 0; + m = PRVM_G_STRING(OFS_PARM1); + mod = NULL; for (i = 0;i < MAX_MODELS && cl.csqc_model_precache[i];i++) { if (!strcmp(cl.csqc_model_precache[i]->name, m)) { - e->fields.client->model = PRVM_SetEngineString(cl.csqc_model_precache[i]->name); + mod = cl.csqc_model_precache[i]; + e->fields.client->model = PRVM_SetEngineString(mod->name); e->fields.client->modelindex = -(i+1); - return; + break; } } - for (i = 0;i < MAX_MODELS;i++) - { - mod = cl.model_precache[i]; - if (mod && !strcmp(mod->name, m)) + if( !mod ) { + for (i = 0;i < MAX_MODELS;i++) { - e->fields.client->model = PRVM_SetEngineString(mod->name); - e->fields.client->modelindex = i; - return; + mod = cl.model_precache[i]; + if (mod && !strcmp(mod->name, m)) + { + e->fields.client->model = PRVM_SetEngineString(mod->name); + e->fields.client->modelindex = i; + break; + } } } - e->fields.client->modelindex = 0; - e->fields.client->model = 0; - VM_Warning ("setmodel: model '%s' not precached\n", m); - - // TODO: check if this breaks needed consistency and maybe add a cvar for it too?? [1/10/2008 Black] - if (mod) - { - SetMinMaxSize (e, mod->normalmins, mod->normalmaxs); + if( mod ) { + // TODO: check if this breaks needed consistency and maybe add a cvar for it too?? [1/10/2008 Black] + //SetMinMaxSize (e, mod->normalmins, mod->normalmaxs); } else + { SetMinMaxSize (e, vec3_origin, vec3_origin); + VM_Warning ("setmodel: model '%s' not precached\n", m); + } } // #4 void(entity e, vector min, vector max) setsize @@ -358,7 +365,7 @@ void VM_CL_precache_model (void) { const char *name; int i; - model_t *m; + dp_model_t *m; VM_SAFEPARMCOUNT(1, VM_CL_precache_model); @@ -379,7 +386,7 @@ void VM_CL_precache_model (void) { if (!cl.csqc_model_precache[i]) { - cl.csqc_model_precache[i] = (model_t*)m; + cl.csqc_model_precache[i] = (dp_model_t*)m; PRVM_G_FLOAT(OFS_RETURN) = -(i+1); return; } @@ -684,6 +691,7 @@ void VM_CL_R_ClearScene (void) r_refdef.view.ortho_x = scr_fov.value * (3.0 / 4.0) * (float)r_refdef.view.width / (float)r_refdef.view.height / vid_pixelheight.value; r_refdef.view.ortho_y = scr_fov.value * (3.0 / 4.0); r_refdef.view.clear = true; + r_refdef.view.isoverlay = false; // FIXME: restore cl.csqc_origin // FIXME: restore cl.csqc_angles cl.csqc_vidvars.drawworld = true; @@ -745,31 +753,31 @@ void VM_CL_R_SetView (void) switch(c) { case VF_MIN: - r_refdef.view.x = (int)(f[0] * vid.width / vid_conwidth.value); - r_refdef.view.y = (int)(f[1] * vid.height / vid_conheight.value); + r_refdef.view.x = (int)(f[0]); + r_refdef.view.y = (int)(f[1]); break; case VF_MIN_X: - r_refdef.view.x = (int)(k * vid.width / vid_conwidth.value); + r_refdef.view.x = (int)(k); break; case VF_MIN_Y: - r_refdef.view.y = (int)(k * vid.height / vid_conheight.value); + r_refdef.view.y = (int)(k); break; case VF_SIZE: - r_refdef.view.width = (int)(f[0] * vid.width / vid_conwidth.value); - r_refdef.view.height = (int)(f[1] * vid.height / vid_conheight.value); - break; - case VF_SIZE_Y: - r_refdef.view.width = (int)(k * vid.width / vid_conwidth.value); + r_refdef.view.width = (int)(f[0]); + r_refdef.view.height = (int)(f[1]); break; case VF_SIZE_X: - r_refdef.view.height = (int)(k * vid.height / vid_conheight.value); + r_refdef.view.width = (int)(k); + break; + case VF_SIZE_Y: + r_refdef.view.height = (int)(k); break; case VF_VIEWPORT: - r_refdef.view.x = (int)(f[0] * vid.width / vid_conwidth.value); - r_refdef.view.y = (int)(f[1] * vid.height / vid_conheight.value); + r_refdef.view.x = (int)(f[0]); + r_refdef.view.y = (int)(f[1]); f = PRVM_G_VECTOR(OFS_PARM2); - r_refdef.view.width = (int)(f[0] * vid.width / vid_conwidth.value); - r_refdef.view.height = (int)(f[1] * vid.height / vid_conheight.value); + r_refdef.view.width = (int)(f[0]); + r_refdef.view.height = (int)(f[1]); break; case VF_FOV: r_refdef.view.frustum_x = tan(f[0] * M_PI / 360.0);r_refdef.view.ortho_x = f[0]; @@ -838,7 +846,7 @@ void VM_CL_R_SetView (void) r_refdef.view.useperspective = k != 0; break; case VF_CLEARSCREEN: - r_refdef.view.clear = k ? true : false; + r_refdef.view.isoverlay = !k; break; default: PRVM_G_FLOAT(OFS_RETURN) = 0; @@ -848,32 +856,54 @@ void VM_CL_R_SetView (void) PRVM_G_FLOAT(OFS_RETURN) = 1; } -//#304 void() renderscene (EXT_CSQC) -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 - // csqc supplies its own view matrix - CL_UpdateViewEntities(); - // now draw stuff! - R_RenderView(); -} - -//#305 void(vector org, float radius, vector lightcolours) adddynamiclight (EXT_CSQC) +//#305 void(vector org, float radius, vector lightcolours[, float style, string cubemapname, float pflags]) adddynamiclight (EXT_CSQC) void VM_CL_R_AddDynamicLight (void) { - float *pos, *col; - matrix4x4_t matrix; - VM_SAFEPARMCOUNTRANGE(3, 3, VM_CL_R_AddDynamicLight); + vec_t *org; + float radius = 300; + vec_t *col; + int style = -1; + const char *cubemapname = NULL; + int pflags = PFLAGS_CORONA | PFLAGS_FULLDYNAMIC; + float coronaintensity = 1; + float coronasizescale = 0.25; + qboolean castshadow = true; + float ambientscale = 0; + float diffusescale = 1; + float specularscale = 1; + matrix4x4_t matrix; + vec3_t forward, left, up; + VM_SAFEPARMCOUNTRANGE(3, 8, VM_CL_R_AddDynamicLight); // if we've run out of dlights, just return if (r_refdef.scene.numlights >= MAX_DLIGHTS) return; - pos = PRVM_G_VECTOR(OFS_PARM0); + org = PRVM_G_VECTOR(OFS_PARM0); + radius = PRVM_G_FLOAT(OFS_PARM1); col = PRVM_G_VECTOR(OFS_PARM2); - Matrix4x4_CreateFromQuakeEntity(&matrix, pos[0], pos[1], pos[2], 0, 0, 0, PRVM_G_FLOAT(OFS_PARM1)); - R_RTLight_Update(&r_refdef.scene.lights[r_refdef.scene.numlights++], false, &matrix, col, -1, NULL, true, 1, 0.25, 0, 1, 1, LIGHTFLAG_NORMALMODE | LIGHTFLAG_REALTIMEMODE); + if (prog->argc >= 4) + { + style = (int)PRVM_G_FLOAT(OFS_PARM3); + if (style >= MAX_LIGHTSTYLES) + { + Con_DPrintf("VM_CL_R_AddDynamicLight: out of bounds lightstyle index %i\n", style); + style = -1; + } + } + if (prog->argc >= 5) + cubemapname = PRVM_G_STRING(OFS_PARM4); + if (prog->argc >= 6) + pflags = (int)PRVM_G_FLOAT(OFS_PARM5); + coronaintensity = (pflags & PFLAGS_CORONA) != 0; + castshadow = (pflags & PFLAGS_NOSHADOW) == 0; + + VectorScale(prog->globals.client->v_forward, radius, forward); + VectorScale(prog->globals.client->v_right, -radius, left); + VectorScale(prog->globals.client->v_up, radius, up); + Matrix4x4_FromVectors(&matrix, forward, left, up, org); + + R_RTLight_Update(&r_refdef.scene.lights[r_refdef.scene.numlights++], false, &matrix, col, style, cubemapname, castshadow, coronaintensity, coronasizescale, ambientscale, diffusescale, specularscale, LIGHTFLAG_NORMALMODE | LIGHTFLAG_REALTIMEMODE); } //============================================================================ @@ -886,7 +916,7 @@ static void VM_CL_unproject (void) VM_SAFEPARMCOUNT(1, VM_CL_unproject); f = PRVM_G_VECTOR(OFS_PARM0); - VectorSet(temp, f[2], f[0] * f[2] * -r_refdef.view.frustum_x * 2.0 / r_refdef.view.width, f[1] * f[2] * -r_refdef.view.frustum_y * 2.0 / r_refdef.view.height); + VectorSet(temp, f[2], (-1.0 + 2.0 * (f[0] - r_refdef.view.x)) / r_refdef.view.width * f[2] * -r_refdef.view.frustum_x, (-1.0 + 2.0 * (f[1] - r_refdef.view.y)) / r_refdef.view.height * f[2] * -r_refdef.view.frustum_y); Matrix4x4_Transform(&r_refdef.view.matrix, temp, PRVM_G_VECTOR(OFS_RETURN)); } @@ -901,7 +931,7 @@ static void VM_CL_project (void) f = PRVM_G_VECTOR(OFS_PARM0); Matrix4x4_Invert_Simple(&m, &r_refdef.view.matrix); Matrix4x4_Transform(&m, f, v); - VectorSet(PRVM_G_VECTOR(OFS_RETURN), v[1]/v[0]/-r_refdef.view.frustum_x*0.5*r_refdef.view.width, v[2]/v[0]/-r_refdef.view.frustum_y*r_refdef.view.height*0.5, v[0]); + VectorSet(PRVM_G_VECTOR(OFS_RETURN), r_refdef.view.x + r_refdef.view.width*0.5*(1.0+v[1]/v[0]/-r_refdef.view.frustum_x), r_refdef.view.y + r_refdef.view.height*0.5*(1.0+v[2]/v[0]/-r_refdef.view.frustum_y), v[0]); } //#330 float(float stnum) getstatf (EXT_CSQC) @@ -1015,7 +1045,7 @@ static void VM_CL_setmodelindex (void) //#334 string(float mdlindex) modelnameforindex (EXT_CSQC) static void VM_CL_modelnameforindex (void) { - model_t *model; + dp_model_t *model; VM_SAFEPARMCOUNT(1, VM_CL_modelnameforindex); @@ -1048,6 +1078,8 @@ static void VM_CL_trailparticles (void) start = PRVM_G_VECTOR(OFS_PARM2); end = PRVM_G_VECTOR(OFS_PARM3); + if (i < 0) + return; CL_ParticleEffect(i, VectorDistance(start, end), start, end, t->fields.client->velocity, t->fields.client->velocity, NULL, prog->argc >= 5 ? (int)PRVM_G_FLOAT(OFS_PARM4) : 0); } @@ -1061,6 +1093,8 @@ static void VM_CL_pointparticles (void) f = PRVM_G_VECTOR(OFS_PARM1); v = PRVM_G_VECTOR(OFS_PARM2); n = (int)PRVM_G_FLOAT(OFS_PARM3); + if (i < 0) + return; CL_ParticleEffect(i, n, f, f, v, v, NULL, prog->argc >= 5 ? (int)PRVM_G_FLOAT(OFS_PARM4) : 0); } @@ -1079,20 +1113,36 @@ static void VM_CL_setcursormode (void) cl_ignoremousemoves = 2; } +//#344 vector() getmousepos (EXT_CSQC) +static void VM_CL_getmousepos(void) +{ + VM_SAFEPARMCOUNT(0,VM_CL_getmousepos); + + if (key_consoleactive || key_dest != key_game) + VectorSet(PRVM_G_VECTOR(OFS_RETURN), 0, 0, 0); + else if (cl.csqc_wantsmousemove) + VectorSet(PRVM_G_VECTOR(OFS_RETURN), in_windowmouse_x * vid_conwidth.integer / vid.width, in_windowmouse_y * vid_conheight.integer / vid.height, 0); + else + VectorSet(PRVM_G_VECTOR(OFS_RETURN), in_mouse_x * vid_conwidth.integer / vid.width, in_mouse_y * vid_conheight.integer / vid.height, 0); +} + //#345 float(float framenum) getinputstate (EXT_CSQC) static void VM_CL_getinputstate (void) { int i, frame; VM_SAFEPARMCOUNT(1, VM_CL_getinputstate); frame = (int)PRVM_G_FLOAT(OFS_PARM0); - for (i = 0;i < cl.movement_numqueue;i++) - if (cl.movement_queue[i].sequence == frame) + for (i = 0;i < CL_MAX_USERCMDS;i++) + { + if (cl.movecmd[i].sequence == frame) { - VectorCopy(cl.movement_queue[i].viewangles, prog->globals.client->input_angles); - //prog->globals.client->input_buttons = cl.movement_queue[i].//FIXME - VectorCopy(cl.movement_queue[i].move, prog->globals.client->input_movevalues); - prog->globals.client->input_timelength = cl.movement_queue[i].frametime; - if(cl.movement_queue[i].crouch) + VectorCopy(cl.movecmd[i].viewangles, prog->globals.client->input_angles); + prog->globals.client->input_buttons = cl.movecmd[i].buttons; // FIXME: this should not be directly exposed to csqc (translation layer needed?) + prog->globals.client->input_movevalues[0] = cl.movecmd[i].forwardmove; + prog->globals.client->input_movevalues[1] = cl.movecmd[i].sidemove; + prog->globals.client->input_movevalues[2] = cl.movecmd[i].upmove; + prog->globals.client->input_timelength = cl.movecmd[i].frametime; + if(cl.movecmd[i].crouch) { VectorCopy(cl.playercrouchmins, prog->globals.client->pmove_mins); VectorCopy(cl.playercrouchmaxs, prog->globals.client->pmove_maxs); @@ -1103,6 +1153,7 @@ static void VM_CL_getinputstate (void) VectorCopy(cl.playerstandmaxs, prog->globals.client->pmove_maxs); } } + } } //#346 void(float sens) setsensitivityscaler (EXT_CSQC) @@ -1131,8 +1182,9 @@ static void VM_CL_getplayerkey (void) PRVM_G_INT(OFS_RETURN) = OFS_NULL; Sbar_SortFrags(); - i = Sbar_GetPlayer(i); - if(i < 0) + if (i < 0) + i = Sbar_GetSortedPlayerIndex(-1-i); + if(i < 0 || i >= cl.maxclients) return; t[0] = 0; @@ -1141,28 +1193,28 @@ static void VM_CL_getplayerkey (void) strlcpy(t, cl.scores[i].name, sizeof(t)); else if(!strcasecmp(c, "frags")) - sprintf(t, "%i", cl.scores[i].frags); + dpsnprintf(t, sizeof(t), "%i", cl.scores[i].frags); else if(!strcasecmp(c, "ping")) - sprintf(t, "%i", cl.scores[i].qw_ping); + dpsnprintf(t, sizeof(t), "%i", cl.scores[i].qw_ping); else if(!strcasecmp(c, "pl")) - sprintf(t, "%i", cl.scores[i].qw_packetloss); + dpsnprintf(t, sizeof(t), "%i", cl.scores[i].qw_packetloss); else if(!strcasecmp(c, "entertime")) - sprintf(t, "%f", cl.scores[i].qw_entertime); + dpsnprintf(t, sizeof(t), "%f", cl.scores[i].qw_entertime); else if(!strcasecmp(c, "colors")) - sprintf(t, "%i", cl.scores[i].colors); + dpsnprintf(t, sizeof(t), "%i", cl.scores[i].colors); else if(!strcasecmp(c, "topcolor")) - sprintf(t, "%i", cl.scores[i].colors & 0xf0); + dpsnprintf(t, sizeof(t), "%i", cl.scores[i].colors & 0xf0); else if(!strcasecmp(c, "bottomcolor")) - sprintf(t, "%i", (cl.scores[i].colors &15)<<4); + dpsnprintf(t, sizeof(t), "%i", (cl.scores[i].colors &15)<<4); else if(!strcasecmp(c, "viewentity")) - sprintf(t, "%i", i+1); + dpsnprintf(t, sizeof(t), "%i", i+1); if(!t[0]) return; PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(t); @@ -1258,6 +1310,55 @@ static void VM_CL_ReadFloat (void) PRVM_G_FLOAT(OFS_RETURN) = MSG_ReadFloat(); } +//#501 string() readpicture (DP_CSQC_READWRITEPICTURE) +extern cvar_t cl_readpicture_force; +static void VM_CL_ReadPicture (void) +{ + const char *name; + unsigned char *data; + unsigned char *buf; + int size; + int i; + cachepic_t *pic; + + VM_SAFEPARMCOUNT(0, VM_CL_ReadPicture); + + name = MSG_ReadString(); + size = MSG_ReadShort(); + + // check if a texture of that name exists + // if yes, it is used and the data is discarded + // if not, the (low quality) data is used to build a new texture, whose name will get returned + + pic = Draw_CachePic_Flags (name, CACHEPICFLAG_NOTPERSISTENT); + + if(size) + { + if(pic->tex == r_texture_notexture) + pic->tex = NULL; // don't overwrite the notexture by Draw_NewPic + if(pic->tex && !cl_readpicture_force.integer) + { + // texture found and loaded + // skip over the jpeg as we don't need it + for(i = 0; i < size; ++i) + MSG_ReadByte(); + } + else + { + // texture not found + // use the attached jpeg as texture + buf = Mem_Alloc(tempmempool, size); + MSG_ReadBytes(size, buf); + data = JPEG_LoadImage_BGRA(buf, size); + Mem_Free(buf); + Draw_NewPic(name, image_width, image_height, false, data); + Mem_Free(data); + } + } + + PRVM_G_INT(OFS_RETURN) = PRVM_SetTempString(name); +} + ////////////////////////////////////////////////////////// static void VM_CL_makestatic (void) @@ -1775,9 +1876,9 @@ static void VM_CL_te_flamejet (void) //==================================================================== //DP_QC_GETSURFACE -extern void clippointtosurface(model_t *model, msurface_t *surface, vec3_t p, vec3_t out); +extern void clippointtosurface(dp_model_t *model, msurface_t *surface, vec3_t p, vec3_t out); -static msurface_t *cl_getsurface(model_t *model, int surfacenum) +static msurface_t *cl_getsurface(dp_model_t *model, int surfacenum) { if (surfacenum < 0 || surfacenum >= model->nummodelsurfaces) return NULL; @@ -1787,7 +1888,7 @@ static msurface_t *cl_getsurface(model_t *model, int surfacenum) // #434 float(entity e, float s) getsurfacenumpoints static void VM_CL_getsurfacenumpoints(void) { - model_t *model; + dp_model_t *model; msurface_t *surface; VM_SAFEPARMCOUNT(2, VM_CL_getsurfacenumpoints); // return 0 if no such surface @@ -1805,7 +1906,7 @@ static void VM_CL_getsurfacenumpoints(void) static void VM_CL_getsurfacepoint(void) { prvm_edict_t *ed; - model_t *model; + dp_model_t *model; msurface_t *surface; int pointnum; VM_SAFEPARMCOUNT(3, VM_CL_getsurfacenumpoints); @@ -1832,7 +1933,7 @@ static void VM_CL_getsurfacepoint(void) static void VM_CL_getsurfacepointattribute(void) { prvm_edict_t *ed; - model_t *model; + dp_model_t *model; msurface_t *surface; int pointnum; int attributetype; @@ -1853,7 +1954,7 @@ static void VM_CL_getsurfacepointattribute(void) switch( attributetype ) { // float SPA_POSITION = 0; case 0: - VectorAdd(&(model->surfmesh.data_vertex3f + 3 * surface->num_firstvertex)[pointnum * 3], ed->fields.server->origin, PRVM_G_VECTOR(OFS_RETURN)); + VectorAdd(&(model->surfmesh.data_vertex3f + 3 * surface->num_firstvertex)[pointnum * 3], ed->fields.client->origin, PRVM_G_VECTOR(OFS_RETURN)); break; // float SPA_S_AXIS = 1; case 1: @@ -1898,7 +1999,7 @@ static void VM_CL_getsurfacepointattribute(void) // #436 vector(entity e, float s) getsurfacenormal static void VM_CL_getsurfacenormal(void) { - model_t *model; + dp_model_t *model; msurface_t *surface; vec3_t normal; VM_SAFEPARMCOUNT(2, VM_CL_getsurfacenormal); @@ -1917,7 +2018,7 @@ static void VM_CL_getsurfacenormal(void) // #437 string(entity e, float s) getsurfacetexture static void VM_CL_getsurfacetexture(void) { - model_t *model; + dp_model_t *model; msurface_t *surface; VM_SAFEPARMCOUNT(2, VM_CL_getsurfacetexture); PRVM_G_INT(OFS_RETURN) = OFS_NULL; @@ -1933,7 +2034,7 @@ static void VM_CL_getsurfacenearpoint(void) vec3_t clipped, p; vec_t dist, bestdist; prvm_edict_t *ed; - model_t *model = NULL; + dp_model_t *model = NULL; msurface_t *surface; vec_t *point; VM_SAFEPARMCOUNT(2, VM_CL_getsurfacenearpoint); @@ -1976,7 +2077,7 @@ static void VM_CL_getsurfacenearpoint(void) static void VM_CL_getsurfaceclippedpoint(void) { prvm_edict_t *ed; - model_t *model; + dp_model_t *model; msurface_t *surface; vec3_t p, out; VM_SAFEPARMCOUNT(3, VM_CL_getsurfaceclippedpoint); @@ -1999,7 +2100,7 @@ void VM_CL_setattachment (void) const char *tagname; prvm_eval_t *v; int modelindex; - model_t *model; + dp_model_t *model; VM_SAFEPARMCOUNT(3, VM_CL_setattachment); e = PRVM_G_EDICT(OFS_PARM0); @@ -2047,7 +2148,7 @@ void VM_CL_setattachment (void) int CL_GetTagIndex (prvm_edict_t *e, const char *tagname) { - model_t *model = CL_GetModelFromEdict(e); + dp_model_t *model = CL_GetModelFromEdict(e); if (model) return Mod_Alias_GetTagIndexForName(model, (int)e->fields.client->skin, tagname); else @@ -2070,7 +2171,7 @@ int CL_GetTagMatrix (matrix4x4_t *out, prvm_edict_t *ent, int tagindex) int reqframe, attachloop; matrix4x4_t entitymatrix, tagmatrix, attachmatrix; prvm_edict_t *attachent; - model_t *model; + dp_model_t *model; float scale; *out = identitymatrix; // warnings and errors return identical matrix @@ -2265,13 +2366,14 @@ typedef struct vmpolygons_triangle_s { rtexture_t *texture; int drawflag; - int element3i[3]; + unsigned short elements[3]; }vmpolygons_triangle_t; typedef struct vmpolygons_s { mempool_t *pool; qboolean initialized; + double progstarttime; int max_vertices; int num_vertices; @@ -2282,7 +2384,7 @@ typedef struct vmpolygons_s int max_triangles; int num_triangles; vmpolygons_triangle_t *data_triangles; - int *data_sortedelement3i; + unsigned short *data_sortedelement3s; qboolean begin_active; rtexture_t *begin_texture; @@ -2296,19 +2398,37 @@ typedef struct vmpolygons_s // FIXME: make VM_CL_R_Polygon functions use Debug_Polygon functions? vmpolygons_t vmpolygons[PRVM_MAXPROGS]; +//#304 void() renderscene (EXT_CSQC) +// moved that here to reset the polygons, +// resetting them earlier causes R_Mesh_Draw to be called with numvertices = 0 +// --blub +void VM_CL_R_RenderScene (void) +{ + vmpolygons_t* polys = vmpolygons + PRVM_GetProgNr(); + VM_SAFEPARMCOUNT(0, VM_CL_R_RenderScene); + // we need to update any RENDER_VIEWMODEL entities at this point because + // csqc supplies its own view matrix + CL_UpdateViewEntities(); + // now draw stuff! + R_RenderView(); + + polys->num_vertices = polys->num_triangles = 0; + polys->progstarttime = prog->starttime; +} + static void VM_ResizePolygons(vmpolygons_t *polys) { float *oldvertex3f = polys->data_vertex3f; float *oldcolor4f = polys->data_color4f; float *oldtexcoord2f = polys->data_texcoord2f; vmpolygons_triangle_t *oldtriangles = polys->data_triangles; - int *oldsortedelement3i = polys->data_sortedelement3i; - polys->max_vertices = polys->max_triangles*3; + unsigned short *oldsortedelement3s = polys->data_sortedelement3s; + polys->max_vertices = min(polys->max_triangles*3, 65536); polys->data_vertex3f = (float *)Mem_Alloc(polys->pool, polys->max_vertices*sizeof(float[3])); polys->data_color4f = (float *)Mem_Alloc(polys->pool, polys->max_vertices*sizeof(float[4])); polys->data_texcoord2f = (float *)Mem_Alloc(polys->pool, polys->max_vertices*sizeof(float[2])); polys->data_triangles = (vmpolygons_triangle_t *)Mem_Alloc(polys->pool, polys->max_triangles*sizeof(vmpolygons_triangle_t)); - polys->data_sortedelement3i = (int *)Mem_Alloc(polys->pool, polys->max_triangles*sizeof(int[3])); + polys->data_sortedelement3s = (unsigned short *)Mem_Alloc(polys->pool, polys->max_triangles*sizeof(unsigned short[3])); if (polys->num_vertices) { memcpy(polys->data_vertex3f, oldvertex3f, polys->num_vertices*sizeof(float[3])); @@ -2318,7 +2438,7 @@ static void VM_ResizePolygons(vmpolygons_t *polys) if (polys->num_triangles) { memcpy(polys->data_triangles, oldtriangles, polys->num_triangles*sizeof(vmpolygons_triangle_t)); - memcpy(polys->data_sortedelement3i, oldsortedelement3i, polys->num_triangles*sizeof(int[3])); + memcpy(polys->data_sortedelement3s, oldsortedelement3s, polys->num_triangles*sizeof(unsigned short[3])); } if (oldvertex3f) Mem_Free(oldvertex3f); @@ -2328,8 +2448,8 @@ static void VM_ResizePolygons(vmpolygons_t *polys) Mem_Free(oldtexcoord2f); if (oldtriangles) Mem_Free(oldtriangles); - if (oldsortedelement3i) - Mem_Free(oldsortedelement3i); + if (oldsortedelement3s) + Mem_Free(oldsortedelement3s); } static void VM_InitPolygons (vmpolygons_t* polys) @@ -2345,23 +2465,31 @@ static void VM_DrawPolygonCallback (const entity_render_t *ent, const rtlight_t { int surfacelistindex; vmpolygons_t* polys = vmpolygons + PRVM_GetProgNr(); + if(polys->progstarttime != prog->starttime) // from other progs? won't draw these (this can cause crashes!) + return; + R_Mesh_ResetTextureState(); R_Mesh_Matrix(&identitymatrix); GL_CullFace(GL_NONE); R_Mesh_VertexPointer(polys->data_vertex3f, 0, 0); R_Mesh_ColorPointer(polys->data_color4f, 0, 0); R_Mesh_TexCoordPointer(0, 2, polys->data_texcoord2f, 0, 0); R_SetupGenericShader(true); + for (surfacelistindex = 0;surfacelistindex < numsurfaces;) { int numtriangles = 0; rtexture_t *tex = polys->data_triangles[surfacelist[surfacelistindex]].texture; int drawflag = polys->data_triangles[surfacelist[surfacelistindex]].drawflag; + // this can't call _DrawQ_ProcessDrawFlag, but should be in sync with it + // FIXME factor this out if(drawflag == DRAWFLAG_ADDITIVE) GL_BlendFunc(GL_SRC_ALPHA, GL_ONE); else if(drawflag == DRAWFLAG_MODULATE) GL_BlendFunc(GL_DST_COLOR, GL_ZERO); else if(drawflag == DRAWFLAG_2XMODULATE) GL_BlendFunc(GL_DST_COLOR,GL_SRC_COLOR); + else if(drawflag == DRAWFLAG_SCREEN) + GL_BlendFunc(GL_ONE_MINUS_DST_COLOR,GL_ONE); else GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); R_Mesh_TexBind(0, R_GetTexture(tex)); @@ -2370,10 +2498,10 @@ static void VM_DrawPolygonCallback (const entity_render_t *ent, const rtlight_t { if (polys->data_triangles[surfacelist[surfacelistindex]].texture != tex || polys->data_triangles[surfacelist[surfacelistindex]].drawflag != drawflag) break; - VectorCopy(polys->data_triangles[surfacelist[surfacelistindex]].element3i, polys->data_sortedelement3i + 3*numtriangles); + VectorCopy(polys->data_triangles[surfacelist[surfacelistindex]].elements, polys->data_sortedelement3s + 3*numtriangles); numtriangles++; } - R_Mesh_Draw(0, polys->num_vertices, numtriangles, polys->data_sortedelement3i, 0, 0); + R_Mesh_Draw(0, polys->num_vertices, 0, numtriangles, NULL, polys->data_sortedelement3s, 0, 0); } } @@ -2386,7 +2514,7 @@ void VMPolygons_Store(vmpolygons_t *polys) mesh.texture = polys->begin_texture; mesh.num_vertices = polys->begin_vertices; mesh.num_triangles = polys->begin_vertices-2; - mesh.data_element3i = polygonelements; + mesh.data_element3s = polygonelements; mesh.data_vertex3f = polys->begin_vertex[0]; mesh.data_color4f = polys->begin_color[0]; mesh.data_texcoord2f = polys->begin_texcoord[0]; @@ -2401,19 +2529,26 @@ void VMPolygons_Store(vmpolygons_t *polys) polys->max_triangles *= 2; VM_ResizePolygons(polys); } - memcpy(polys->data_vertex3f + polys->num_vertices * 3, polys->begin_vertex[0], polys->num_vertices * sizeof(float[3])); - memcpy(polys->data_color4f + polys->num_vertices * 4, polys->begin_color[0], polys->num_vertices * sizeof(float[4])); - memcpy(polys->data_texcoord2f + polys->num_vertices * 2, polys->begin_texcoord[0], polys->num_vertices * sizeof(float[2])); - for (i = 0;i < polys->begin_vertices-2;i++) + if (polys->num_vertices + polys->begin_vertices <= polys->max_vertices) { - polys->data_triangles[polys->num_triangles].texture = polys->begin_texture; - polys->data_triangles[polys->num_triangles].drawflag = polys->begin_drawflag; - polys->data_triangles[polys->num_triangles].element3i[0] = polys->num_vertices; - polys->data_triangles[polys->num_triangles].element3i[1] = polys->num_vertices + i+1; - polys->data_triangles[polys->num_triangles].element3i[2] = polys->num_vertices + i+2; - polys->num_triangles++; + // needle in a haystack! + // polys->num_vertices was used for copying where we actually want to copy begin_vertices + // that also caused it to not render the first polygon that is added + // --blub + memcpy(polys->data_vertex3f + polys->num_vertices * 3, polys->begin_vertex[0], polys->begin_vertices * sizeof(float[3])); + memcpy(polys->data_color4f + polys->num_vertices * 4, polys->begin_color[0], polys->begin_vertices * sizeof(float[4])); + memcpy(polys->data_texcoord2f + polys->num_vertices * 2, polys->begin_texcoord[0], polys->begin_vertices * sizeof(float[2])); + for (i = 0;i < polys->begin_vertices-2;i++) + { + polys->data_triangles[polys->num_triangles].texture = polys->begin_texture; + polys->data_triangles[polys->num_triangles].drawflag = polys->begin_drawflag; + polys->data_triangles[polys->num_triangles].elements[0] = polys->num_vertices; + polys->data_triangles[polys->num_triangles].elements[1] = polys->num_vertices + i+1; + polys->data_triangles[polys->num_triangles].elements[2] = polys->num_vertices + i+2; + polys->num_triangles++; + } + polys->num_vertices += polys->begin_vertices; } - polys->num_vertices += polys->begin_vertices; } polys->begin_active = false; } @@ -2435,32 +2570,65 @@ void VM_CL_AddPolygonsToMeshQueue (void) for (i = 0;i < polys->num_triangles;i++) { - VectorMAMAM(1.0f / 3.0f, polys->data_vertex3f + 3*polys->data_triangles[i].element3i[0], 1.0f / 3.0f, polys->data_vertex3f + 3*polys->data_triangles[i].element3i[1], 1.0f / 3.0f, polys->data_vertex3f + 3*polys->data_triangles[i].element3i[2], center); + VectorMAMAM(1.0f / 3.0f, polys->data_vertex3f + 3*polys->data_triangles[i].elements[0], 1.0f / 3.0f, polys->data_vertex3f + 3*polys->data_triangles[i].elements[1], 1.0f / 3.0f, polys->data_vertex3f + 3*polys->data_triangles[i].elements[2], center); R_MeshQueue_AddTransparent(center, VM_DrawPolygonCallback, NULL, i, NULL); } - polys->num_triangles = 0; - polys->num_vertices = 0; + /*polys->num_triangles = 0; // now done after rendering the scene, + polys->num_vertices = 0; // otherwise it's not rendered at all and prints an error message --blub */ } //void(string texturename, float flag) R_BeginPolygon void VM_CL_R_PolygonBegin (void) { const char *picname; + skinframe_t *sf; vmpolygons_t* polys = vmpolygons + PRVM_GetProgNr(); + int tf; + + // TODO instead of using skinframes here (which provides the benefit of + // better management of flags, and is more suited for 3D rendering), what + // about supporting Q3 shaders? VM_SAFEPARMCOUNT(2, VM_CL_R_PolygonBegin); if (!polys->initialized) VM_InitPolygons(polys); + if(polys->progstarttime != prog->starttime) + { + // from another progs? then reset the polys first (fixes crashes on map change, because that can make skinframe textures invalid) + polys->num_vertices = polys->num_triangles = 0; + polys->progstarttime = prog->starttime; + } if (polys->begin_active) { VM_Warning("VM_CL_R_PolygonBegin: called twice without VM_CL_R_PolygonBegin after first\n"); return; } picname = PRVM_G_STRING(OFS_PARM0); - polys->begin_texture = picname[0] ? Draw_CachePic(picname, true)->tex : r_texture_white; - polys->begin_drawflag = (int)PRVM_G_FLOAT(OFS_PARM1); + + sf = NULL; + if(*picname) + { + tf = TEXF_ALPHA; + if((int)PRVM_G_FLOAT(OFS_PARM1) & DRAWFLAG_MIPMAP) + tf |= TEXF_MIPMAP; + + do + { + sf = R_SkinFrame_FindNextByName(sf, picname); + } + while(sf && sf->textureflags != tf); + + if(!sf || !sf->base) + sf = R_SkinFrame_LoadExternal(picname, tf, true); + + if(sf) + R_SkinFrame_MarkUsed(sf); + } + + polys->begin_texture = (sf && sf->base) ? sf->base : r_texture_white; + polys->begin_drawflag = (int)PRVM_G_FLOAT(OFS_PARM1) & DRAWFLAG_MASK; polys->begin_vertices = 0; polys->begin_active = true; } @@ -2525,7 +2693,7 @@ void Debug_PolygonBegin(const char *picname, int drawflag) Con_Printf("Debug_PolygonBegin: called twice without Debug_PolygonEnd after first\n"); return; } - debugPolys.begin_texture = picname[0] ? Draw_CachePic(picname, true)->tex : r_texture_white; + debugPolys.begin_texture = picname[0] ? Draw_CachePic (picname)->tex : r_texture_white; debugPolys.begin_drawflag = drawflag; debugPolys.begin_vertices = 0; debugPolys.begin_active = true; @@ -3173,8 +3341,8 @@ VM_drawfill, // #323 float(vector position, vector size, vector rgb, float a VM_drawsetcliparea, // #324 void(float x, float y, float width, float height) drawsetcliparea VM_drawresetcliparea, // #325 void(void) drawresetcliparea VM_drawcolorcodedstring, // #326 float drawcolorcodedstring(vector position, string text, vector scale, vector rgb, float alpha, float flag) (EXT_CSQC) -NULL, // #327 // FIXME add stringwidth() here? -NULL, // #328 // FIXME add drawsubpic() here? +VM_stringwidth, // #327 // FIXME is this okay? +VM_drawsubpic, // #328 // FIXME is this okay? NULL, // #329 VM_CL_getstatf, // #330 float(float stnum) getstatf (EXT_CSQC) VM_CL_getstati, // #331 float(float stnum) getstati (EXT_CSQC) @@ -3190,7 +3358,7 @@ VM_keynumtostring, // #340 string(float keynum) keynumtostring (EXT_CSQC) VM_stringtokeynum, // #341 float(string keyname) stringtokeynum (EXT_CSQC) VM_CL_getkeybind, // #342 string(float keynum) getkeybind (EXT_CSQC) VM_CL_setcursormode, // #343 void(float usecursor) setcursormode (EXT_CSQC) -VM_getmousepos, // #344 vector() getmousepos (EXT_CSQC) +VM_CL_getmousepos, // #344 vector() getmousepos (EXT_CSQC) VM_CL_getinputstate, // #345 float(float framenum) getinputstate (EXT_CSQC) VM_CL_setsensitivityscale, // #346 void(float sens) setsensitivityscale (EXT_CSQC) VM_CL_runplayerphysics, // #347 void() runstandardplayerphysics (EXT_CSQC) @@ -3342,11 +3510,33 @@ VM_gecko_movemouse, // #491 void gecko_mousemove( string name, float x, float VM_gecko_resize, // #492 void gecko_resize( string name, float w, float h ) VM_gecko_get_texture_extent, // #493 vector gecko_get_texture_extent( string name ) VM_crc16, // #494 float(float caseinsensitive, string s, ...) crc16 = #494 (DP_QC_CRC16) -NULL, // #495 -NULL, // #496 -NULL, // #497 -NULL, // #498 -NULL, // #499 +VM_cvar_type, // #495 float(string name) cvar_type = #495; (DP_QC_CVAR_TYPE) +VM_numentityfields, // #496 float() numentityfields = #496; (QP_QC_ENTITYDATA) +VM_entityfieldname, // #497 string(float fieldnum) entityfieldname = #497; (DP_QC_ENTITYDATA) +VM_entityfieldtype, // #498 float(float fieldnum) entityfieldtype = #498; (DP_QC_ENTITYDATA) +VM_getentityfieldstring, // #499 string(float fieldnum, entity ent) getentityfieldstring = #499; (DP_QC_ENTITYDATA) +VM_putentityfieldstring, // #500 float(float fieldnum, entity ent, string s) putentityfieldstring = #500; (DP_QC_ENTITYDATA) +VM_CL_ReadPicture, // #501 string() ReadPicture = #501; +NULL, // #502 +VM_whichpack, // #503 string(string) whichpack = #503; +NULL, // #504 +NULL, // #505 +NULL, // #506 +NULL, // #507 +NULL, // #508 +NULL, // #509 +VM_uri_escape, // #510 string(string in) uri_escape = #510; +VM_uri_unescape, // #511 string(string in) uri_unescape = #511; +VM_etof, // #512 float(entity ent) num_for_edict = #512 (DP_QC_NUM_FOR_EDICT) +VM_uri_get, // #513 float(string uril, float id) uri_get = #512; (DP_QC_URI_GET) +NULL, // #514 +NULL, // #515 +NULL, // #516 +NULL, // #517 +NULL, // #518 +NULL, // #519 +VM_keynumtostring, // #520 string keynumtostring(float keynum) +VM_findkeysforcommand, // #521 string findkeysforcommand(string command) }; const int vm_cl_numbuiltins = sizeof(vm_cl_builtins) / sizeof(prvm_builtin_t);