X-Git-Url: https://git.xonotic.org/?a=blobdiff_plain;f=prvm_cmds.c;h=e2b023e24e1c16ed18f00abd02a8252bb41f30cb;hb=1da342cb637815a1eb2d9d96384ceb6fa4765d3f;hp=d8f5681c88ac10b65d2b48f8a04a82cceafc30e6;hpb=9a69ea042cd1455e635febc7f4af634ac2a90730;p=xonotic%2Fdarkplaces.git diff --git a/prvm_cmds.c b/prvm_cmds.c index d8f5681c..e2b023e2 100644 --- a/prvm_cmds.c +++ b/prvm_cmds.c @@ -99,7 +99,10 @@ void VM_FrameBlendFromFrameGroupBlend(frameblend_t *frameblend, const framegroup memset(blend, 0, MAX_FRAMEBLENDS * sizeof(*blend)); - if (!model || !model->surfmesh.isanimated) + // rpolzer: Not testing isanimated here - a model might have + // "animations" that move no vertices (but only bones), thus rendering + // may assume it's not animated while processing can't. + if (!model) { blend[0].lerp = 1; return; @@ -4425,23 +4428,25 @@ string altstr_prepare(string) */ void VM_altstr_prepare(prvm_prog_t *prog) { - char *out; const char *instr, *in; - int size; char outstr[VM_STRINGTEMP_LENGTH]; + size_t outpos; VM_SAFEPARMCOUNT( 1, VM_altstr_prepare ); instr = PRVM_G_STRING( OFS_PARM0 ); - for( out = outstr, in = instr, size = sizeof(outstr) - 1 ; size && *in ; size--, in++, out++ ) - if( *in == '\'' ) { - *out++ = '\\'; - *out = '\''; - size--; - } else - *out = *in; - *out = 0; + for (in = instr, outpos = 0; *in && outpos < sizeof(outstr) - 1; ++in) + { + if (*in == '\'' && outpos < sizeof(outstr) - 2) + { + outstr[outpos++] = '\\'; + outstr[outpos++] = '\''; + } + else + outstr[outpos++] = *in; + } + outstr[outpos] = 0; PRVM_G_INT( OFS_RETURN ) = PRVM_SetTempString(prog, outstr ); } @@ -4637,7 +4642,7 @@ static int BufStr_SortStringsDOWN (const void *in1, const void *in2) return strncmp(b, a, stringbuffers_sortlength); } -prvm_stringbuffer_t *BufStr_FindCreateReplace (prvm_prog_t *prog, int bufindex, int flags, char *format) +prvm_stringbuffer_t *BufStr_FindCreateReplace (prvm_prog_t *prog, int bufindex, int flags, const char *format) { prvm_stringbuffer_t *stringbuffer; int i; @@ -5090,21 +5095,19 @@ void VM_buf_loadfile(prvm_prog_t *prog) size_t alloclen; prvm_stringbuffer_t *stringbuffer; char string[VM_STRINGTEMP_LENGTH]; - int filenum, strindex, c, end; + int strindex, c, end; const char *filename; char vabuf[1024]; + qfile_t *file; VM_SAFEPARMCOUNT(2, VM_buf_loadfile); // get file filename = PRVM_G_STRING(OFS_PARM0); - for (filenum = 0;filenum < PRVM_MAX_OPENFILES;filenum++) - if (prog->openfiles[filenum] == NULL) - break; - prog->openfiles[filenum] = FS_OpenVirtualFile(va(vabuf, sizeof(vabuf), "data/%s", filename), false); - if (prog->openfiles[filenum] == NULL) - prog->openfiles[filenum] = FS_OpenVirtualFile(va(vabuf, sizeof(vabuf), "%s", filename), false); - if (prog->openfiles[filenum] == NULL) + file = FS_OpenVirtualFile(va(vabuf, sizeof(vabuf), "data/%s", filename), false); + if (file == NULL) + file = FS_OpenVirtualFile(va(vabuf, sizeof(vabuf), "%s", filename), false); + if (file == NULL) { if (developer_extra.integer) VM_Warning(prog, "VM_buf_loadfile: failed to open file %s in %s\n", filename, prog->name); @@ -5129,7 +5132,7 @@ void VM_buf_loadfile(prvm_prog_t *prog) end = 0; for (;;) { - c = FS_Getc(prog->openfiles[filenum]); + c = FS_Getc(file); if (c == '\r' || c == '\n' || c < 0) break; if (end < VM_STRINGTEMP_LENGTH - 1) @@ -5139,9 +5142,9 @@ void VM_buf_loadfile(prvm_prog_t *prog) // remove \n following \r if (c == '\r') { - c = FS_Getc(prog->openfiles[filenum]); + c = FS_Getc(file); if (c != '\n') - FS_UnGetc(prog->openfiles[filenum], (unsigned char)c); + FS_UnGetc(file, (unsigned char)c); } // add and continue if (c >= 0 || end) @@ -5158,10 +5161,7 @@ void VM_buf_loadfile(prvm_prog_t *prog) } // close file - FS_Close(prog->openfiles[filenum]); - prog->openfiles[filenum] = NULL; - if (prog->openfiles_origin[filenum]) - PRVM_Free((char *)prog->openfiles_origin[filenum]); + FS_Close(file); PRVM_G_FLOAT(OFS_RETURN) = 1; } @@ -6039,11 +6039,14 @@ void VM_Cmd_Init(prvm_prog_t *prog) VM_Search_Init(prog); } +static void animatemodel_reset(prvm_prog_t *prog); + void VM_Cmd_Reset(prvm_prog_t *prog) { CL_PurgeOwner( MENUOWNER ); VM_Search_Reset(prog); VM_Files_CloseAll(prog); + animatemodel_reset(prog); } // #510 string(string input, ...) uri_escape (DP_QC_URI_ESCAPE) @@ -6813,7 +6816,8 @@ nolength: default: verbatim: if(o < end - 1) - *o++ = *s++; + *o++ = *s; + ++s; break; } } @@ -6835,9 +6839,8 @@ static dp_model_t *getmodel(prvm_prog_t *prog, prvm_edict_t *ed) return NULL; } -typedef struct +struct animatemodel_cache { - unsigned int progid; dp_model_t *model; frameblend_t frameblend[MAX_FRAMEBLENDS]; skeleton_t *skeleton_p; @@ -6851,61 +6854,74 @@ typedef struct float *buf_svector3f; float *buf_tvector3f; float *buf_normal3f; +}; + +static void animatemodel_reset(prvm_prog_t *prog) +{ + if (!prog->animatemodel_cache) + return; + if(prog->animatemodel_cache->buf_vertex3f) Mem_Free(prog->animatemodel_cache->buf_vertex3f); + if(prog->animatemodel_cache->buf_svector3f) Mem_Free(prog->animatemodel_cache->buf_svector3f); + if(prog->animatemodel_cache->buf_tvector3f) Mem_Free(prog->animatemodel_cache->buf_tvector3f); + if(prog->animatemodel_cache->buf_normal3f) Mem_Free(prog->animatemodel_cache->buf_normal3f); + Mem_Free(prog->animatemodel_cache); } -animatemodel_cache_t; -static animatemodel_cache_t animatemodel_cache; static void animatemodel(prvm_prog_t *prog, dp_model_t *model, prvm_edict_t *ed) { skeleton_t *skeleton; int skeletonindex = -1; qboolean need = false; + struct animatemodel_cache *animatemodel_cache; + if (!prog->animatemodel_cache) + { + prog->animatemodel_cache = (struct animatemodel_cache *)Mem_Alloc(prog->progs_mempool, sizeof(struct animatemodel_cache)); + memset(prog->animatemodel_cache, 0, sizeof(struct animatemodel_cache)); + } + animatemodel_cache = prog->animatemodel_cache; if(!(model->surfmesh.isanimated && model->AnimateVertices)) { - animatemodel_cache.data_vertex3f = model->surfmesh.data_vertex3f; - animatemodel_cache.data_svector3f = model->surfmesh.data_svector3f; - animatemodel_cache.data_tvector3f = model->surfmesh.data_tvector3f; - animatemodel_cache.data_normal3f = model->surfmesh.data_normal3f; + animatemodel_cache->data_vertex3f = model->surfmesh.data_vertex3f; + animatemodel_cache->data_svector3f = model->surfmesh.data_svector3f; + animatemodel_cache->data_tvector3f = model->surfmesh.data_tvector3f; + animatemodel_cache->data_normal3f = model->surfmesh.data_normal3f; return; } - if(animatemodel_cache.progid != prog->id) - memset(&animatemodel_cache, 0, sizeof(animatemodel_cache)); - need |= (animatemodel_cache.model != model); + need |= (animatemodel_cache->model != model); VM_GenerateFrameGroupBlend(prog, ed->priv.server->framegroupblend, ed); VM_FrameBlendFromFrameGroupBlend(ed->priv.server->frameblend, ed->priv.server->framegroupblend, model, PRVM_serverglobalfloat(time)); - need |= (memcmp(&animatemodel_cache.frameblend, &ed->priv.server->frameblend, sizeof(ed->priv.server->frameblend))) != 0; + need |= (memcmp(&animatemodel_cache->frameblend, &ed->priv.server->frameblend, sizeof(ed->priv.server->frameblend))) != 0; skeletonindex = (int)PRVM_gameedictfloat(ed, skeletonindex) - 1; if (!(skeletonindex >= 0 && skeletonindex < MAX_EDICTS && (skeleton = prog->skeletons[skeletonindex]) && skeleton->model->num_bones == ed->priv.server->skeleton.model->num_bones)) skeleton = NULL; - need |= (animatemodel_cache.skeleton_p != skeleton); + need |= (animatemodel_cache->skeleton_p != skeleton); if(skeleton) - need |= (memcmp(&animatemodel_cache.skeleton, skeleton, sizeof(ed->priv.server->skeleton))) != 0; + need |= (memcmp(&animatemodel_cache->skeleton, skeleton, sizeof(ed->priv.server->skeleton))) != 0; if(!need) return; - if(model->surfmesh.num_vertices > animatemodel_cache.max_vertices) - { - animatemodel_cache.max_vertices = model->surfmesh.num_vertices * 2; - if(animatemodel_cache.buf_vertex3f) Mem_Free(animatemodel_cache.buf_vertex3f); - if(animatemodel_cache.buf_svector3f) Mem_Free(animatemodel_cache.buf_svector3f); - if(animatemodel_cache.buf_tvector3f) Mem_Free(animatemodel_cache.buf_tvector3f); - if(animatemodel_cache.buf_normal3f) Mem_Free(animatemodel_cache.buf_normal3f); - animatemodel_cache.buf_vertex3f = (float *)Mem_Alloc(prog->progs_mempool, sizeof(float[3]) * animatemodel_cache.max_vertices); - animatemodel_cache.buf_svector3f = (float *)Mem_Alloc(prog->progs_mempool, sizeof(float[3]) * animatemodel_cache.max_vertices); - animatemodel_cache.buf_tvector3f = (float *)Mem_Alloc(prog->progs_mempool, sizeof(float[3]) * animatemodel_cache.max_vertices); - animatemodel_cache.buf_normal3f = (float *)Mem_Alloc(prog->progs_mempool, sizeof(float[3]) * animatemodel_cache.max_vertices); - } - animatemodel_cache.data_vertex3f = animatemodel_cache.buf_vertex3f; - animatemodel_cache.data_svector3f = animatemodel_cache.buf_svector3f; - animatemodel_cache.data_tvector3f = animatemodel_cache.buf_tvector3f; - animatemodel_cache.data_normal3f = animatemodel_cache.buf_normal3f; + if(model->surfmesh.num_vertices > animatemodel_cache->max_vertices) + { + animatemodel_cache->max_vertices = model->surfmesh.num_vertices * 2; + if(animatemodel_cache->buf_vertex3f) Mem_Free(animatemodel_cache->buf_vertex3f); + if(animatemodel_cache->buf_svector3f) Mem_Free(animatemodel_cache->buf_svector3f); + if(animatemodel_cache->buf_tvector3f) Mem_Free(animatemodel_cache->buf_tvector3f); + if(animatemodel_cache->buf_normal3f) Mem_Free(animatemodel_cache->buf_normal3f); + animatemodel_cache->buf_vertex3f = (float *)Mem_Alloc(prog->progs_mempool, sizeof(float[3]) * animatemodel_cache->max_vertices); + animatemodel_cache->buf_svector3f = (float *)Mem_Alloc(prog->progs_mempool, sizeof(float[3]) * animatemodel_cache->max_vertices); + animatemodel_cache->buf_tvector3f = (float *)Mem_Alloc(prog->progs_mempool, sizeof(float[3]) * animatemodel_cache->max_vertices); + animatemodel_cache->buf_normal3f = (float *)Mem_Alloc(prog->progs_mempool, sizeof(float[3]) * animatemodel_cache->max_vertices); + } + animatemodel_cache->data_vertex3f = animatemodel_cache->buf_vertex3f; + animatemodel_cache->data_svector3f = animatemodel_cache->buf_svector3f; + animatemodel_cache->data_tvector3f = animatemodel_cache->buf_tvector3f; + animatemodel_cache->data_normal3f = animatemodel_cache->buf_normal3f; VM_UpdateEdictSkeleton(prog, ed, model, ed->priv.server->frameblend); - model->AnimateVertices(model, ed->priv.server->frameblend, &ed->priv.server->skeleton, animatemodel_cache.data_vertex3f, animatemodel_cache.data_normal3f, animatemodel_cache.data_svector3f, animatemodel_cache.data_tvector3f); - animatemodel_cache.progid = prog->id; - animatemodel_cache.model = model; - memcpy(&animatemodel_cache.frameblend, &ed->priv.server->frameblend, sizeof(ed->priv.server->frameblend)); - animatemodel_cache.skeleton_p = skeleton; + model->AnimateVertices(model, ed->priv.server->frameblend, &ed->priv.server->skeleton, animatemodel_cache->data_vertex3f, animatemodel_cache->data_normal3f, animatemodel_cache->data_svector3f, animatemodel_cache->data_tvector3f); + animatemodel_cache->model = model; + memcpy(&animatemodel_cache->frameblend, &ed->priv.server->frameblend, sizeof(ed->priv.server->frameblend)); + animatemodel_cache->skeleton_p = skeleton; if(skeleton) - memcpy(&animatemodel_cache.skeleton, skeleton, sizeof(ed->priv.server->skeleton)); + memcpy(&animatemodel_cache->skeleton, skeleton, sizeof(ed->priv.server->skeleton)); } static void getmatrix(prvm_prog_t *prog, prvm_edict_t *ed, matrix4x4_t *out) @@ -6961,9 +6977,9 @@ static void clippointtosurface(prvm_prog_t *prog, prvm_edict_t *ed, dp_model_t * { // clip original point to each triangle of the surface and find the // triangle that is closest - v[0] = animatemodel_cache.data_vertex3f + e[0] * 3; - v[1] = animatemodel_cache.data_vertex3f + e[1] * 3; - v[2] = animatemodel_cache.data_vertex3f + e[2] * 3; + v[0] = prog->animatemodel_cache->data_vertex3f + e[0] * 3; + v[1] = prog->animatemodel_cache->data_vertex3f + e[1] * 3; + v[2] = prog->animatemodel_cache->data_vertex3f + e[2] * 3; TriangleNormal(v[0], v[1], v[2], facenormal); VectorNormalize(facenormal); offsetdist = DotProduct(v[0], facenormal) - DotProduct(p, facenormal); @@ -7028,7 +7044,7 @@ void VM_getsurfacepoint(prvm_prog_t *prog) if (pointnum < 0 || pointnum >= surface->num_vertices) return; animatemodel(prog, model, ed); - applytransform_forward(prog, &(animatemodel_cache.data_vertex3f + 3 * surface->num_firstvertex)[pointnum * 3], ed, result); + applytransform_forward(prog, &(prog->animatemodel_cache->data_vertex3f + 3 * surface->num_firstvertex)[pointnum * 3], ed, result); VectorCopy(result, PRVM_G_VECTOR(OFS_RETURN)); } //PF_getsurfacepointattribute, // #486 vector(entity e, float s, float n, float a) getsurfacepointattribute = #486; @@ -7063,22 +7079,22 @@ void VM_getsurfacepointattribute(prvm_prog_t *prog) switch( attributetype ) { // float SPA_POSITION = 0; case 0: - applytransform_forward(prog, &(animatemodel_cache.data_vertex3f + 3 * surface->num_firstvertex)[pointnum * 3], ed, result); + applytransform_forward(prog, &(prog->animatemodel_cache->data_vertex3f + 3 * surface->num_firstvertex)[pointnum * 3], ed, result); VectorCopy(result, PRVM_G_VECTOR(OFS_RETURN)); break; // float SPA_S_AXIS = 1; case 1: - applytransform_forward_direction(prog, &(animatemodel_cache.data_svector3f + 3 * surface->num_firstvertex)[pointnum * 3], ed, result); + applytransform_forward_direction(prog, &(prog->animatemodel_cache->data_svector3f + 3 * surface->num_firstvertex)[pointnum * 3], ed, result); VectorCopy(result, PRVM_G_VECTOR(OFS_RETURN)); break; // float SPA_T_AXIS = 2; case 2: - applytransform_forward_direction(prog, &(animatemodel_cache.data_tvector3f + 3 * surface->num_firstvertex)[pointnum * 3], ed, result); + applytransform_forward_direction(prog, &(prog->animatemodel_cache->data_tvector3f + 3 * surface->num_firstvertex)[pointnum * 3], ed, result); VectorCopy(result, PRVM_G_VECTOR(OFS_RETURN)); break; // float SPA_R_AXIS = 3; // same as SPA_NORMAL case 3: - applytransform_forward_direction(prog, &(animatemodel_cache.data_normal3f + 3 * surface->num_firstvertex)[pointnum * 3], ed, result); + applytransform_forward_direction(prog, &(prog->animatemodel_cache->data_normal3f + 3 * surface->num_firstvertex)[pointnum * 3], ed, result); VectorCopy(result, PRVM_G_VECTOR(OFS_RETURN)); break; // float SPA_TEXCOORDS0 = 4; @@ -7123,7 +7139,7 @@ void VM_getsurfacenormal(prvm_prog_t *prog) // note: this only returns the first triangle, so it doesn't work very // well for curved surfaces or arbitrary meshes animatemodel(prog, model, PRVM_G_EDICT(OFS_PARM0)); - TriangleNormal((animatemodel_cache.data_vertex3f + 3 * surface->num_firstvertex), (animatemodel_cache.data_vertex3f + 3 * surface->num_firstvertex) + 3, (animatemodel_cache.data_vertex3f + 3 * surface->num_firstvertex) + 6, normal); + TriangleNormal((prog->animatemodel_cache->data_vertex3f + 3 * surface->num_firstvertex), (prog->animatemodel_cache->data_vertex3f + 3 * surface->num_firstvertex) + 3, (prog->animatemodel_cache->data_vertex3f + 3 * surface->num_firstvertex) + 6, normal); applytransform_forward_normal(prog, normal, PRVM_G_EDICT(OFS_PARM0), result); VectorNormalize(result); VectorCopy(result, PRVM_G_VECTOR(OFS_RETURN));