diff --git a/doc/040_cvarlist.md b/doc/040_cvarlist.md index 884eb5a3..19295354 100644 --- a/doc/040_cvarlist.md +++ b/doc/040_cvarlist.md @@ -146,6 +146,10 @@ it's `+set busywait 0` (setting the `busywait` cvar) and `-portable` preview. `-1` - don't show animation. Defaults to `94` for show salute animation. +* **cl_model_mesh_hide**: Mesh mask to hide in multiplayer model preview. + `0` - show whole model, `2` - hide second mesh from model. Defaults + to `0` for show whole model. + * **cl_nodownload_list**: Whitespace separated list of substrings, files having one these strings in their name are never downloaded. Empty by default. Note that some substrings are always forbidden, for security diff --git a/src/client/cl_entities.c b/src/client/cl_entities.c index 6f68e29c..235b2704 100644 --- a/src/client/cl_entities.c +++ b/src/client/cl_entities.c @@ -63,6 +63,7 @@ CL_AddPacketEntities(frame_t *frame) effects = s1->effects; rr_effects = s1->rr_effects; renderfx = s1->renderfx; + ent.rr_mesh = s1->rr_mesh; /* set frame */ if (effects & EF_ANIM01) diff --git a/src/client/cl_parse.c b/src/client/cl_parse.c index 5f558ba0..c8904380 100644 --- a/src/client/cl_parse.c +++ b/src/client/cl_parse.c @@ -259,20 +259,24 @@ CL_ParseDelta(const entity_xstate_t *from, entity_xstate_t *to, int number, int if (cls.serverProtocol != PROTOCOL_VERSION) { to->rr_effects = 0; + to->rr_mesh = 0; } else { if ((bits & (U_EFFECTS8 | U_EFFECTS16)) == (U_EFFECTS8 | U_EFFECTS16)) { to->rr_effects = MSG_ReadLong(&net_message); + to->rr_mesh = MSG_ReadLong(&net_message); } else if (bits & U_EFFECTS8) { to->rr_effects = MSG_ReadByte(&net_message); + to->rr_mesh = MSG_ReadByte(&net_message); } else if (bits & U_EFFECTS16) { to->rr_effects = MSG_ReadShort(&net_message); + to->rr_mesh = MSG_ReadShort(&net_message); } } diff --git a/src/client/menu/menu.c b/src/client/menu/menu.c index 7190df88..7d84f19c 100644 --- a/src/client/menu/menu.c +++ b/src/client/menu/menu.c @@ -6180,11 +6180,12 @@ extern float CalcFov(float fov_x, float w, float h); static void PlayerConfig_AnimateModel(entity_t *entity, int count, int curTime) { - const cvar_t *cl_start_frame, *cl_end_frame; + const cvar_t *cl_start_frame, *cl_end_frame, *cl_mesh_mask; int startFrame, endFrame; cl_start_frame = Cvar_Get("cl_model_preview_start", "84", CVAR_ARCHIVE); cl_end_frame = Cvar_Get("cl_model_preview_end", "94", CVAR_ARCHIVE); + cl_mesh_mask = Cvar_Get("cl_model_mesh_hide", "0", CVAR_ARCHIVE); startFrame = cl_start_frame->value; endFrame = cl_end_frame->value; @@ -6196,6 +6197,8 @@ PlayerConfig_AnimateModel(entity_t *entity, int count, int curTime) { /* salute male 84..94 frame */ entity[i].frame = (curTime / 100) % (endFrame - startFrame) + startFrame; + /* hide part of meshes */ + entity[i].rr_mesh = cl_mesh_mask->value; } } } diff --git a/src/client/refresh/gl1/gl1_mesh.c b/src/client/refresh/gl1/gl1_mesh.c index c2c42088..54419fe7 100644 --- a/src/client/refresh/gl1/gl1_mesh.c +++ b/src/client/refresh/gl1/gl1_mesh.c @@ -181,6 +181,11 @@ R_DrawAliasFrameLerp(entity_t *currententity, dmdx_t *paliashdr, float backlerp, for (i = 0; i < num_mesh_nodes; i++) { + if (currententity->rr_mesh & (1 << i)) + { + continue; + } + R_DrawAliasDrawCommands(currententity, order + mesh_nodes[i].ofs_glcmds, order + Q_min(paliashdr->num_glcmds, diff --git a/src/client/refresh/gl3/gl3_mesh.c b/src/client/refresh/gl3/gl3_mesh.c index 0ff9e889..fcd46ea9 100644 --- a/src/client/refresh/gl3/gl3_mesh.c +++ b/src/client/refresh/gl3/gl3_mesh.c @@ -299,6 +299,11 @@ DrawAliasFrameLerp(dmdx_t *paliashdr, entity_t* entity, vec3_t shadelight, for (i = 0; i < num_mesh_nodes; i++) { + if (entity->rr_mesh & (1 << i)) + { + continue; + } + DrawAliasFrameLerpCommands(paliashdr, entity, shadelight, order + mesh_nodes[i].ofs_glcmds, order + Q_min(paliashdr->num_glcmds, diff --git a/src/client/refresh/gl4/gl4_mesh.c b/src/client/refresh/gl4/gl4_mesh.c index a8f789a2..577acb22 100644 --- a/src/client/refresh/gl4/gl4_mesh.c +++ b/src/client/refresh/gl4/gl4_mesh.c @@ -299,6 +299,11 @@ DrawAliasFrameLerp(dmdx_t *paliashdr, entity_t* entity, vec3_t shadelight, for (i = 0; i < num_mesh_nodes; i++) { + if (entity->rr_mesh & (1 << i)) + { + continue; + } + DrawAliasFrameLerpCommands(paliashdr, entity, shadelight, order + mesh_nodes[i].ofs_glcmds, order + Q_min(paliashdr->num_glcmds, diff --git a/src/client/refresh/soft/sw_alias.c b/src/client/refresh/soft/sw_alias.c index 185071f5..73c19dcc 100644 --- a/src/client/refresh/soft/sw_alias.c +++ b/src/client/refresh/soft/sw_alias.c @@ -476,6 +476,11 @@ R_AliasPreparePoints(const entity_t *currententity, finalvert_t *verts, const fi const dtriangle_t *ptri; int num_tris; + if (currententity->rr_mesh & (1 << i)) + { + continue; + } + num_tris = Q_min(s_pmdl->num_tris - mesh_nodes[i].ofs_tris, mesh_nodes[i].num_tris); ptri = (dtriangle_t *)((byte *)s_pmdl + s_pmdl->ofs_tris) + mesh_nodes[i].ofs_tris; diff --git a/src/client/refresh/vk/vk_mesh.c b/src/client/refresh/vk/vk_mesh.c index 4ba2759c..f027304d 100644 --- a/src/client/refresh/vk/vk_mesh.c +++ b/src/client/refresh/vk/vk_mesh.c @@ -383,6 +383,11 @@ Vk_DrawAliasFrameLerp(entity_t *currententity, dmdx_t *paliashdr, float backlerp for (i = 0; i < num_mesh_nodes; i++) { + if (currententity->rr_mesh & (1 << i)) + { + continue; + } + Vk_DrawAliasFrameLerpCommands( order + mesh_nodes[i].ofs_glcmds, order + Q_min(paliashdr->num_glcmds, diff --git a/src/client/vid/header/ref.h b/src/client/vid/header/ref.h index f6a8e15d..7e69732c 100644 --- a/src/client/vid/header/ref.h +++ b/src/client/vid/header/ref.h @@ -69,6 +69,7 @@ typedef struct entity_s { float backlerp; /* 0.0 = current, 1.0 = old */ int skinnum; /* also used as RF_BEAM's palette index */ vec3_t scale; /* model scale before render */ + unsigned rr_mesh; /* disabled meshes */ int lightstyle; /* for flashing entities */ float alpha; /* ignore if RF_TRANSLUCENT isn't set */ diff --git a/src/common/header/shared.h b/src/common/header/shared.h index c2fa8c3b..e095a799 100644 --- a/src/common/header/shared.h +++ b/src/common/header/shared.h @@ -1236,6 +1236,7 @@ typedef struct entity_rrstate_s /* New protocol fields */ vec3_t scale; /* model scale */ unsigned int effects; + unsigned int mesh; } entity_rrstate_t; typedef struct entity_xstate_s @@ -1263,6 +1264,7 @@ typedef struct entity_xstate_s /* New protocol fields, sync with entity_rrstate_t */ vec3_t scale; /* model scale */ unsigned int rr_effects; + unsigned int rr_mesh; } entity_xstate_t; /* ============================================== */ diff --git a/src/common/movemsg.c b/src/common/movemsg.c index 52b786f6..935b410c 100644 --- a/src/common/movemsg.c +++ b/src/common/movemsg.c @@ -545,7 +545,7 @@ MSG_WriteDeltaEntity(const entity_xstate_t *from, } } - if (to->rr_effects != from->rr_effects) + if (to->rr_effects != from->rr_effects || to->rr_mesh != from->rr_mesh) { bits |= U_EFFECTS8 | U_EFFECTS16; } @@ -778,16 +778,19 @@ MSG_WriteDeltaEntity(const entity_xstate_t *from, if ((bits & (U_EFFECTS8 | U_EFFECTS16)) == (U_EFFECTS8 | U_EFFECTS16)) { MSG_WriteLong(msg, to->rr_effects); + MSG_WriteLong(msg, to->rr_mesh); } else if (bits & U_EFFECTS8) { MSG_WriteByte(msg, to->rr_effects); + MSG_WriteByte(msg, to->rr_mesh); } else if (bits & U_EFFECTS16) { MSG_WriteShort(msg, to->rr_effects); + MSG_WriteShort(msg, to->rr_mesh); } }