diff --git a/engine/client/m_options.c b/engine/client/m_options.c index bd413a2c0..d7a6a112f 100644 --- a/engine/client/m_options.c +++ b/engine/client/m_options.c @@ -3386,6 +3386,7 @@ static void M_ModelViewerDraw(int x, int y, struct menucustom_s *c, struct emenu modelview_t *mods = c->dptr; skinfile_t *skin; + texnums_t *texnums; if (R2D_Flush) R2D_Flush(); @@ -3756,7 +3757,7 @@ static void M_ModelViewerDraw(int x, int y, struct menucustom_s *c, struct emenu } else { - shader = Mod_ShaderForSkin(ent.model, mods->surfaceidx, mods->skingroup); + shader = Mod_ShaderForSkin(ent.model, mods->surfaceidx, mods->skingroup, r_refdef.time, &texnums); Draw_FunString(0, y, va("Skin %i: \"%s\", material \"%s\"", mods->skingroup, fname, shader?shader->name:"NO SHADER")); } y+=8; @@ -3904,7 +3905,7 @@ static void M_ModelViewerDraw(int x, int y, struct menucustom_s *c, struct emenu { if (!mods->shadertext) { - char *body = Shader_GetShaderBody(Mod_ShaderForSkin(ent.model, mods->surfaceidx, mods->skingroup), mods->shaderfile, sizeof(mods->shaderfile)); + char *body = Shader_GetShaderBody(Mod_ShaderForSkin(ent.model, mods->surfaceidx, mods->skingroup, r_refdef.time, &texnums), mods->shaderfile, sizeof(mods->shaderfile)); if (!body) { Draw_FunString(0, y, "Shader info not available"); @@ -3922,11 +3923,11 @@ static void M_ModelViewerDraw(int x, int y, struct menucustom_s *c, struct emenu break; case MV_TEXTURE: { - shader_t *shader = Mod_ShaderForSkin(ent.model, mods->surfaceidx, mods->skingroup); + shader_t *shader = Mod_ShaderForSkin(ent.model, mods->surfaceidx, mods->skingroup, r_refdef.time, &texnums); if (shader) { char *t; - texnums_t *skin = shader->defaulttextures; + texnums_t *skin = (texnums&&TEXVALID(texnums->base))?texnums:shader->defaulttextures; shader = R_RegisterShader("modelviewertexturepreview", SUF_2D, "{\nprogram default2d\n{\nmap $diffuse\n}\n}\n"); switch(mods->textype) @@ -3983,10 +3984,54 @@ static void M_ModelViewerDraw(int x, int y, struct menucustom_s *c, struct emenu w = (float)vid.width / shader->defaulttextures->base->width; h = (float)(vid.height-y) / shader->defaulttextures->base->height; - h = min(min(w,h), 1); + h = min(w,h); w = h*shader->defaulttextures->base->width; h = h*shader->defaulttextures->base->height; R2D_Image(0, y, w, h, 0, 0, 1, 1, shader); + + + { + shader_t *s = R_RegisterShader("hitbox_nodepth", SUF_NONE, + "{\n" + "polygonoffset\n" + "{\n" + "map $whiteimage\n" + "blendfunc gl_src_alpha gl_one\n" + "rgbgen vertex\n" + "alphagen vertex\n" + "nodepthtest\n" + "}\n" + "}\n"); + int oldtris = cl_numstris; + int oldidx = cl_numstrisidx; + int oldvert = cl_numstrisvert; + mesh_t mesh; + memset(&mesh, 0, sizeof(mesh)); + + AngleVectors(vec3_origin, ent.axis[0], ent.axis[1], ent.axis[2]); + VectorInverse(ent.axis[1]); + VectorScale(ent.axis[0], w, ent.axis[0]); + VectorScale(ent.axis[1], h, ent.axis[1]); + VectorSet(ent.origin, 0, y, 0); + ent.scale = 1; + + Mod_AddSingleSurface(&ent, mods->surfaceidx, s, 2); + + mesh.xyz_array = cl_strisvertv + oldvert; + mesh.st_array = cl_strisvertt + oldvert; + mesh.colors4f_array[0] = cl_strisvertc + oldvert; + mesh.indexes = cl_strisidx + oldidx; + mesh.numindexes = cl_numstrisidx - oldidx; + mesh.numvertexes = cl_numstrisvert-oldvert; + + cl_numstris = oldtris; + cl_numstrisidx = oldidx; + cl_numstrisvert = oldvert; + + if (R2D_Flush) + R2D_Flush(); + BE_DrawMesh_Single(s, &mesh, NULL, BEF_LINES); + } } else Draw_FunString(0, y, va("%s: ", t)); diff --git a/engine/client/merged.h b/engine/client/merged.h index 6f071e403..b6ff315ca 100644 --- a/engine/client/merged.h +++ b/engine/client/merged.h @@ -202,7 +202,7 @@ extern int Mod_GetFrameCount (struct model_s *model); extern qboolean Mod_GetTag (struct model_s *model, int tagnum, framestate_t *framestate, float *transforms); extern int Mod_TagNumForName (struct model_s *model, const char *name); -void Mod_AddSingleSurface(struct entity_s *ent, int surfaceidx, shader_t *shader, qboolean normals); +void Mod_AddSingleSurface(struct entity_s *ent, int surfaceidx, shader_t *shader, int mode); int Mod_GetNumBones(struct model_s *model, qboolean allowtags); int Mod_GetBoneRelations(struct model_s *model, int firstbone, int lastbone, framestate_t *fstate, float *result); int Mod_GetBoneParent(struct model_s *model, int bonenum); diff --git a/engine/common/com_mesh.c b/engine/common/com_mesh.c index 404843a25..4f7672dff 100644 --- a/engine/common/com_mesh.c +++ b/engine/common/com_mesh.c @@ -2110,7 +2110,10 @@ qboolean Alias_GAliasBuildMesh(mesh_t *mesh, vbo_t **vbop, galiasinfo_t *inf, in #ifndef SERVERONLY //used by the modelviewer. -void Mod_AddSingleSurface(entity_t *ent, int surfaceidx, shader_t *shader, qboolean normals) +//mode 0: wireframe +//mode 1: normal pegs +//mode 2: 2d projection. +void Mod_AddSingleSurface(entity_t *ent, int surfaceidx, shader_t *shader, int mode) { scenetris_t *t; vecV_t *posedata = NULL; @@ -2165,8 +2168,65 @@ void Mod_AddSingleSurface(entity_t *ent, int surfaceidx, shader_t *shader, qbool m = b->mesh[meshidx]; + if (mode == 2 && m->st_array) + { //2d wireframe (using texture coords instead of modelspace) + if (cl_numstris == cl_maxstris) + { + cl_maxstris+=8; + cl_stris = BZ_Realloc(cl_stris, sizeof(*cl_stris)*cl_maxstris); + } + t = &cl_stris[cl_numstris++]; + t->shader = shader; + t->flags = BEF_LINES; + t->firstidx = cl_numstrisidx; + t->firstvert = cl_numstrisvert; + if (t->flags&BEF_LINES) + t->numidx = m->numindexes*2; + else + t->numidx = m->numindexes; + t->numvert = m->numvertexes; + + if (cl_numstrisidx+t->numidx > cl_maxstrisidx) + { + cl_maxstrisidx=cl_numstrisidx+t->numidx; + cl_strisidx = BZ_Realloc(cl_strisidx, sizeof(*cl_strisidx)*cl_maxstrisidx); + } + if (cl_numstrisvert+m->numvertexes > cl_maxstrisvert) + cl_stris_ExpandVerts(cl_numstrisvert+m->numvertexes); + for (i = 0; i < m->numvertexes; i++) + { + VectorMA(vec3_origin, m->st_array[i][0], ent->axis[0], tmp); + VectorMA(tmp, m->st_array[i][1], ent->axis[1], tmp); + VectorMA(tmp, 0, ent->axis[2], tmp); + VectorMA(ent->origin, ent->scale, tmp, cl_strisvertv[t->firstvert+i]); + + Vector2Set(cl_strisvertt[t->firstvert+i], 0.5, 0.5); + Vector4Set(cl_strisvertc[t->firstvert+i], 1, 1, 1, 0.1); + } + if (t->flags&BEF_LINES) + { + for (i = 0; i < m->numindexes; i+=3) + { + cl_strisidx[cl_numstrisidx++] = m->indexes[i+0]; + cl_strisidx[cl_numstrisidx++] = m->indexes[i+1]; + cl_strisidx[cl_numstrisidx++] = m->indexes[i+1]; + cl_strisidx[cl_numstrisidx++] = m->indexes[i+2]; + cl_strisidx[cl_numstrisidx++] = m->indexes[i+2]; + cl_strisidx[cl_numstrisidx++] = m->indexes[i+0]; + } + } + else + { + for (i = 0; i < m->numindexes; i++) + cl_strisidx[cl_numstrisidx+i] = m->indexes[i]; + cl_numstrisidx += m->numindexes; + } + cl_numstrisvert += m->numvertexes; + continue; + } + posedata = m->xyz_array; - normdata = normals?m->normals_array:NULL; + normdata = (mode==1)?m->normals_array:NULL; #ifdef SKELETALMODELS if (m->numbones) { //intended shader might have caused it to use skeletal stuff. @@ -2199,7 +2259,7 @@ void Mod_AddSingleSurface(entity_t *ent, int surfaceidx, shader_t *shader, qbool posedata = m->xyz_array; } if (normdata) - { + { //show small pegs at each vertex if (cl_numstris == cl_maxstris) { cl_maxstris+=8; @@ -2242,8 +2302,8 @@ void Mod_AddSingleSurface(entity_t *ent, int surfaceidx, shader_t *shader, qbool cl_numstrisidx += i*2; cl_numstrisvert += i*2; } - if (!normals) - { + else if (mode == 0) + { //regular wireframe if (cl_numstris == cl_maxstris) { cl_maxstris+=8; @@ -5541,10 +5601,13 @@ qboolean Mod_FrameInfoForNum(model_t *model, int surfaceidx, int num, char **nam } #ifndef SERVERONLY -shader_t *Mod_ShaderForSkin(model_t *model, int surfaceidx, int num) +shader_t *Mod_ShaderForSkin(model_t *model, int surfaceidx, int num, float time, texnums_t **out_texnums) { galiasinfo_t *inf; galiasskin_t *skin; + skinframe_t *skinframe; + + *out_texnums = NULL; if (!model || model->loadstate != MLS_LOADED) { @@ -5572,7 +5635,12 @@ shader_t *Mod_ShaderForSkin(model_t *model, int surfaceidx, int num) if (!inf || num >= inf->numskins) return NULL; skin = inf->ofsskins; - return skin[num].frame[0].shader; + skin += num; + skinframe = skin->frame; + if (skin->numframes) + skinframe += (int)(time*skin->skinspeed)%skin->numframes; + *out_texnums = &skinframe->texnums; + return skinframe->shader; default: return NULL; } diff --git a/engine/common/com_mesh.h b/engine/common/com_mesh.h index 2488fe2c8..ba29e8cbd 100644 --- a/engine/common/com_mesh.h +++ b/engine/common/com_mesh.h @@ -266,7 +266,7 @@ void Mod_DestroyMesh(galiasinfo_t *galias); void Alias_FlushCache(void); void Alias_Shutdown(void); void Alias_Register(void); -shader_t *Mod_ShaderForSkin(model_t *model, int surfaceidx, int num); +shader_t *Mod_ShaderForSkin(model_t *model, int surfaceidx, int num, float time, texnums_t **out_texnums); const char *Mod_SkinNameForNum(model_t *model, int surfaceidx, int num); const char *Mod_SurfaceNameForNum(model_t *model, int num); const char *Mod_FrameNameForNum(model_t *model, int surfaceidx, int num);