/* <84171> ../engine/r_studio.c:1351 */ void EXT_FUNC GetAttachment(const edict_t *pEdict, int iAttachment, float *rgflOrigin, float *rgflAngles) { mstudioattachment_t *pattachment; vec3_t angles; angles[0] = -pEdict->v.angles[0]; angles[1] = pEdict->v.angles[1]; angles[2] = pEdict->v.angles[2]; pstudiohdr = (studiohdr_t *)Mod_Extradata(g_psv.models[pEdict->v.modelindex]); pattachment = (mstudioattachment_t *)((char *)pstudiohdr + pstudiohdr->attachmentindex); pattachment += iAttachment; g_pSvBlendingAPI->SV_StudioSetupBones( g_psv.models[pEdict->v.modelindex], pEdict->v.frame, pEdict->v.sequence, angles, pEdict->v.origin, pEdict->v.controller, pEdict->v.blending, pattachment->bone, pEdict ); if (rgflOrigin) VectorTransform(pattachment->org, (float *)bonetransform[pattachment->bone], rgflOrigin); }
/* ================ R_AliasDrawModel ================ */ void R_AliasDrawModel(alight_t *plighting) { finalvert_t finalverts[MAXALIASVERTS + ((CACHE_SIZE - 1) / sizeof(finalvert_t)) + 1]; auxvert_t auxverts[MAXALIASVERTS]; r_amodels_drawn++; // cache align pfinalverts = (finalvert_t *) (((long)&finalverts[0] + CACHE_SIZE - 1) & ~(CACHE_SIZE - 1)); pauxverts = &auxverts[0]; paliashdr = (aliashdr_t *)Mod_Extradata(currententity->model); pmdl = (mdl_t *)((byte *)paliashdr + paliashdr->model); R_AliasSetupSkin(); R_AliasSetUpTransform(currententity->trivial_accept); R_AliasSetupLighting(plighting); R_AliasSetupFrame(); if (!currententity->colormap) { Sys_Error("R_AliasDrawModel: !currententity->colormap"); } r_affinetridesc.drawtype = (currententity->trivial_accept == 3) && r_recursiveaffinetriangles; if (r_affinetridesc.drawtype) { D_PolysetUpdateTables(); // FIXME: precalc... } else { #if id386 D_Aff8Patch(currententity->colormap); #endif } acolormap = currententity->colormap; if (currententity != &cl.viewent) { ziscale = (float)0x8000 * (float)0x10000; } else { ziscale = (float)0x8000 * (float)0x10000 * 3.0; } if (currententity->trivial_accept) { R_AliasPrepareUnclippedPoints(); } else { R_AliasPreparePoints(); } }
/* <8402e> ../engine/r_studio.c:1264 */ qboolean SV_CheckSphereIntersection(edict_t *ent, const vec_t *start, const vec_t *end) { studiohdr_t *studiohdr; mstudioseqdesc_t *pseqdesc; vec3_t traceOrg; vec3_t traceDir; float radiusSquared; vec3_t maxDim; radiusSquared = 0.0f; if (!(ent->v.flags & FL_CLIENT)) return 1; traceOrg[0] = start[0]; traceOrg[1] = start[1]; traceOrg[2] = start[2]; traceDir[0] = end[0] - start[0]; traceDir[1] = end[1] - start[1]; traceDir[2] = end[2] - start[2]; studiohdr = (studiohdr_t *)Mod_Extradata(g_psv.models[ent->v.modelindex]); pseqdesc = (mstudioseqdesc_t *)((char *)studiohdr + studiohdr->seqindex); pseqdesc += ent->v.sequence; for (int i = 0; i < 3; i++) { maxDim[i] = max(fabs(pseqdesc->bbmax[i]), fabs(pseqdesc->bbmin[i])); } radiusSquared = maxDim[0] * maxDim[0] + maxDim[1] * maxDim[1] + maxDim[2] * maxDim[2]; return DoesSphereIntersect(ent->v.origin, radiusSquared, traceOrg, traceDir) != 0; }
/* <83a1c> ../engine/r_studio.c:844 */ hull_t *R_StudioHull(model_t *pModel, float frame, int sequence, const vec_t *angles, const vec_t *origin, const vec_t *size, const unsigned char *pcontroller, const unsigned char *pblending, int *pNumHulls, const edict_t *pEdict, int bSkipShield) { SV_InitStudioHull(); if (r_cachestudio.value != 0) { #ifdef SWDS Sys_Error(__FUNCTION__ ": Studio state caching is not used on server"); #endif // TODO: Reverse for client-side } pstudiohdr = (studiohdr_t*)Mod_Extradata(pModel); vec_t angles2[3] = { -angles[0], angles[1], angles[2] }; g_pSvBlendingAPI->SV_StudioSetupBones(pModel, frame, sequence, angles2, origin, pcontroller, pblending, -1, pEdict); mstudiobbox_t* pbbox = (mstudiobbox_t *)((char *)pstudiohdr + pstudiohdr->hitboxindex); for (int i = 0; i < pstudiohdr->numhitboxes; i++) { if (bSkipShield && i == 21) continue; studio_hull_hitgroup[i] = pbbox[i].group; for (int j = 0; j < 3; j++) { mplane_t* plane0 = &studio_planes[i * 6 + j * 2 + 0]; mplane_t* plane1 = &studio_planes[i * 6 + j * 2 + 1]; SV_SetStudioHullPlane(plane0, pbbox[i].bone, j, pbbox[i].bbmax[j]); SV_SetStudioHullPlane(plane1, pbbox[i].bone, j, pbbox[i].bbmin[j]); plane0->dist += fabs(plane0->normal[0] * size[0]) + fabs(plane0->normal[1] * size[1]) + fabs(plane0->normal[2] * size[2]); plane1->dist -= fabs(plane1->normal[0] * size[0]) + fabs(plane1->normal[1] * size[1]) + fabs(plane1->normal[2] * size[2]); } } *pNumHulls = (bSkipShield == 1) ? pstudiohdr->numhitboxes - 1 : pstudiohdr->numhitboxes; if (r_cachestudio.value != 0) { #ifdef SWDS Sys_Error(__FUNCTION__ ": Studio state caching is not used on server"); #endif // TODO: Reverse for client-side // R_AddToStudioCache(float frame, // int sequence, // const vec_t *angles, // const vec_t *origin, // const vec_t *size, // const unsigned char *controller, // const unsigned char *pblending, // model_t *pModel, // hull_t *pHulls, // int numhulls); /* size=0, low_pc=0 */ // 917 } return &studio_hull[0]; }
void R_DrawAliasBatchPass (entity_t **ents, int numents, qbool showtris) { int i; gltexture_t *lasttexture = NULL; gltexture_t *lastfullbright = NULL; if (!numents) return; if (showtris) GL_TexEnv (GL_TEXTURE0_ARB, GL_TEXTURE_2D, GL_REPLACE); else if (gl_overbright.value) GL_TexEnv (GL_TEXTURE0_ARB, GL_TEXTURE_2D, GL_RGB_SCALE_ARB); else GL_TexEnv (GL_TEXTURE0_ARB, GL_TEXTURE_2D, GL_MODULATE); for (i = 0; i < numents; i++) { entity_t *ent = ents[i]; aliasstate_t *state = &ent->aliasstate; aliashdr_t *hdr = Mod_Extradata (ent->model); // we need a separate test for culling here as r_shadows mode doesn't cull if (ent->visframe != r_framecount) continue; if (!showtris && ((state->tx != lasttexture) || (state->fb != lastfullbright))) { if (state->fb) { GL_TexEnv (GL_TEXTURE1_ARB, GL_TEXTURE_2D, GL_ADD); GL_BindTexture (GL_TEXTURE1_ARB, state->fb); } else GL_TexEnv (GL_TEXTURE1_ARB, GL_TEXTURE_2D, GL_NONE); GL_BindTexture (GL_TEXTURE0_ARB, state->tx); lasttexture = state->tx; lastfullbright = state->fb; } // OK, this works better in GL... go figure... R_DrawAliasModel (ent, hdr, state, showtris); } GL_TexEnv (GL_TEXTURE1_ARB, GL_TEXTURE_2D, GL_NONE); GL_TexEnv (GL_TEXTURE0_ARB, GL_TEXTURE_2D, GL_REPLACE); qglColor4f (1, 1, 1, 1); // go back to the world matrix qglLoadMatrixf (r_world_matrix.m16); }
/* ============= GL_DrawAliasShadow -- johnfitz -- rewritten TODO: orient shadow onto "lightplane" (a global mplane_t*) ============= */ void GL_DrawAliasShadow (entity_t *e) { float shadowmatrix[16] = {1, 0, 0, 0, 0, 1, 0, 0, SHADOW_SKEW_X, SHADOW_SKEW_Y, SHADOW_VSCALE, 0, 0, 0, SHADOW_HEIGHT, 1}; float lheight; aliashdr_t *paliashdr; lerpdata_t lerpdata; if (R_CullModelForEntity(e)) return; if (e == &cl.viewent || e->model->flags & MOD_NOSHADOW) return; entalpha = ENTALPHA_DECODE(e->alpha); if (entalpha == 0) return; paliashdr = (aliashdr_t *)Mod_Extradata (e->model); R_SetupAliasFrame (paliashdr, e->frame, &lerpdata); R_SetupEntityTransform (e, &lerpdata); R_LightPoint (e->origin); lheight = currententity->origin[2] - lightspot[2]; // set up matrix glPushMatrix (); glTranslatef (lerpdata.origin[0], lerpdata.origin[1], lerpdata.origin[2]); glTranslatef (0,0,-lheight); glMultMatrixf (shadowmatrix); glTranslatef (0,0,lheight); glRotatef (lerpdata.angles[1], 0, 0, 1); glRotatef (-lerpdata.angles[0], 0, 1, 0); glRotatef (lerpdata.angles[2], 1, 0, 0); glTranslatef (paliashdr->scale_origin[0], paliashdr->scale_origin[1], paliashdr->scale_origin[2]); glScalef (paliashdr->scale[0], paliashdr->scale[1], paliashdr->scale[2]); // draw it glDepthMask(GL_FALSE); glEnable (GL_BLEND); GL_DisableMultitexture (); glDisable (GL_TEXTURE_2D); shading = false; glColor4f(0,0,0,entalpha * 0.5); GL_DrawAliasFrame (paliashdr, lerpdata); glEnable (GL_TEXTURE_2D); glDisable (GL_BLEND); glDepthMask(GL_TRUE); //clean up glPopMatrix (); }
static void PrintFrameName(model_t *m, int frame) { aliashdr_t *hdr; maliasframedesc_t *pframedesc; hdr = Mod_Extradata(m); if (!hdr) return; pframedesc = &hdr->frames[frame]; Con_Printf("frame %i: %s\n", frame, pframedesc->name); }
/* ==================== StudioGetAttachment ==================== */ void Mod_StudioGetAttachment( const edict_t *e, int iAttachment, float *origin, float *angles ) { mstudioattachment_t *pAtt; vec3_t angles2; model_t *mod; mod = Mod_Handle( e->v.modelindex ); mod_studiohdr = (studiohdr_t *)Mod_Extradata( mod ); if( !mod_studiohdr ) return; if( mod_studiohdr->numattachments <= 0 ) return; ASSERT( pBlendAPI != NULL ); if( mod_studiohdr->numattachments > MAXSTUDIOATTACHMENTS ) { mod_studiohdr->numattachments = MAXSTUDIOATTACHMENTS; // reduce it MsgDev( D_WARN, "SV_StudioGetAttahment: too many attachments on %s\n", mod_studiohdr->name ); } iAttachment = bound( 0, iAttachment, mod_studiohdr->numattachments ); // calculate attachment origin and angles pAtt = (mstudioattachment_t *)((byte *)mod_studiohdr + mod_studiohdr->attachmentindex); VectorCopy( e->v.angles, angles2 ); if( !( host.features & ENGINE_COMPENSATE_QUAKE_BUG )) angles2[PITCH] = -angles2[PITCH]; pBlendAPI->SV_StudioSetupBones( mod, e->v.frame, e->v.sequence, angles2, e->v.origin, e->v.controller, e->v.blending, pAtt[iAttachment].bone, e ); // compute pos and angles if( origin != NULL ) Matrix3x4_VectorTransform( studio_bones[pAtt[iAttachment].bone], pAtt[iAttachment].org, origin ); if( sv_allow_studio_attachment_angles->integer && origin != NULL && angles != NULL ) { vec3_t forward, bonepos; Matrix3x4_OriginFromMatrix( studio_bones[pAtt[iAttachment].bone], bonepos ); VectorSubtract( origin, bonepos, forward ); // make forward VectorNormalizeFast( forward ); VectorAngles( forward, angles ); } }
/* ================ GLMesh_LoadVertexBuffers Loop over all precached alias models, and upload each one to a VBO. ================ */ void GLMesh_LoadVertexBuffers (void) { int j; qmodel_t *m; const aliashdr_t *hdr; for (j = 1; j < MAX_MODELS; j++) { if (!(m = cl.model_precache[j])) break; if (m->type != mod_alias) continue; hdr = (const aliashdr_t *) Mod_Extradata (m); GLMesh_LoadVertexBuffer (m, hdr); } }
/* ==================== GetBonePosition ==================== */ void Mod_GetBonePosition( const edict_t *e, int iBone, float *origin, float *angles ) { model_t *mod; mod = Mod_Handle( e->v.modelindex ); mod_studiohdr = (studiohdr_t *)Mod_Extradata( mod ); if( !mod_studiohdr ) return; ASSERT( pBlendAPI != NULL ); pBlendAPI->SV_StudioSetupBones( mod, e->v.frame, e->v.sequence, e->v.angles, e->v.origin, e->v.controller, e->v.blending, iBone, e ); if( origin ) Matrix3x4_OriginFromMatrix( studio_bones[iBone], origin ); if( angles ) VectorAngles( studio_bones[iBone][0], angles ); // bone forward to angles }
/* <83db3> ../engine/r_studio.c:957 */ int R_StudioBodyVariations(model_t *model) { if (model->type != mod_studio) return 0; studiohdr_t *shdr = (studiohdr_t *)Mod_Extradata(model); if (!shdr) return 0; int count = 1; mstudiobodyparts_t *pbodypart = (mstudiobodyparts_t *)((char *)shdr + shdr->bodypartindex); for (int i = 0; i < shdr->numbodyparts; i++, pbodypart++) { count *= pbodypart->nummodels; } return count; }
/* <8411a> ../engine/r_studio.c:1329 */ void EXT_FUNC GetBonePosition(const edict_t *pEdict, int iBone, float *rgflOrigin, float *rgflAngles) { pstudiohdr = (studiohdr_t *)Mod_Extradata(g_psv.models[pEdict->v.modelindex]); g_pSvBlendingAPI->SV_StudioSetupBones( g_psv.models[pEdict->v.modelindex], pEdict->v.frame, pEdict->v.sequence, pEdict->v.angles, pEdict->v.origin, pEdict->v.controller, pEdict->v.blending, iBone, pEdict ); if (rgflOrigin) { rgflOrigin[0] = bonetransform[iBone][0][3]; rgflOrigin[1] = bonetransform[iBone][1][3]; rgflOrigin[2] = bonetransform[iBone][2][3]; } }
/* =========== R_AddEfrags =========== */ void R_AddEfrags( cl_entity_t *ent ) { int i; if( !ent->model ) return; r_addent = ent; lastlink = &ent->efrag; r_pefragtopnode = NULL; // NOTE: can't copy these bounds directly into model->mins\model->maxs // because all other code don't expected this if( ent->model->type == mod_studio ) { studiohdr_t *phdr = (studiohdr_t *)Mod_Extradata( ent->model ); mstudioseqdesc_t *pseqdesc; if( !phdr ) return; pseqdesc = (mstudioseqdesc_t *)((byte *)phdr + phdr->seqindex); for( i = 0; i < 3; i++ ) { r_emins[i] = ent->origin[i] + pseqdesc[0].bbmin[i]; r_emaxs[i] = ent->origin[i] + pseqdesc[0].bbmax[i]; } } else { for( i = 0; i < 3; i++ ) { r_emins[i] = ent->origin[i] + ent->model->mins[i]; r_emaxs[i] = ent->origin[i] + ent->model->maxs[i]; } } R_SplitEntityOnNode( cl.worldmodel->nodes ); ent->topnode = r_pefragtopnode; }
/* ================= R_DrawAliasModel_ShowTris -- johnfitz ================= */ void R_DrawAliasModel_ShowTris (entity_t *e) { aliashdr_t *paliashdr; lerpdata_t lerpdata; if (R_CullModelForEntity(e)) return; paliashdr = (aliashdr_t *)Mod_Extradata (e->model); R_SetupAliasFrame (paliashdr, e->frame, &lerpdata); R_SetupEntityTransform (e, &lerpdata); glPushMatrix (); R_RotateForEntity (lerpdata.origin,lerpdata.angles); glTranslatef (paliashdr->scale_origin[0], paliashdr->scale_origin[1], paliashdr->scale_origin[2]); glScalef (paliashdr->scale[0], paliashdr->scale[1], paliashdr->scale[2]); shading = false; glColor3f(1,1,1); GL_DrawAliasFrame (paliashdr, lerpdata); glPopMatrix (); }
/* ==================== CL_AllocRemapInfo Allocate new remap info per entity and make copy of remap textures ==================== */ void CL_AllocRemapInfo( int topcolor, int bottomcolor ) { remap_info_t *info; studiohdr_t *phdr; mstudiotexture_t *src, *dst; int i, size; if( !RI.currententity ) return; i = ( RI.currententity == &clgame.viewent ) ? clgame.maxEntities : RI.currententity->curstate.number; if( !RI.currentmodel || RI.currentmodel->type != mod_studio ) { // entity has changed model by another type, release remap info if( clgame.remap_info[i] ) { CL_FreeRemapInfo( clgame.remap_info[i] ); clgame.remap_info[i] = NULL; } return; // missed or hide model, ignore it } // model doesn't contains remap textures if( RI.currentmodel->numtextures <= 0 ) { // entity has changed model with no remap textures if( clgame.remap_info[i] ) { CL_FreeRemapInfo( clgame.remap_info[i] ); clgame.remap_info[i] = NULL; } return; } phdr = (studiohdr_t *)Mod_Extradata( RI.currentmodel ); if( !phdr ) return; // missed header ??? src = (mstudiotexture_t *)(((byte *)phdr) + phdr->textureindex); dst = (clgame.remap_info[i] ? clgame.remap_info[i]->ptexture : NULL); // NOTE: we must copy all the structures 'mstudiotexture_t' for easy access when model is rendering if( !CL_CmpStudioTextures( phdr->numtextures, src, dst ) || clgame.remap_info[i]->model != RI.currentmodel ) { // this code catches studiomodel change with another studiomodel with remap textures // e.g. playermodel 'barney' with playermodel 'gordon' if( clgame.remap_info[i] ) CL_FreeRemapInfo( clgame.remap_info[i] ); // free old info size = sizeof( remap_info_t ) + ( sizeof( mstudiotexture_t ) * phdr->numtextures ); info = clgame.remap_info[i] = Mem_Alloc( clgame.mempool, size ); info->ptexture = (mstudiotexture_t *)(info + 1); // textures are immediately comes after remap_info } else { // studiomodel is valid, nothing to change return; } info->numtextures = phdr->numtextures; info->model = RI.currentmodel; info->topcolor = topcolor; info->bottomcolor = bottomcolor; src = (mstudiotexture_t *)(((byte *)phdr) + phdr->textureindex); dst = info->ptexture; // copy unchanged first Q_memcpy( dst, src, sizeof( mstudiotexture_t ) * phdr->numtextures ); // make local copies for remap textures for( i = 0; i < info->numtextures; i++ ) { if( dst[i].flags & STUDIO_NF_COLORMAP ) CL_DuplicateTexture( &dst[i], topcolor, bottomcolor ); } }
/* ================ R_AliasCheckBBox ================ */ qboolean R_AliasCheckBBox(void) { int i, flags, frame, numv; aliashdr_t *pahdr; float zi, basepts[8][3], v0, v1, frac; finalvert_t *pv0, *pv1, viewpts[16]; auxvert_t *pa0, *pa1, viewaux[16]; maliasframedesc_t *pframedesc; qboolean zclipped, zfullyclipped; unsigned anyclip, allclip; int minz; // expand, rotate, and translate points into worldspace currententity->trivial_accept = 0; pmodel = currententity->model; pahdr = Mod_Extradata(pmodel); pmdl = (mdl_t *)((byte *)pahdr + pahdr->model); R_AliasSetUpTransform(0); // construct the base bounding box for this frame frame = currententity->frame; // TODO: don't repeat this check when drawing? if ((frame >= pmdl->numframes) || (frame < 0)) { Con_DPrintf("No such frame %d %s\n", frame, pmodel->name); frame = 0; } pframedesc = &pahdr->frames[frame]; // x worldspace coordinates basepts[0][0] = basepts[1][0] = basepts[2][0] = basepts[3][0] = (float)pframedesc->bboxmin.v[0]; basepts[4][0] = basepts[5][0] = basepts[6][0] = basepts[7][0] = (float)pframedesc->bboxmax.v[0]; // y worldspace coordinates basepts[0][1] = basepts[3][1] = basepts[5][1] = basepts[6][1] = (float)pframedesc->bboxmin.v[1]; basepts[1][1] = basepts[2][1] = basepts[4][1] = basepts[7][1] = (float)pframedesc->bboxmax.v[1]; // z worldspace coordinates basepts[0][2] = basepts[1][2] = basepts[4][2] = basepts[5][2] = (float)pframedesc->bboxmin.v[2]; basepts[2][2] = basepts[3][2] = basepts[6][2] = basepts[7][2] = (float)pframedesc->bboxmax.v[2]; zclipped = false; zfullyclipped = true; minz = 9999; for (i=0; i<8 ; i++) { R_AliasTransformVector(&basepts[i][0], &viewaux[i].fv[0]); if (viewaux[i].fv[2] < ALIAS_Z_CLIP_PLANE) { // we must clip points that are closer than the near clip plane viewpts[i].flags = ALIAS_Z_CLIP; zclipped = true; } else { if (viewaux[i].fv[2] < minz) { minz = viewaux[i].fv[2]; } viewpts[i].flags = 0; zfullyclipped = false; } } if (zfullyclipped) { return false; // everything was near-z-clipped } numv = 8; if (zclipped) { // organize points by edges, use edges to get new points (possible trivial // reject) for (i=0 ; i<12 ; i++) { // edge endpoints pv0 = &viewpts[aedges[i].index0]; pv1 = &viewpts[aedges[i].index1]; pa0 = &viewaux[aedges[i].index0]; pa1 = &viewaux[aedges[i].index1]; // if one end is clipped and the other isn't, make a new point if (pv0->flags ^ pv1->flags) { frac = (ALIAS_Z_CLIP_PLANE - pa0->fv[2]) / (pa1->fv[2] - pa0->fv[2]); viewaux[numv].fv[0] = pa0->fv[0] + (pa1->fv[0] - pa0->fv[0]) * frac; viewaux[numv].fv[1] = pa0->fv[1] + (pa1->fv[1] - pa0->fv[1]) * frac; viewaux[numv].fv[2] = ALIAS_Z_CLIP_PLANE; viewpts[numv].flags = 0; numv++; } } } // project the vertices that remain after clipping anyclip = 0; allclip = ALIAS_XY_CLIP_MASK; // TODO: probably should do this loop in ASM, especially if we use floats for (i=0 ; i<numv ; i++) { // we don't need to bother with vertices that were z-clipped if (viewpts[i].flags & ALIAS_Z_CLIP) { continue; } zi = 1.0 / viewaux[i].fv[2]; // FIXME: do with chop mode in ASM, or convert to float v0 = (viewaux[i].fv[0] * xscale * zi) + xcenter; v1 = (viewaux[i].fv[1] * yscale * zi) + ycenter; flags = 0; if (v0 < r_refdef.fvrectx) { flags |= ALIAS_LEFT_CLIP; } if (v1 < r_refdef.fvrecty) { flags |= ALIAS_TOP_CLIP; } if (v0 > r_refdef.fvrectright) { flags |= ALIAS_RIGHT_CLIP; } if (v1 > r_refdef.fvrectbottom) { flags |= ALIAS_BOTTOM_CLIP; } anyclip |= flags; allclip &= flags; } if (allclip) { return false; // trivial reject off one side } currententity->trivial_accept = !anyclip & !zclipped; if (currententity->trivial_accept) { if (minz > (r_aliastransition + (pmdl->size * r_resfudge))) { currententity->trivial_accept |= 2; } } return true; }
/* ================= R_DrawQ3Model Modified Dr Labmans md3 code splitting it up to make it easier to add dynamic lighting code ================= */ void R_DrawQ3Model (entity_t *e) { md3header_t *header; //md3shader_t *shader; md3surface_t *surf; /* if (!gl_notrans.value) // always true if not -nehahra { r_modelalpha = e->transparency; if (r_modelalpha == 0) r_modelalpha = 1.0; } else { r_modelalpha = 1.0; } */ /*************** FIXME: combine with alias model code! ***************/ R_CalcMD3Lighting (e, e->model); // Get the model data header = (md3header_t *)Mod_Extradata (e->model); // locate the proper data "huh surface related"! surf = (md3surface_t *)((byte *)header + header->surface_offs); c_alias_polys += surf->num_surf_tris; /*******JDH******* //get pointer to shaders shader = (md3shader_t *)((byte *)surf + surf->shader_offs); //shaders = shader[(currententity->skinnum%surf->num_surf_shaders)].texnum; shaders = shader[ e->skinnum % surf->num_surf_shaders ].index; if (shaders) { GL_Bind(shaders); } else { GL_Bind(0); } *******JDH*******/ glPushMatrix(); //interpolate unless its the viewmodel if (gl_interpolate_animation.value && (e != &cl.viewent)) { R_BlendedRotateForEntity (e); } else { R_RotateForEntity (e); } if (gl_smoothmodels.value) glShadeModel (GL_SMOOTH); if (gl_affinemodels.value) glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST); R_SetupQ3AliasFrame (e->frame, header, e, gl_mtexable); glShadeModel (GL_FLAT); if (gl_affinemodels.value) glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); glPopMatrix(); }
void R_DrawAliasModel(entity_t *e) { extern void AddFire(vec3_t org, float size); int lnum; vec3_t dist; float add; model_t *clmodel; vec3_t mins, maxs; aliashdr_t *paliashdr; float an; //s, t, int anim; md2_t *pheader; // LH / muff int shell; //QMB :model shells //not implemented yet // byte c, *color; //QMB :color map //does the model need a shell? if (cl.items & IT_QUAD && e == &cl.viewent) shell = true; else shell = false; //set get the model from the e clmodel = e->model; //work out its max and mins VectorAdd(e->origin, clmodel->mins, mins); VectorAdd(e->origin, clmodel->maxs, maxs); //make sure its in screen if (R_CullBox(mins, maxs) && e != &cl.viewent) return; //QMB: FIXME //should use a particle emitter linked to the model for its org //needs to be linked when the model is created and distroyed when //the entity is distroyed //check if its a fire and add the particle effect if (!strcmp(clmodel->name, "progs/flame.mdl")) AddFire(e->origin, 4); if (!strcmp(clmodel->name, "progs/flame2.mdl")) { AddFire(e->origin, 10); return; //do not draw the big fire model, its just a place holder for the particles } // get lighting information //QMB: FIXME //SHOULD CHANGE TO A PASSED VAR //get vertex normals (for lighting and shells) shadedots = r_avertexnormal_dots[((int) (e->angles[1] * (SHADEDOT_QUANT / 360.0))) & (SHADEDOT_QUANT - 1)]; //make a default lighting direction an = e->angles[1] / 180 * M_PI; shadevector[0] = cos(-an); shadevector[1] = sin(-an); shadevector[2] = 1; //e->angles[0]; VectorNormalize(shadevector); //get the light for the model R_LightPoint(e->origin); // LordHavoc: lightcolor is all that matters from this //work out lighting from the dynamic lights for (lnum = 0; lnum < MAX_DLIGHTS; lnum++) { //if the light is alive if (cl_dlights[lnum].die >= cl.time) { //work out the distance to the light VectorSubtract(e->origin, cl_dlights[lnum].origin, dist); add = cl_dlights[lnum].radius - VectorLength(dist); //if its close enough add light from it if (add > 0) { lightcolor[0] += add * cl_dlights[lnum].colour[0]; lightcolor[1] += add * cl_dlights[lnum].colour[1]; lightcolor[2] += add * cl_dlights[lnum].colour[2]; } } } //scale lighting to floating point VectorScale(lightcolor, 1.0f / 200.0f, lightcolor); // locate the proper data glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); if (gl_n_patches && gl_npatches.getBool()) { glEnable(GL_PN_TRIANGLES_ATI); glPNTrianglesiATI(GL_PN_TRIANGLES_TESSELATION_LEVEL_ATI, gl_npatches.getInt()); if (true) glPNTrianglesiATI(GL_PN_TRIANGLES_POINT_MODE_ATI, GL_PN_TRIANGLES_POINT_MODE_CUBIC_ATI); else glPNTrianglesiATI(GL_PN_TRIANGLES_POINT_MODE_ATI, GL_PN_TRIANGLES_POINT_MODE_LINEAR_ATI); if (true) glPNTrianglesiATI(GL_PN_TRIANGLES_NORMAL_MODE_ATI, GL_PN_TRIANGLES_NORMAL_MODE_QUADRATIC_ATI); else glPNTrianglesiATI(GL_PN_TRIANGLES_NORMAL_MODE_ATI, GL_PN_TRIANGLES_NORMAL_MODE_LINEAR_ATI); } if (clmodel->aliastype == MD3IDHEADER) { //do nothing for testing if (!r_modeltexture.getBool()) { GL_DisableTMU(GL_TEXTURE0_ARB); }//disable texture if needed R_DrawQ3Model(e, false, false); if (!r_modeltexture.getBool()) { GL_EnableTMU(GL_TEXTURE0_ARB); }//enable texture if needed if (r_celshading.getBool() || r_outline.getBool()) { glCullFace(GL_BACK); glEnable(GL_BLEND); glPolygonMode(GL_FRONT, GL_LINE); if (e == &cl.viewent) { glLineWidth(1.0f); } else { glLineWidth(5.0f); } glEnable(GL_LINE_SMOOTH); GL_DisableTMU(GL_TEXTURE0_ARB); glColor3f(0.0, 0.0, 0.0); R_DrawQ3Model(e, false, true); glColor3f(1.0, 1.0, 1.0); GL_EnableTMU(GL_TEXTURE0_ARB); glPolygonMode(GL_FRONT, GL_FILL); glDisable(GL_BLEND); glCullFace(GL_FRONT); } if (shell) { glBindTexture(GL_TEXTURE_2D, quadtexture); glColor4f(1.0, 1.0, 1.0, 0.5); glEnable(GL_BLEND); R_DrawQ3Model(e, true, false); glDisable(GL_BLEND); glColor3f(1.0, 1.0, 1.0); } } else if (clmodel->aliastype != ALIASTYPE_MD2) { paliashdr = (aliashdr_t *) Mod_Extradata(e->model); c_alias_polys += paliashdr->numtris; glPushMatrix(); //interpolate unless its the viewmodel if (e != &cl.viewent) R_BlendedRotateForEntity(e); else R_RotateForEntity(e); glTranslatef(paliashdr->scale_origin[0], paliashdr->scale_origin[1], paliashdr->scale_origin[2]); glScalef(paliashdr->scale[0], paliashdr->scale[1], paliashdr->scale[2]); anim = (int) (cl.time * 10) & 3; glBindTexture(GL_TEXTURE_2D, paliashdr->gl_texturenum[e->skinnum][anim]); // draw all the triangles if (!r_modeltexture.getBool()) { GL_DisableTMU(GL_TEXTURE0_ARB); } else { //highlighting test code if (0 && gl_textureunits > 2) { GL_EnableTMU(GL_TEXTURE1_ARB); glBindTexture(GL_TEXTURE_2D, TextureManager::highlighttexture); glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); glEnable(GL_TEXTURE_GEN_S); glEnable(GL_TEXTURE_GEN_T); //need correct mode glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT); glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_ADD); glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_EXT, 1.0); //glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_ADD); } } glColor3fv(lightcolor); R_SetupAliasBlendedFrame(e->frame, paliashdr, e, false, false); glDisable(GL_TEXTURE_1D); if (r_celshading.getBool() || r_outline.getBool()) { glColor3f(0.0, 0.0, 0.0); R_SetupAliasBlendedFrame(e->frame, paliashdr, e, false, true); glColor3f(1.0, 1.0, 1.0); } if (!r_modeltexture.getBool()) { GL_EnableTMU(GL_TEXTURE0_ARB); } else { if (0 && gl_textureunits > 2) { //highlighting test code glDisable(GL_TEXTURE_GEN_S); glDisable(GL_TEXTURE_GEN_T); GL_DisableTMU(GL_TEXTURE1_ARB); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); } } glActiveTexture(GL_TEXTURE0_ARB); //colour map code... not working yet... /* if (e->colormap != vid.colormap && !gl_nocolors.value) { if (paliashdr->gl_texturenumColorMap&&paliashdr->gl_texturenumColorMap){ glBindTexture(GL_TEXTURE_2D,paliashdr->gl_texturenumColorMap); c = (byte)e->colormap & 0xF0; c += (c >= 128 && c < 224) ? 4 : 12; // 128-224 are backwards ranges color = (byte *) (&d_8to24table[c]); //glColor3fv(color); glColor3f(1.0,1.0,1.0); } }*/ if (shell) { glBindTexture(GL_TEXTURE_2D, quadtexture); glColor4f(1.0, 1.0, 1.0, 0.5); glEnable(GL_BLEND); R_SetupAliasBlendedFrame(e->frame, paliashdr, e, true, false); glDisable(GL_BLEND); glColor3f(1.0, 1.0, 1.0); } glPopMatrix(); } else { pheader = (md2_t *) Mod_Extradata(e->model); c_alias_polys += pheader->num_tris; glBindTexture(GL_TEXTURE_2D, pheader->gl_texturenum[e->skinnum]); R_SetupQ2AliasFrame(e, pheader); } if (gl_n_patches && gl_npatches.getBool()) { glDisable(GL_PN_TRIANGLES_ATI); } glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); }
/* ================= R_DrawAliasModel -- johnfitz -- almost completely rewritten ================= */ void R_DrawAliasModel (entity_t *e) { aliashdr_t *paliashdr; int i, anim; gltexture_t *tx, *fb; lerpdata_t lerpdata; // // setup pose/lerp data -- do it first so we don't miss updates due to culling // paliashdr = (aliashdr_t *)Mod_Extradata (e->model); R_SetupAliasFrame (paliashdr, e->frame, &lerpdata); R_SetupEntityTransform (e, &lerpdata); // // cull it // if (R_CullModelForEntity(e)) return; // // transform it // glPushMatrix (); R_RotateForEntity (lerpdata.origin, lerpdata.angles); glTranslatef (paliashdr->scale_origin[0], paliashdr->scale_origin[1], paliashdr->scale_origin[2]); glScalef (paliashdr->scale[0], paliashdr->scale[1], paliashdr->scale[2]); // // random stuff // if (gl_smoothmodels.value && !r_drawflat_cheatsafe) glShadeModel (GL_SMOOTH); if (gl_affinemodels.value) glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST); overbright = gl_overbright_models.value; shading = true; // // set up for alpha blending // if (r_drawflat_cheatsafe || r_lightmap_cheatsafe) //no alpha in drawflat or lightmap mode entalpha = 1; else entalpha = ENTALPHA_DECODE(e->alpha); if (entalpha == 0) goto cleanup; if (entalpha < 1) { if (!gl_texture_env_combine) overbright = false; //overbright can't be done in a single pass without combiners glDepthMask(GL_FALSE); glEnable(GL_BLEND); } // // set up lighting // rs_aliaspolys += paliashdr->numtris; R_SetupAliasLighting (e); // // set up textures // GL_DisableMultitexture(); anim = (int)(cl.time*10) & 3; tx = paliashdr->gltextures[e->skinnum][anim]; fb = paliashdr->fbtextures[e->skinnum][anim]; if (e->colormap != vid.colormap && !gl_nocolors.value) { i = e - cl_entities; if (i >= 1 && i<=cl.maxclients /* && !strcmp (currententity->model->name, "progs/player.mdl") */) tx = playertextures[i - 1]; } if (!gl_fullbrights.value) fb = NULL; // // draw it // if (r_drawflat_cheatsafe) { glDisable (GL_TEXTURE_2D); GL_DrawAliasFrame (paliashdr, lerpdata); glEnable (GL_TEXTURE_2D); srand((int) (cl.time * 1000)); //restore randomness } else if (r_fullbright_cheatsafe) { GL_Bind (tx); shading = false; glColor4f(1,1,1,entalpha); GL_DrawAliasFrame (paliashdr, lerpdata); if (fb) { glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); GL_Bind(fb); glEnable(GL_BLEND); glBlendFunc (GL_ONE, GL_ONE); glDepthMask(GL_FALSE); glColor3f(entalpha,entalpha,entalpha); Fog_StartAdditive (); GL_DrawAliasFrame (paliashdr, lerpdata); Fog_StopAdditive (); glDepthMask(GL_TRUE); glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glDisable(GL_BLEND); } } else if (r_lightmap_cheatsafe) { glDisable (GL_TEXTURE_2D); shading = false; glColor3f(1,1,1); GL_DrawAliasFrame (paliashdr, lerpdata); glEnable (GL_TEXTURE_2D); } else if (overbright) { if (gl_texture_env_combine && gl_mtexable && gl_texture_env_add && fb) //case 1: everything in one pass { GL_Bind (tx); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_MODULATE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_TEXTURE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_PRIMARY_COLOR_EXT); glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_EXT, 2.0f); GL_EnableMultitexture(); // selects TEXTURE1 GL_Bind (fb); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_ADD); glEnable(GL_BLEND); GL_DrawAliasFrame (paliashdr, lerpdata); glDisable(GL_BLEND); GL_DisableMultitexture(); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); } else if (gl_texture_env_combine) //case 2: overbright in one pass, then fullbright pass { // first pass GL_Bind(tx); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_MODULATE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_TEXTURE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_PRIMARY_COLOR_EXT); glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_EXT, 2.0f); GL_DrawAliasFrame (paliashdr, lerpdata); glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_EXT, 1.0f); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); // second pass if (fb) { glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); GL_Bind(fb); glEnable(GL_BLEND); glBlendFunc (GL_ONE, GL_ONE); glDepthMask(GL_FALSE); shading = false; glColor3f(entalpha,entalpha,entalpha); Fog_StartAdditive (); GL_DrawAliasFrame (paliashdr, lerpdata); Fog_StopAdditive (); glDepthMask(GL_TRUE); glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glDisable(GL_BLEND); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); } } else //case 3: overbright in two passes, then fullbright pass { // first pass GL_Bind(tx); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); GL_DrawAliasFrame (paliashdr, lerpdata); // second pass -- additive with black fog, to double the object colors but not the fog color glEnable(GL_BLEND); glBlendFunc (GL_ONE, GL_ONE); glDepthMask(GL_FALSE); Fog_StartAdditive (); GL_DrawAliasFrame (paliashdr, lerpdata); Fog_StopAdditive (); glDepthMask(GL_TRUE); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glDisable(GL_BLEND); // third pass if (fb) { glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); GL_Bind(fb); glEnable(GL_BLEND); glBlendFunc (GL_ONE, GL_ONE); glDepthMask(GL_FALSE); shading = false; glColor3f(entalpha,entalpha,entalpha); Fog_StartAdditive (); GL_DrawAliasFrame (paliashdr, lerpdata); Fog_StopAdditive (); glDepthMask(GL_TRUE); glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glDisable(GL_BLEND); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); } } } else { if (gl_mtexable && gl_texture_env_add && fb) //case 4: fullbright mask using multitexture { GL_DisableMultitexture(); // selects TEXTURE0 GL_Bind (tx); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); GL_EnableMultitexture(); // selects TEXTURE1 GL_Bind (fb); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_ADD); glEnable(GL_BLEND); GL_DrawAliasFrame (paliashdr, lerpdata); glDisable(GL_BLEND); GL_DisableMultitexture(); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); } else //case 5: fullbright mask without multitexture { // first pass GL_Bind(tx); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); GL_DrawAliasFrame (paliashdr, lerpdata); // second pass if (fb) { GL_Bind(fb); glEnable(GL_BLEND); glBlendFunc (GL_ONE, GL_ONE); glDepthMask(GL_FALSE); shading = false; glColor3f(entalpha,entalpha,entalpha); Fog_StartAdditive (); GL_DrawAliasFrame (paliashdr, lerpdata); Fog_StopAdditive (); glDepthMask(GL_TRUE); glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glDisable(GL_BLEND); } } } cleanup: glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); glShadeModel (GL_FLAT); glDepthMask(GL_TRUE); glDisable(GL_BLEND); glColor3f(1,1,1); glPopMatrix (); }
void R_SetupAliasModel (entity_t *e) { aliashdr_t *paliashdr; int anim; aliasstate_t *state = &e->aliasstate; // initially not visible e->visframe = -1; // setup pose/lerp data -- do it first so we don't miss updates due to culling paliashdr = (aliashdr_t *) Mod_Extradata (e->model); R_SetupAliasFrame (e, paliashdr, e->frame, state); R_SetupEntityTransform (e, state); R_BBoxForEnt (e); // cull it (the viewmodel is never culled) if (r_shadows.value > 0.01f) { if (!(e->renderfx & RF_WEAPONMODEL)) { if (R_CullBox (e->mins, e->maxs)) e->visframe = -1; else e->visframe = r_framecount; } } else { if (!(e->renderfx & RF_WEAPONMODEL)) { if (R_CullBox (e->mins, e->maxs)) return; } // the ent is visible now e->visframe = r_framecount; } // set up lighting overbright = gl_overbright.value; rs_aliaspolys += paliashdr->numtris; R_SetupAliasLighting (e, state->shadelight); // store out the alpha value state->shadelight[3] = ((float) e->alpha / 255.0f); // set up textures anim = (int) (cl.time * 10) & 3; state->tx = paliashdr->gltextures[e->skinnum][anim]; // ensure we have a valid texture if (!state->tx) state->tx = notexture; if (!gl_fullbrights.value) state->fb = NULL; else state->fb = paliashdr->fbtextures[e->skinnum][anim]; if (e->colormap && (e->model->modhint == MOD_PLAYER || e->renderfx & RF_PLAYERMODEL) && !gl_nocolors.value) R_GetTranslatedPlayerSkin (e->colormap, &state->tx, &state->fb); }
void R_DrawAliasShadows (entity_t **ents, int numents, void *meshbuffer) { if (r_shadows.value > 0.01f) { int i; qbool stateset = false; byte shadecolor[4] = {0, 0, 0, 128}; // extern int gl_stencilbits; for (i = 0; i < numents; i++) { entity_t *ent = ents[i]; glmatrix eshadow; if (!(ent->model->flags & MOD_NOSHADOW)) { aliasstate_t *state = &ent->aliasstate; aliashdr_t *hdr = Mod_Extradata (ent->model); float lheight = state->origin[2] - state->lightspot[2]; if (!stateset) { float *mesh = (float *) meshbuffer; qglDepthMask (GL_FALSE); qglEnable (GL_BLEND); GL_TexEnv (GL_TEXTURE1_ARB, GL_TEXTURE_2D, GL_NONE); GL_TexEnv (GL_TEXTURE0_ARB, GL_TEXTURE_2D, GL_NONE); qglColor4f (0, 0, 0, r_shadows.value); shadecolor[3] = BYTE_CLAMPF (r_shadows.value); /* if (gl_stencilbits) { qglEnable (GL_STENCIL_TEST); qglStencilFunc (GL_EQUAL, 1, 2); qglStencilOp (GL_KEEP, GL_KEEP, GL_INCR); } */ GL_SetStreamSource (GLSTREAM_POSITION, 3, GL_FLOAT, sizeof (float) * 4, mesh); GL_SetStreamSource (GLSTREAM_COLOR, 4, GL_UNSIGNED_BYTE, sizeof (float) * 4, &mesh[3]); GL_SetStreamSource (GLSTREAM_TEXCOORD0, 0, GL_NONE, 0, NULL); GL_SetStreamSource (GLSTREAM_TEXCOORD1, 0, GL_NONE, 0, NULL); GL_SetStreamSource (GLSTREAM_TEXCOORD2, 0, GL_NONE, 0, NULL); stateset = true; } GL_LoadMatrix (&eshadow, &r_world_matrix); if (state->origin[0] || state->origin[1] || state->origin[2]) GL_TranslateMatrix (&eshadow, state->origin[0], state->origin[1], state->origin[2]); GL_TranslateMatrix (&eshadow, 0, 0, -lheight); GL_MultiplyMatrix (&eshadow, &shadowmatrix, &eshadow); GL_TranslateMatrix (&eshadow, 0, 0, lheight); if (state->angles[1]) GL_RotateMatrix (&eshadow, state->angles[1], 0, 0, 1); GL_TranslateMatrix (&eshadow, hdr->scale_origin[0], hdr->scale_origin[1], hdr->scale_origin[2]); GL_ScaleMatrix (&eshadow, hdr->scale[0], hdr->scale[1], hdr->scale[2]); qglLoadMatrixf (eshadow.m16); R_DrawAliasShadow (ent, hdr, state, (float *) meshbuffer, (float *) shadecolor); } } if (stateset) { /* if (gl_stencilbits) qglDisable (GL_STENCIL_TEST); */ GL_TexEnv (GL_TEXTURE0_ARB, GL_TEXTURE_2D, GL_REPLACE); qglDisable (GL_BLEND); qglDepthMask (GL_TRUE); qglColor4f (1, 1, 1, 1); qglLoadMatrixf (r_world_matrix.m16); } } }
/* ================ R_AliasDrawModel ================ */ void R_AliasDrawModel (alight_t *plighting) { finalvert_t finalverts[MAXALIASVERTS + ((CACHE_SIZE - 1) / sizeof(finalvert_t)) + 1]; auxvert_t auxverts[MAXALIASVERTS]; // finalvert_t *finalverts; // auxvert_t *auxverts; //Anders> Change malloc to static allocated memory to avoid malloc? // finalverts = malloc( (sizeof(finalvert_t)*MAXALIASVERTS) + (sizeof(finalvert_t)*(((CACHE_SIZE - 1) / sizeof(finalvert_t)) + 1))); // auxverts = malloc( (sizeof(finalvert_t)*MAXALIASVERTS)); GpError("R_AliasDrawModel A",11); r_amodels_drawn++; // cache align pfinalverts = (finalvert_t *) (((long)&finalverts[0] + CACHE_SIZE - 1) & ~(CACHE_SIZE - 1)); pauxverts = &auxverts[0]; GpError("R_AliasDrawModel B",11); paliashdr = (aliashdr_t *)Mod_Extradata (currententity->model); pmdl = (mdl_t *)((byte *)paliashdr + paliashdr->model); GpError("R_AliasDrawModel C",11); R_AliasSetupSkin (); GpError("R_AliasDrawModel D",11); R_AliasSetUpTransform (currententity->trivial_accept); GpError("R_AliasDrawModel E",11); R_AliasSetupLighting (plighting); GpError("R_AliasDrawModel F",11); R_AliasSetupFrame (); GpError("R_AliasDrawModel G",11); if (!currententity->colormap) Sys_Error ("R_AliasDrawModel: !currententity->colormap"); r_affinetridesc.drawtype = (currententity->trivial_accept == 3) && r_recursiveaffinetriangles; if (r_affinetridesc.drawtype) { GpError("R_AliasDrawModel H",11); D_PolysetUpdateTables (); // FIXME: precalc... } else { #if id386 D_Aff8Patch (currententity->colormap); #endif } acolormap = currententity->colormap; if (currententity != &cl.viewent) ziscale = (float)0x8000 * (float)0x10000; else ziscale = (float)0x8000 * (float)0x10000 * 3.0; if (currententity->trivial_accept){ GpError("R_AliasDrawModel I",11); R_AliasPrepareUnclippedPoints (); } else{ GpError("R_AliasDrawModel J",11); R_AliasPreparePoints (); } // free(finalverts); // free(auxverts); GpError("R_AliasDrawModel end",11); }
/* ================= R_DrawAliasModel ================= */ void R_DrawAliasModel (entity_t *e) { int i, j; int lnum; vec3_t dist; float add; model_t *clmodel; vec3_t mins, maxs; aliashdr_t *paliashdr; trivertx_t *verts, *v; int index; float s, t, an; int anim; clmodel = currententity->model; VectorAdd (currententity->origin, clmodel->mins, mins); VectorAdd (currententity->origin, clmodel->maxs, maxs); if (R_CullBox (mins, maxs)) return; VectorCopy (currententity->origin, r_entorigin); VectorSubtract (r_origin, r_entorigin, modelorg); // // get lighting information // ambientlight = shadelight = R_LightPoint (currententity->origin); // allways give the gun some light if (e == &cl.viewent && ambientlight < 24) ambientlight = shadelight = 24; for (lnum=0 ; lnum<MAX_DLIGHTS ; lnum++) { if (cl_dlights[lnum].die >= cl.time) { VectorSubtract (currententity->origin, cl_dlights[lnum].origin, dist); add = cl_dlights[lnum].radius - Length(dist); if (add > 0) { ambientlight += add; //ZOID models should be affected by dlights as well shadelight += add; } } } // clamp lighting so it doesn't overbright as much if (ambientlight > 128) ambientlight = 128; if (ambientlight + shadelight > 192) shadelight = 192 - ambientlight; // ZOID: never allow players to go totally black i = currententity - cl_entities; if (i >= 1 && i<=cl.maxclients /* && !strcmp (currententity->model->name, "progs/player.mdl") */) if (ambientlight < 8) ambientlight = shadelight = 8; // HACK HACK HACK -- no fullbright colors, so make torches full light if (!strcmp (clmodel->name, "progs/flame2.mdl") || !strcmp (clmodel->name, "progs/flame.mdl") ) ambientlight = shadelight = 256; shadedots = r_avertexnormal_dots[((int)(e->angles[1] * (SHADEDOT_QUANT / 360.0))) & (SHADEDOT_QUANT - 1)]; shadelight = shadelight / 200.0; an = e->angles[1]/180*M_PI; shadevector[0] = cos(-an); shadevector[1] = sin(-an); shadevector[2] = 1; VectorNormalize (shadevector); // // locate the proper data // paliashdr = (aliashdr_t *)Mod_Extradata (currententity->model); c_alias_polys += paliashdr->numtris; // // draw all the triangles // GL_DisableMultitexture(); glPushMatrix (); R_RotateForEntity (e); if (!strcmp (clmodel->name, "progs/eyes.mdl") && gl_doubleeyes.value) { glTranslatef (paliashdr->scale_origin[0], paliashdr->scale_origin[1], paliashdr->scale_origin[2] - (22 + 8)); // double size of eyes, since they are really hard to see in gl glScalef (paliashdr->scale[0]*2, paliashdr->scale[1]*2, paliashdr->scale[2]*2); } else { glTranslatef (paliashdr->scale_origin[0], paliashdr->scale_origin[1], paliashdr->scale_origin[2]); glScalef (paliashdr->scale[0], paliashdr->scale[1], paliashdr->scale[2]); } anim = (int)(cl.time*10) & 3; GL_Bind(paliashdr->gl_texturenum[currententity->skinnum][anim]); // we can't dynamically colormap textures, so they are cached // seperately for the players. Heads are just uncolored. if (currententity->colormap != vid.colormap && !gl_nocolors.value) { i = currententity - cl_entities; if (i >= 1 && i<=cl.maxclients /* && !strcmp (currententity->model->name, "progs/player.mdl") */) GL_Bind(playertextures - 1 + i); } if (gl_smoothmodels.value) glShadeModel (GL_SMOOTH); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); if (gl_affinemodels.value) glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST); R_SetupAliasFrame (currententity->frame, paliashdr); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); glShadeModel (GL_FLAT); if (gl_affinemodels.value) glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); glPopMatrix (); if (r_shadows.value) { glPushMatrix (); R_RotateForEntity (e); glDisable (GL_TEXTURE_2D); glEnable (GL_BLEND); glColor4f (0,0,0,0.5); GL_DrawAliasShadow (paliashdr, lastposenum); glEnable (GL_TEXTURE_2D); glDisable (GL_BLEND); glColor4f (1,1,1,1); glPopMatrix (); } }
void R_AliasDrawModel (alight_t *plighting) #endif { // h2 int mls; int i, j; byte *dest, *source, *sourceA; // h2 finalvert_t finalverts[MAXALIASVERTS + ((CACHE_SIZE - 1) / sizeof(finalvert_t)) + 1]; auxvert_t auxverts[MAXALIASVERTS]; r_amodels_drawn++; // cache align pfinalverts = (finalvert_t *) (((long)&finalverts[0] + CACHE_SIZE - 1) & ~(CACHE_SIZE - 1)); #ifdef INTERPOL7 if(r_lerpmodels->value) pauxverts = &r_auxverts[0]; else pauxverts = &auxverts[0]; #else pauxverts = &auxverts[0]; #endif paliashdr = (aliashdr_t *)Mod_Extradata (currententity->model); pmdl = (mdl_t *)((byte *)paliashdr + paliashdr->model); R_AliasSetupSkin (); #ifdef INTERPOL7 if (r_lerpmodels->value) R_AliasSetUpTransform (0); else R_AliasSetUpTransform (currententity->trivial_accept); // R_AliasSetUpTransform (currententity->trivial_accept); #else R_AliasSetUpTransform (currententity->trivial_accept); #endif if (r_shading->value > 1 && (lightingavailable)) R_AliasSetupLighting_enhanced (plighting); // leilei - further hacked else if (r_shading->value > 1 && !lightingavailable) R_AliasSetupLighting (plighting); // no lighting available so we fall back else if (r_shading->value) R_AliasSetupLighting (plighting); else R_AliasSetupLightingSimple (plighting); #ifdef INTERPOL7 R_AliasSetupFrame (currententity); #else R_AliasSetupFrame (); #endif if (!currententity->colormap) Sys_Error ("R_AliasDrawModel: !currententity->colormap"); if (!coloredlights){ r_affinetridesc.drawtype = (currententity->trivial_accept == 3) && r_recursiveaffinetriangles; } if (r_affinetridesc.drawtype) { D_PolysetUpdateTables (); // FIXME: precalc... } else { #if id386broken D_Aff8Patch (currententity->colormap); #endif } acolormap = currententity->colormap; #ifdef VMTOC // if (viewmodel) // ziscale = (float)0x8000 * (float)0x10000 * 3.0; // else if (viewmodel) ziscale = (float)0x8000 * (float)0x10000 * 3.0; else ziscale = (float)0x8000 * (float)0x10000; #else if (currententity != &cl.viewent) ziscale = (float)0x8000 * (float)0x10000; else ziscale = (float)0x8000 * (float)0x10000 * 3.0; #endif if (currententity->trivial_accept) R_AliasPrepareUnclippedPoints (); else R_AliasPreparePoints (); }
/* <83e97> ../engine/r_studio.c:1015 */ hull_t *SV_HullForStudioModel(const edict_t *pEdict, const vec_t *mins, const vec_t *maxs, vec_t *offset, int *pNumHulls) { qboolean useComplexHull = FALSE; vec3_t size; float factor = 0.5; int bSkipShield = 0; size[0] = maxs[0] - mins[0]; size[1] = maxs[1] - mins[1]; size[2] = maxs[2] - mins[2]; if (VectorCompare(vec3_origin, size)) { if (!(gGlobalVariables.trace_flags & FTRACE_SIMPLEBOX)) { useComplexHull = TRUE; if (pEdict->v.flags & FL_CLIENT) { if (sv_clienttrace.value == 0.0) { useComplexHull = FALSE; } else { size[2] = 1.0f; size[1] = 1.0f; size[0] = 1.0f; factor = sv_clienttrace.value * 0.5f; } } } } if (pEdict->v.gamestate == 1 && (g_bIsTerrorStrike == 1 || g_bIsCStrike == 1 || g_bIsCZero == 1)) bSkipShield = 1; if ((g_psv.models[pEdict->v.modelindex]->flags & FL_ONGROUND) || useComplexHull == TRUE) { VectorScale(size, factor, size); offset[0] = 0; offset[1] = 0; offset[2] = 0; if (pEdict->v.flags & FL_CLIENT) { pstudiohdr = (studiohdr_t *)Mod_Extradata(g_psv.models[pEdict->v.modelindex]); mstudioseqdesc_t* pseqdesc = (mstudioseqdesc_t *)((char*)pstudiohdr + pstudiohdr->seqindex); pseqdesc += pEdict->v.sequence; vec3_t angles; angles[0] = pEdict->v.angles[0]; angles[1] = pEdict->v.angles[1]; angles[2] = pEdict->v.angles[2]; int iBlend; R_StudioPlayerBlend(pseqdesc, &iBlend, angles); unsigned char blending = (unsigned char)iBlend; unsigned char controller[4] = { 0x7F, 0x7F, 0x7F, 0x7F }; return R_StudioHull( g_psv.models[pEdict->v.modelindex], pEdict->v.frame, pEdict->v.sequence, angles, pEdict->v.origin, size, controller, &blending, pNumHulls, pEdict, bSkipShield); } else { return R_StudioHull( g_psv.models[pEdict->v.modelindex], pEdict->v.frame, pEdict->v.sequence, pEdict->v.angles, pEdict->v.origin, size, pEdict->v.controller, pEdict->v.blending, pNumHulls, pEdict, bSkipShield); } } else { *pNumHulls = 1; return SV_HullForEntity((edict_t *)pEdict, mins, maxs, offset); } }
/* ==================== HullForStudio NOTE: pEdict may be NULL ==================== */ hull_t *Mod_HullForStudio( model_t *model, float frame, int sequence, vec3_t angles, vec3_t origin, vec3_t size, byte *pcontroller, byte *pblending, int *numhitboxes, edict_t *pEdict ) { vec3_t angles2; mstudiocache_t *bonecache; mstudiobbox_t *phitbox; int i, j; qboolean bSkipShield = 0; ASSERT( numhitboxes ); *numhitboxes = 0; // assume error if((sv_skipshield->integer == 1 && pEdict && pEdict->v.gamestate == 1) || sv_skipshield->integer == 2) bSkipShield = 1; if( mod_studiocache->integer ) { bonecache = Mod_CheckStudioCache( model, frame, sequence, angles, origin, size, pcontroller, pblending ); if( bonecache != NULL ) { Q_memcpy( studio_planes, &cache_planes[bonecache->current_plane], bonecache->numhitboxes * sizeof( mplane_t ) * 6 ); Q_memcpy( studio_hull_hitgroup, &cache_hull_hitgroup[bonecache->current_hull], bonecache->numhitboxes * sizeof( uint )); Q_memcpy( studio_hull, &cache_hull[bonecache->current_hull], bonecache->numhitboxes * sizeof( hull_t )); *numhitboxes = bonecache->numhitboxes; return studio_hull; } } mod_studiohdr = Mod_Extradata( model ); if( !mod_studiohdr ) return NULL; // probably not a studiomodel ASSERT( pBlendAPI != NULL ); VectorCopy( angles, angles2 ); if( !( host.features & ENGINE_COMPENSATE_QUAKE_BUG )) angles2[PITCH] = -angles2[PITCH]; // stupid quake bug pBlendAPI->SV_StudioSetupBones( model, frame, sequence, angles2, origin, pcontroller, pblending, -1, pEdict ); phitbox = (mstudiobbox_t *)((byte *)mod_studiohdr + mod_studiohdr->hitboxindex); for( i = j = 0; i < mod_studiohdr->numhitboxes; i++, j += 6 ) { studio_hull_hitgroup[i] = phitbox[i].group; Mod_SetStudioHullPlane( &studio_planes[j+0], phitbox[i].bone, 0, phitbox[i].bbmax[0] ); Mod_SetStudioHullPlane( &studio_planes[j+1], phitbox[i].bone, 0, phitbox[i].bbmin[0] ); Mod_SetStudioHullPlane( &studio_planes[j+2], phitbox[i].bone, 1, phitbox[i].bbmax[1] ); Mod_SetStudioHullPlane( &studio_planes[j+3], phitbox[i].bone, 1, phitbox[i].bbmin[1] ); Mod_SetStudioHullPlane( &studio_planes[j+4], phitbox[i].bone, 2, phitbox[i].bbmax[2] ); Mod_SetStudioHullPlane( &studio_planes[j+5], phitbox[i].bone, 2, phitbox[i].bbmin[2] ); studio_planes[j+0].dist += DotProductFabs( studio_planes[j+0].normal, size ); studio_planes[j+1].dist -= DotProductFabs( studio_planes[j+1].normal, size ); studio_planes[j+2].dist += DotProductFabs( studio_planes[j+2].normal, size ); studio_planes[j+3].dist -= DotProductFabs( studio_planes[j+3].normal, size ); studio_planes[j+4].dist += DotProductFabs( studio_planes[j+4].normal, size ); studio_planes[j+5].dist -= DotProductFabs( studio_planes[j+5].normal, size ); } // tell trace code about hitbox count *numhitboxes = (bSkipShield == true) ? mod_studiohdr->numhitboxes - 1 : mod_studiohdr->numhitboxes; if( mod_studiocache->integer ) { Mod_AddToStudioCache( frame, sequence, angles, origin, size, pcontroller, pblending, model, studio_hull, *numhitboxes ); } return studio_hull; }