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;
void VM_precache_pic(prvm_prog_t *prog)
{
const char *s;
- int flags = 0;
+ int flags = CACHEPICFLAG_FAILONMISSING;
VM_SAFEPARMCOUNTRANGE(1, 2, VM_precache_pic);
flags |= CACHEPICFLAG_MIPMAP;
}
- // AK Draw_CachePic is supposed to always return a valid pointer
- if( Draw_CachePic_Flags(s, flags)->tex == r_texture_notexture )
+ if( !Draw_IsPicLoaded(Draw_CachePic_Flags(s, flags)) )
PRVM_G_INT(OFS_RETURN) = OFS_NULL;
}
float sx, sy;
VM_SAFEPARMCOUNT(6,VM_drawcharacter);
+ // polygonbegin without draw2d arg has to guess
+ prog->polygonbegin_guess2d = true;
+
character = (char) PRVM_G_FLOAT(OFS_PARM1);
if(character == 0)
{
float sx, sy;
VM_SAFEPARMCOUNTRANGE(5,6,VM_drawstring);
+ // polygonbegin without draw2d arg has to guess
+ prog->polygonbegin_guess2d = true;
+
string = PRVM_G_STRING(OFS_PARM1);
pos = PRVM_G_VECTOR(OFS_PARM0);
scale = PRVM_G_VECTOR(OFS_PARM2);
VM_SAFEPARMCOUNTRANGE(5,6,VM_drawcolorcodedstring);
+ // polygonbegin without draw2d arg has to guess
+ prog->polygonbegin_guess2d = true;
+
if (prog->argc == 6) // full 6 parms, like normal drawstring
{
pos = PRVM_G_VECTOR(OFS_PARM0);
VM_SAFEPARMCOUNTRANGE(5,6,VM_drawpic);
+ // polygonbegin without draw2d arg has to guess
+ prog->polygonbegin_guess2d = true;
+
picname = PRVM_G_STRING(OFS_PARM1);
VM_CheckEmptyString(prog, picname);
VM_SAFEPARMCOUNT(8,VM_drawrotpic);
+ // polygonbegin without draw2d arg has to guess
+ prog->polygonbegin_guess2d = true;
+
picname = PRVM_G_STRING(OFS_PARM1);
VM_CheckEmptyString(prog, picname);
VM_SAFEPARMCOUNT(8,VM_drawsubpic);
+ // polygonbegin without draw2d arg has to guess
+ prog->polygonbegin_guess2d = true;
+
picname = PRVM_G_STRING(OFS_PARM2);
VM_CheckEmptyString(prog, picname);
VM_SAFEPARMCOUNT(5,VM_drawfill);
+ // polygonbegin without draw2d arg has to guess
+ prog->polygonbegin_guess2d = true;
pos = PRVM_G_VECTOR(OFS_PARM0);
size = PRVM_G_VECTOR(OFS_PARM1);
float x,y,w,h;
VM_SAFEPARMCOUNT(4,VM_drawsetcliparea);
+ // polygonbegin without draw2d arg has to guess
+ prog->polygonbegin_guess2d = true;
+
x = bound(0, PRVM_G_FLOAT(OFS_PARM0), vid_conwidth.integer);
y = bound(0, PRVM_G_FLOAT(OFS_PARM1), vid_conheight.integer);
w = bound(0, PRVM_G_FLOAT(OFS_PARM2) + PRVM_G_FLOAT(OFS_PARM0) - x, (vid_conwidth.integer - x));
{
VM_SAFEPARMCOUNT(0,VM_drawresetcliparea);
+ // polygonbegin without draw2d arg has to guess
+ prog->polygonbegin_guess2d = true;
+
DrawQ_ResetClipArea();
}
VM_CheckEmptyString(prog, p);
pic = Draw_CachePic_Flags (p, CACHEPICFLAG_NOTPERSISTENT);
- if( pic->tex == r_texture_notexture )
+ if (!Draw_IsPicLoaded(pic))
{
PRVM_G_VECTOR(OFS_RETURN)[0] = 0;
PRVM_G_VECTOR(OFS_RETURN)[1] = 0;
}
else
{
- PRVM_G_VECTOR(OFS_RETURN)[0] = pic->width;
- PRVM_G_VECTOR(OFS_RETURN)[1] = pic->height;
+ PRVM_G_VECTOR(OFS_RETURN)[0] = Draw_GetPicWidth(pic);
+ PRVM_G_VECTOR(OFS_RETURN)[1] = Draw_GetPicHeight(pic);
}
PRVM_G_VECTOR(OFS_RETURN)[2] = 0;
}
unsigned char flags;
VM_SAFEPARMCOUNT(6, VM_drawline);
+
+ // polygonbegin without draw2d arg has to guess
+ prog->polygonbegin_guess2d = true;
+
width = PRVM_G_FLOAT(OFS_PARM0);
c1 = PRVM_G_VECTOR(OFS_PARM1);
c2 = PRVM_G_VECTOR(OFS_PARM2);
void VM_altstr_prepare(prvm_prog_t *prog)
{
const char *instr, *in;
- int size;
char outstr[VM_STRINGTEMP_LENGTH];
- int outpos;
+ size_t outpos;
VM_SAFEPARMCOUNT( 1, VM_altstr_prepare );
{
if (*in == '\'' && outpos < sizeof(outstr) - 2)
{
- out[outpos++] = '\\';
- out[outpos++] = '\'';
+ outstr[outpos++] = '\\';
+ outstr[outpos++] = '\'';
}
else
- out[outpos++] = *in;
+ outstr[outpos++] = *in;
}
- out[outpos++] = 0;
+ outstr[outpos] = 0;
PRVM_G_INT( OFS_RETURN ) = PRVM_SetTempString(prog, outstr );
}
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;
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)
return NULL;
}
-typedef struct
+struct animatemodel_cache
{
- unsigned int progid;
dp_model_t *model;
frameblend_t frameblend[MAX_FRAMEBLENDS];
skeleton_t *skeleton_p;
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)
{
// 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);
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;
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;
// 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));