X-Git-Url: http://de.git.xonotic.org/?p=xonotic%2Fdarkplaces.git;a=blobdiff_plain;f=clvm_cmds.c;h=7849ffe2a29b846d032a1704bc334a798904f8dd;hp=289e531eed039e9391c2aed589f1c2581128603d;hb=c3ea7019c9ce6dd91e6f40a027a45cd27da17385;hpb=6e48dafd2f198e53ef8031379080656e9483e709 diff --git a/clvm_cmds.c b/clvm_cmds.c index 289e531e..7849ffe2 100644 --- a/clvm_cmds.c +++ b/clvm_cmds.c @@ -20,6 +20,8 @@ //4 feature darkplaces csqc: add builtin to clientside qc for reading triangles of model meshes (useful to orient a ui along a triangle of a model mesh) //4 feature darkplaces csqc: add builtins to clientside qc for gl calls +extern cvar_t v_flipped; + sfx_t *S_FindName(const char *name); int Sbar_GetSortedPlayerIndex (int index); void Sbar_SortFrags (void); @@ -228,12 +230,23 @@ static void VM_CL_spawn (void) VM_RETURN_EDICT(ed); } +void CL_VM_SetTraceGlobals(const trace_t *trace, int svent) +{ + prvm_eval_t *val; + VM_SetTraceGlobals(trace); + if ((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.trace_networkentity))) + val->_float = svent; +} + +#define CL_HitNetworkBrushModels(move) !((move) == MOVE_WORLDONLY) +#define CL_HitNetworkPlayers(move) !((move) == MOVE_WORLDONLY || (move) == MOVE_NOMONSTERS) + // #16 float(vector v1, vector v2, float movetype, entity ignore) traceline static void VM_CL_traceline (void) { float *v1, *v2; trace_t trace; - int move; + int move, svent; prvm_edict_t *ent; VM_SAFEPARMCOUNTRANGE(4, 4, VM_CL_traceline); @@ -248,9 +261,9 @@ static void VM_CL_traceline (void) if (IS_NAN(v1[0]) || IS_NAN(v1[1]) || IS_NAN(v1[2]) || IS_NAN(v2[0]) || IS_NAN(v1[2]) || IS_NAN(v2[2])) PRVM_ERROR("%s: NAN errors detected in traceline('%f %f %f', '%f %f %f', %i, entity %i)\n", PRVM_NAME, v1[0], v1[1], v1[2], v2[0], v2[1], v2[2], move, PRVM_EDICT_TO_PROG(ent)); - trace = CL_Move(v1, vec3_origin, vec3_origin, v2, move, ent, CL_GenericHitSuperContentsMask(ent), true, true, NULL, true); + trace = CL_Move(v1, vec3_origin, vec3_origin, v2, move, ent, CL_GenericHitSuperContentsMask(ent), CL_HitNetworkBrushModels(move), CL_HitNetworkPlayers(move), &svent, true); - VM_SetTraceGlobals(&trace); + CL_VM_SetTraceGlobals(&trace, svent); } /* @@ -269,7 +282,7 @@ static void VM_CL_tracebox (void) { float *v1, *v2, *m1, *m2; trace_t trace; - int move; + int move, svent; prvm_edict_t *ent; VM_SAFEPARMCOUNTRANGE(6, 8, VM_CL_tracebox); // allow more parameters for future expansion @@ -286,12 +299,12 @@ static void VM_CL_tracebox (void) if (IS_NAN(v1[0]) || IS_NAN(v1[1]) || IS_NAN(v1[2]) || IS_NAN(v2[0]) || IS_NAN(v1[2]) || IS_NAN(v2[2])) PRVM_ERROR("%s: NAN errors detected in tracebox('%f %f %f', '%f %f %f', '%f %f %f', '%f %f %f', %i, entity %i)\n", PRVM_NAME, v1[0], v1[1], v1[2], m1[0], m1[1], m1[2], m2[0], m2[1], m2[2], v2[0], v2[1], v2[2], move, PRVM_EDICT_TO_PROG(ent)); - trace = CL_Move(v1, m1, m2, v2, move, ent, CL_GenericHitSuperContentsMask(ent), true, true, NULL, true); + trace = CL_Move(v1, m1, m2, v2, move, ent, CL_GenericHitSuperContentsMask(ent), CL_HitNetworkBrushModels(move), CL_HitNetworkPlayers(move), &svent, true); - VM_SetTraceGlobals(&trace); + CL_VM_SetTraceGlobals(&trace, svent); } -trace_t CL_Trace_Toss (prvm_edict_t *tossent, prvm_edict_t *ignore) +trace_t CL_Trace_Toss (prvm_edict_t *tossent, prvm_edict_t *ignore, int *svent) { int i; float gravity; @@ -341,6 +354,7 @@ static void VM_CL_tracetoss (void) trace_t trace; prvm_edict_t *ent; prvm_edict_t *ignore; + int svent; prog->xfunction->builtinsprofile += 600; @@ -354,9 +368,9 @@ static void VM_CL_tracetoss (void) } ignore = PRVM_G_EDICT(OFS_PARM1); - trace = CL_Trace_Toss (ent, ignore); + trace = CL_Trace_Toss (ent, ignore, &svent); - VM_SetTraceGlobals(&trace); + CL_VM_SetTraceGlobals(&trace, svent); } @@ -753,31 +767,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); + r_refdef.view.width = (int)(f[0]); + r_refdef.view.height = (int)(f[1]); break; case VF_SIZE_X: - r_refdef.view.width = (int)(k * vid.width / vid_conwidth.value); + r_refdef.view.width = (int)(k); break; case VF_SIZE_Y: - r_refdef.view.height = (int)(k * vid.height / vid_conheight.value); + 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]; @@ -903,7 +917,8 @@ void VM_CL_R_AddDynamicLight (void) 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); + R_RTLight_Update(&r_refdef.scene.templights[r_refdef.scene.numlights], false, &matrix, col, style, cubemapname, castshadow, coronaintensity, coronasizescale, ambientscale, diffusescale, specularscale, LIGHTFLAG_NORMALMODE | LIGHTFLAG_REALTIMEMODE); + r_refdef.scene.lights[r_refdef.scene.numlights] = &r_refdef.scene.templights[r_refdef.scene.numlights++]; } //============================================================================ @@ -916,7 +931,9 @@ 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); + if(v_flipped.integer) + f[0] = r_refdef.view.x + r_refdef.view.width - f[0]; + 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)); } @@ -931,7 +948,9 @@ 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]); + if(v_flipped.integer) + v[1] = -v[1]; + 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) @@ -1347,7 +1366,7 @@ static void VM_CL_ReadPicture (void) { // texture not found // use the attached jpeg as texture - buf = Mem_Alloc(tempmempool, size); + buf = (unsigned char *) Mem_Alloc(tempmempool, size); MSG_ReadBytes(size, buf); data = JPEG_LoadImage_BGRA(buf, size); Mem_Free(buf); @@ -2146,6 +2165,35 @@ void VM_CL_setattachment (void) ///////////////////////////////////////// // DP_MD3_TAGINFO extension coded by VorteX +int CL_GetExtendedTagInfo (prvm_edict_t *e, int tagindex, int *parentindex, const char **tagname, matrix4x4_t *tag_localmatrix) +{ + int r; + dp_model_t *model; + int frame; + + *tagname = NULL; + *parentindex = 0; + Matrix4x4_CreateIdentity(tag_localmatrix); + + if (tagindex >= 0 + && (model = CL_GetModelFromEdict(e)) + && model->animscenes) + { + frame = (int)e->fields.client->frame; + if (frame < 0 || frame >= model->numframes) + frame = 0; + + r = Mod_Alias_GetExtendedTagInfoForIndex(model, (int)e->fields.client->skin, model->animscenes[frame].firstframe, tagindex - 1, parentindex, tagname, tag_localmatrix); + + if(!r) // success? + *parentindex += 1; + + return r; + } + + return 1; +} + int CL_GetTagIndex (prvm_edict_t *e, const char *tagname) { dp_model_t *model = CL_GetModelFromEdict(e); @@ -2243,6 +2291,7 @@ int CL_GetTagMatrix (matrix4x4_t *out, prvm_edict_t *ent, int tagindex) if (val && val->_float != 0) scale = val->_float; // Alias models have inverse pitch, bmodels can't have tags, so don't check for modeltype... + // FIXME: support RF_USEAXIS Matrix4x4_CreateFromQuakeEntity(&entitymatrix, ent->fields.client->origin[0], ent->fields.client->origin[1], ent->fields.client->origin[2], -ent->fields.client->angles[0], ent->fields.client->angles[1], ent->fields.client->angles[2], scale); Matrix4x4_Concat(out, &entitymatrix, &tagmatrix); @@ -2325,7 +2374,12 @@ void VM_CL_gettaginfo (void) prvm_edict_t *e; int tagindex; matrix4x4_t tag_matrix; + matrix4x4_t tag_localmatrix; + int parentindex; + const char *tagname; int returncode; + prvm_eval_t *val; + vec3_t fo, ri, up, trans; VM_SAFEPARMCOUNT(2, VM_CL_gettaginfo); @@ -2333,6 +2387,21 @@ void VM_CL_gettaginfo (void) tagindex = (int)PRVM_G_FLOAT(OFS_PARM1); returncode = CL_GetTagMatrix(&tag_matrix, e, tagindex); Matrix4x4_ToVectors(&tag_matrix, prog->globals.client->v_forward, prog->globals.client->v_right, prog->globals.client->v_up, PRVM_G_VECTOR(OFS_RETURN)); + CL_GetExtendedTagInfo(e, tagindex, &parentindex, &tagname, &tag_localmatrix); + Matrix4x4_ToVectors(&tag_localmatrix, fo, ri, up, trans); + + if((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.gettaginfo_parent))) + val->_float = parentindex; + if((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.gettaginfo_name))) + val->string = tagname ? PRVM_SetTempString(tagname) : 0; + if((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.gettaginfo_offset))) + VectorCopy(trans, val->vector); + if((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.gettaginfo_forward))) + VectorCopy(fo, val->vector); + if((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.gettaginfo_right))) + VectorCopy(ri, val->vector); + if((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.gettaginfo_up))) + VectorCopy(up, val->vector); switch(returncode) { @@ -2373,6 +2442,7 @@ typedef struct vmpolygons_s { mempool_t *pool; qboolean initialized; + double progstarttime; int max_vertices; int num_vertices; @@ -2412,6 +2482,7 @@ void VM_CL_R_RenderScene (void) R_RenderView(); polys->num_vertices = polys->num_triangles = 0; + polys->progstarttime = prog->starttime; } static void VM_ResizePolygons(vmpolygons_t *polys) @@ -2463,6 +2534,8 @@ 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); @@ -2476,12 +2549,16 @@ static void VM_DrawPolygonCallback (const entity_render_t *ent, const rtlight_t 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)); @@ -2574,20 +2651,53 @@ void VM_CL_AddPolygonsToMeshQueue (void) 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_Flags (picname, CACHEPICFLAG_NOCLAMP)->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; } @@ -2742,7 +2852,7 @@ realcheck: start[0] = stop[0] = (mins[0] + maxs[0])*0.5; start[1] = stop[1] = (mins[1] + maxs[1])*0.5; stop[2] = start[2] - 2*sv_stepheight.value; - trace = CL_Move (start, vec3_origin, vec3_origin, stop, MOVE_NOMONSTERS, ent, CL_GenericHitSuperContentsMask(ent), true, true, NULL, true); + trace = CL_Move (start, vec3_origin, vec3_origin, stop, MOVE_NOMONSTERS, ent, CL_GenericHitSuperContentsMask(ent), true, false, NULL, true); if (trace.fraction == 1.0) return false; @@ -2755,7 +2865,7 @@ realcheck: start[0] = stop[0] = x ? maxs[0] : mins[0]; start[1] = stop[1] = y ? maxs[1] : mins[1]; - trace = CL_Move (start, vec3_origin, vec3_origin, stop, MOVE_NOMONSTERS, ent, CL_GenericHitSuperContentsMask(ent), true, true, NULL, true); + trace = CL_Move (start, vec3_origin, vec3_origin, stop, MOVE_NOMONSTERS, ent, CL_GenericHitSuperContentsMask(ent), true, false, NULL, true); if (trace.fraction != 1.0 && trace.endpos[2] > bottom) bottom = trace.endpos[2]; @@ -2780,7 +2890,7 @@ qboolean CL_movestep (prvm_edict_t *ent, vec3_t move, qboolean relink, qboolean float dz; vec3_t oldorg, neworg, end, traceendpos; trace_t trace; - int i; + int i, svent; prvm_edict_t *enemy; prvm_eval_t *val; @@ -2804,9 +2914,9 @@ qboolean CL_movestep (prvm_edict_t *ent, vec3_t move, qboolean relink, qboolean if (dz < 30) neworg[2] += 8; } - trace = CL_Move (ent->fields.client->origin, ent->fields.client->mins, ent->fields.client->maxs, neworg, MOVE_NORMAL, ent, CL_GenericHitSuperContentsMask(ent), true, true, NULL, true); + trace = CL_Move (ent->fields.client->origin, ent->fields.client->mins, ent->fields.client->maxs, neworg, MOVE_NORMAL, ent, CL_GenericHitSuperContentsMask(ent), true, true, &svent, true); if (settrace) - VM_SetTraceGlobals(&trace); + CL_VM_SetTraceGlobals(&trace, svent); if (trace.fraction == 1) { @@ -2832,16 +2942,16 @@ qboolean CL_movestep (prvm_edict_t *ent, vec3_t move, qboolean relink, qboolean VectorCopy (neworg, end); end[2] -= sv_stepheight.value*2; - trace = CL_Move (neworg, ent->fields.client->mins, ent->fields.client->maxs, end, MOVE_NORMAL, ent, CL_GenericHitSuperContentsMask(ent), true, true, NULL, true); + trace = CL_Move (neworg, ent->fields.client->mins, ent->fields.client->maxs, end, MOVE_NORMAL, ent, CL_GenericHitSuperContentsMask(ent), true, true, &svent, true); if (settrace) - VM_SetTraceGlobals(&trace); + CL_VM_SetTraceGlobals(&trace, svent); if (trace.startsolid) { neworg[2] -= sv_stepheight.value; - trace = CL_Move (neworg, ent->fields.client->mins, ent->fields.client->maxs, end, MOVE_NORMAL, ent, CL_GenericHitSuperContentsMask(ent), true, true, NULL, true); + trace = CL_Move (neworg, ent->fields.client->mins, ent->fields.client->maxs, end, MOVE_NORMAL, ent, CL_GenericHitSuperContentsMask(ent), true, true, &svent, true); if (settrace) - VM_SetTraceGlobals(&trace); + CL_VM_SetTraceGlobals(&trace, svent); if (trace.startsolid) return false; } @@ -3488,14 +3598,25 @@ 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 +VM_tokenize_console, // #514 float(string str) tokenize_console = #514; (DP_QC_TOKENIZE_CONSOLE) +VM_argv_start_index, // #515 float(float idx) argv_start_index = #515; (DP_QC_TOKENIZE_CONSOLE) +VM_argv_end_index, // #516 float(float idx) argv_end_index = #516; (DP_QC_TOKENIZE_CONSOLE) +VM_buf_cvarlist, // #517 void(float buf, string prefix, string antiprefix) buf_cvarlist = #517; (DP_QC_STRINGBUFFERS_CVARLIST) +VM_cvar_description, // #518 float(string name) cvar_description = #518; (DP_QC_CVAR_DESCRIPTION) NULL, // #519 VM_keynumtostring, // #520 string keynumtostring(float keynum) VM_findkeysforcommand, // #521 string findkeysforcommand(string command) +NULL, // #522 +NULL, // #523 +NULL, // #524 +NULL, // #525 +NULL, // #526 +NULL, // #527 +NULL, // #528 +NULL, // #529 +NULL, // #530 +NULL, // #531 +NULL, // #532 }; const int vm_cl_numbuiltins = sizeof(vm_cl_builtins) / sizeof(prvm_builtin_t);