From 19259a56af993def9d5160bb2eb32e35a2fc6398 Mon Sep 17 00:00:00 2001 From: havoc Date: Sun, 27 Mar 2005 08:22:05 +0000 Subject: [PATCH] implemented tag attachments on skeletal .zym models and centralized the code dealing with tags in model_alias.c git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@5125 d7cf8633-e32d-0410-b094-e92efae38249 --- cl_main.c | 7 +++-- model_alias.c | 65 ++++++++++++++++++++++++++++++++++++++++++ model_alias.h | 2 ++ model_shared.h | 8 +++--- pr_cmds.c | 76 ++++++++++---------------------------------------- 5 files changed, 90 insertions(+), 68 deletions(-) diff --git a/cl_main.c b/cl_main.c index d9bc3b06..94f52fe8 100644 --- a/cl_main.c +++ b/cl_main.c @@ -560,17 +560,18 @@ void CL_LinkNetworkEntity(entity_t *e) e->render.flags |= t->render.flags & RENDER_EXTERIORMODEL; // if a valid tagindex is used, make it relative to that tag instead // FIXME: use a model function to get tag info (need to handle skeletal) - if (e->state_current.tagentity && e->state_current.tagindex >= 1 && (model = t->render.model) && e->state_current.tagindex <= t->render.model->alias.aliasnum_tags) + if (e->state_current.tagentity && e->state_current.tagindex >= 1 && (model = t->render.model)) { // blend the matrices memset(&blendmatrix, 0, sizeof(blendmatrix)); for (j = 0;j < 4 && t->render.frameblend[j].lerp > 0;j++) { - matrix = &t->render.model->alias.aliasdata_tags[t->render.frameblend[j].frame * t->render.model->alias.aliasnum_tags + (e->state_current.tagindex - 1)].matrix; + matrix4x4_t tagmatrix; + Mod_Alias_GetTagMatrix(model, t->render.frameblend[j].frame, e->state_current.tagindex - 1, &tagmatrix); d = t->render.frameblend[j].lerp; for (l = 0;l < 4;l++) for (k = 0;k < 4;k++) - blendmatrix.m[l][k] += d * matrix->m[l][k]; + blendmatrix.m[l][k] += d * tagmatrix.m[l][k]; } // concat the tag matrices onto the entity matrix Matrix4x4_Concat(&tempmatrix, &t->render.matrix, &blendmatrix); diff --git a/model_alias.c b/model_alias.c index a35dbb75..04e66354 100644 --- a/model_alias.c +++ b/model_alias.c @@ -102,6 +102,71 @@ void Mod_Alias_GetMesh_Vertex3f(const model_t *model, const frameblend_t *frameb } } +int Mod_Alias_GetTagMatrix(const model_t *model, int poseframe, int tagindex, matrix4x4_t *outmatrix) +{ + const float *boneframe; + float tempbonematrix[12], bonematrix[12]; + Matrix4x4_CreateIdentity(outmatrix); + if (model->alias.aliasnum_bones) + { + if (tagindex < 0 || tagindex >= model->alias.aliasnum_bones) + return 4; + if (poseframe >= model->alias.aliasnum_poses) + return 6; + boneframe = model->alias.aliasdata_poses + poseframe * model->alias.aliasnum_bones * 12; + memcpy(bonematrix, boneframe + tagindex * 12, sizeof(float[12])); + while (model->alias.aliasdata_bones[tagindex].parent >= 0) + { + memcpy(tempbonematrix, bonematrix, sizeof(float[12])); + R_ConcatTransforms(boneframe + model->alias.aliasdata_bones[tagindex].parent * 12, tempbonematrix, bonematrix); + tagindex = model->alias.aliasdata_bones[tagindex].parent; + } + outmatrix->m[0][0] = bonematrix[0]; + outmatrix->m[0][1] = bonematrix[1]; + outmatrix->m[0][2] = bonematrix[2]; + outmatrix->m[0][3] = bonematrix[3]; + outmatrix->m[1][0] = bonematrix[4]; + outmatrix->m[1][1] = bonematrix[5]; + outmatrix->m[1][2] = bonematrix[6]; + outmatrix->m[1][3] = bonematrix[7]; + outmatrix->m[2][0] = bonematrix[8]; + outmatrix->m[2][1] = bonematrix[9]; + outmatrix->m[2][2] = bonematrix[10]; + outmatrix->m[2][3] = bonematrix[11]; + outmatrix->m[3][0] = 0; + outmatrix->m[3][1] = 0; + outmatrix->m[3][2] = 0; + outmatrix->m[3][3] = 1; + } + else if (model->alias.aliasnum_tags) + { + if (tagindex < 0 || tagindex >= model->alias.aliasnum_tags) + return 4; + if (poseframe >= model->alias.aliasnum_tagframes) + return 6; + *outmatrix = model->alias.aliasdata_tags[poseframe * model->alias.aliasnum_tags + tagindex].matrix; + } + return 0; +} + +int Mod_Alias_GetTagIndexForName(const model_t *model, unsigned int skin, const char *tagname) +{ + int i; + if (model->data_overridetagnamesforskin && skin < (unsigned int)model->numskins && model->data_overridetagnamesforskin[(unsigned int)skin].num_overridetagnames) + for (i = 0;i < model->data_overridetagnamesforskin[skin].num_overridetagnames;i++) + if (!strcasecmp(tagname, model->data_overridetagnamesforskin[skin].data_overridetagnames[i].name)) + return i + 1; + if (model->alias.aliasnum_bones) + for (i = 0;i < model->alias.aliasnum_bones;i++) + if (!strcasecmp(tagname, model->alias.aliasdata_bones[i].name)) + return i + 1; + if (model->alias.aliasnum_tags) + for (i = 0;i < model->alias.aliasnum_tags;i++) + if (!strcasecmp(tagname, model->alias.aliasdata_tags[i].name)) + return i + 1; + return 0; +} + static void Mod_Alias_Mesh_CompileFrameZero(aliasmesh_t *mesh) { frameblend_t frameblend[4] = {{0, 1}, {0, 0}, {0, 0}, {0, 0}}; diff --git a/model_alias.h b/model_alias.h index 338e2dd9..15c6d8a2 100644 --- a/model_alias.h +++ b/model_alias.h @@ -271,6 +271,8 @@ aliasbone_t; struct frameblend_s; void Mod_Alias_GetMesh_Vertex3f(const struct model_s *model, const struct frameblend_s *frameblend, const struct aliasmesh_s *mesh, float *out3f); +int Mod_Alias_GetTagMatrix(const struct model_s *model, int poseframe, int tagindex, matrix4x4_t *outmatrix); +int Mod_Alias_GetTagIndexForName(const struct model_s *model, unsigned int skin, const char *tagname); #endif diff --git a/model_shared.h b/model_shared.h index 3123203f..5379bd5f 100644 --- a/model_shared.h +++ b/model_shared.h @@ -79,15 +79,15 @@ typedef struct surfmesh_s int num_vertices; // number of vertices in the mesh int num_triangles; // number of triangles in the mesh float *data_vertex3f; // float[verts*3] vertex locations + int *data_element3i; // int[tris*3] triangles of the mesh, 3 indices into vertex arrays for each + float *data_texcoordtexture2f; // float[verts*2] texcoords for surface texture + float *data_texcoordlightmap2f; // float[verts*2] texcoords for lightmap texture + float *data_lightmapcolor4f; float *data_svector3f; // float[verts*3] direction of 'S' (right) texture axis for each vertex float *data_tvector3f; // float[verts*3] direction of 'T' (down) texture axis for each vertex float *data_normal3f; // float[verts*3] direction of 'R' (out) texture axis for each vertex int *data_lightmapoffsets; // index into surface's lightmap samples for vertex lighting - float *data_texcoordtexture2f; // float[verts*2] texcoords for surface texture - float *data_texcoordlightmap2f; // float[verts*2] texcoords for lightmap texture float *data_texcoorddetail2f; // float[verts*2] texcoords for detail texture - float *data_lightmapcolor4f; - int *data_element3i; // int[tris*3] triangles of the mesh, 3 indices into vertex arrays for each int *data_neighbor3i; // int[tris*3] neighboring triangle on each edge (-1 if none) int num_collisionvertices; diff --git a/pr_cmds.c b/pr_cmds.c index e57ebe39..15e902b2 100644 --- a/pr_cmds.c +++ b/pr_cmds.c @@ -3059,7 +3059,7 @@ void PF_setattachment (void) edict_t *tagentity = G_EDICT(OFS_PARM1); char *tagname = G_STRING(OFS_PARM2); eval_t *v; - int i, modelindex; + int modelindex; model_t *model; if (e == sv.edicts) @@ -3082,15 +3082,7 @@ void PF_setattachment (void) modelindex = (int)tagentity->v->modelindex; if (modelindex >= 0 && modelindex < MAX_MODELS && (model = sv.models[modelindex])) { - if (model->data_overridetagnamesforskin && (unsigned int)tagentity->v->skin < (unsigned int)model->numskins && model->data_overridetagnamesforskin[(unsigned int)tagentity->v->skin].num_overridetagnames) - for (i = 0;i < model->data_overridetagnamesforskin[(unsigned int)tagentity->v->skin].num_overridetagnames;i++) - if (!strcmp(tagname, model->data_overridetagnamesforskin[(unsigned int)tagentity->v->skin].data_overridetagnames[i].name)) - v->_float = i + 1; - // FIXME: use a model function to get tag info (need to handle skeletal) - if (v->_float == 0 && model->alias.aliasnum_tags) - for (i = 0;i < model->alias.aliasnum_tags;i++) - if (!strcmp(tagname, model->alias.aliasdata_tags[i].name)) - v->_float = i + 1; + v->_float = Mod_Alias_GetTagIndexForName(model, tagentity->v->skin, tagname); if (v->_float == 0) Con_DPrintf("setattachment(edict %i, edict %i, string \"%s\"): tried to find tag named \"%s\" on entity %i (model \"%s\") but could not find it\n", NUM_FOR_EDICT(e), NUM_FOR_EDICT(tagentity), tagname, tagname, NUM_FOR_EDICT(tagentity), model->name); } @@ -3104,7 +3096,7 @@ void PF_setattachment (void) int SV_GetTagIndex (edict_t *e, char *tagname) { - int tagindex, i; + int i; model_t *model; i = e->v->modelindex; @@ -3112,30 +3104,7 @@ int SV_GetTagIndex (edict_t *e, char *tagname) return -1; model = sv.models[i]; - tagindex = -1; - if (model->data_overridetagnamesforskin && (unsigned int)e->v->skin < (unsigned int)model->numskins && model->data_overridetagnamesforskin[(unsigned int)e->v->skin].num_overridetagnames) - { - for (i = 0; i < model->data_overridetagnamesforskin[(unsigned int)e->v->skin].num_overridetagnames; i++) - { - if (!strcmp(tagname, model->data_overridetagnamesforskin[(unsigned int)e->v->skin].data_overridetagnames[i].name)) - { - tagindex = i; - break; - } - } - } - if (tagindex == -1) - { - for (i = 0;i < model->alias.aliasnum_tags; i++) - { - if (!(strcmp(tagname, model->alias.aliasdata_tags[i].name))) - { - tagindex = i; - break; - } - } - } - return tagindex + 1; + return Mod_Alias_GetTagIndexForName(model, e->v->skin, tagname); }; // Warnings/errors code: @@ -3151,7 +3120,7 @@ extern cvar_t cl_bobup; int SV_GetTagMatrix (matrix4x4_t *out, edict_t *ent, int tagindex) { eval_t *val; - int modelindex, reqtag, reqframe, attachloop; + int modelindex, reqframe, attachloop; matrix4x4_t entitymatrix, tagmatrix, attachmatrix; edict_t *attachent; model_t *model; @@ -3168,25 +3137,18 @@ int SV_GetTagMatrix (matrix4x4_t *out, edict_t *ent, int tagindex) return 3; model = sv.models[modelindex]; - reqtag = model->alias.aliasnum_tags; - - if (tagindex <= 0 || tagindex > reqtag) - { - if (reqtag && tagindex) // Only appear if model has no tags or not-null tag requested - return 4; - return 0; - } - if (ent->v->frame < 0 || ent->v->frame > model->alias.aliasnum_tagframes) - reqframe = model->numframes - 1; // if model has wrong frame, engine automatically switches to model last frame + if (ent->v->frame >= 0 && ent->v->frame < model->numframes && model->animscenes) + reqframe = model->animscenes[(int)ent->v->frame].firstframe; else - reqframe = ent->v->frame; + reqframe = 0; // if model has wrong frame, engine automatically switches to model first frame // get initial tag matrix if (tagindex) { - reqtag = (tagindex - 1) + ent->v->frame*model->alias.aliasnum_tags; - Matrix4x4_Copy(&tagmatrix, &model->alias.aliasdata_tags[reqtag].matrix); + int ret = Mod_Alias_GetTagMatrix(model, reqframe, tagindex - 1, &tagmatrix); + if (ret) + return ret; } else Matrix4x4_CreateIdentity(&tagmatrix); @@ -3198,18 +3160,10 @@ int SV_GetTagMatrix (matrix4x4_t *out, edict_t *ent, int tagindex) { attachent = EDICT_NUM(val->edict); // to this it entity our entity is attached val = GETEDICTFIELDVALUE(ent, eval_tag_index); - Matrix4x4_CreateIdentity(&attachmatrix); - if (val->_float >= 1 && attachent->v->modelindex >= 1 && attachent->v->modelindex < MAX_MODELS) - { - model = sv.models[(int)attachent->v->modelindex]; - if (val->_float < model->alias.aliasnum_tags) - { - // got tagname on parent entity attachment tag via tag_index (and got it's matrix) - model = sv.models[(int)attachent->v->modelindex]; - reqtag = (val->_float - 1) + attachent->v->frame*model->alias.aliasnum_tags; - Matrix4x4_Copy(&attachmatrix, &model->alias.aliasdata_tags[reqtag].matrix); - } - } + if (val->_float >= 1 && attachent->v->modelindex >= 1 && attachent->v->modelindex < MAX_MODELS && (model = sv.models[(int)attachent->v->modelindex]) && model->animscenes && attachent->v->frame >= 0 && attachent->v->frame < model->numframes) + Mod_Alias_GetTagMatrix(model, model->animscenes[(int)attachent->v->frame].firstframe, val->_float - 1, &attachmatrix); + else + Matrix4x4_CreateIdentity(&attachmatrix); // apply transformation by child entity matrix val = GETEDICTFIELDVALUE(ent, eval_scale); -- 2.39.2