/** * @brief Calculates transformation matrix for the model and its tags * @note The transformation matrix is only calculated once */ static float* R_CalcTransform (entity_t* e) { transform_t* t; float* mp; float mt[16], mc[16]; /* check if this entity is already transformed */ t = &e->transform; if (t->processing) Com_Error(ERR_DROP, "Ring in entity transformations!"); if (t->done) return t->matrix; /* process this matrix */ t->processing = true; mp = nullptr; /* do parent object transformations first */ if (e->tagent) { /* tag transformation */ const model_t* model = e->tagent->model; const mAliasTagOrientation_t* current = nullptr; const mAliasTagOrientation_t* old = nullptr; const animState_t* as = &e->tagent->as; R_GetTags(model, e->tagname, as->frame, as->oldframe, ¤t, &old); if (current != nullptr && old != nullptr) { float interpolated[16]; /* parent transformation */ mp = R_CalcTransform(e->tagent); /* do interpolation */ R_InterpolateTransform(as->backlerp, model->alias.num_frames, current, old, interpolated); /* transform */ GLMatrixMultiply(mp, interpolated, mt); mp = mt; } } GLMatrixAssemble(e->origin, e->angles, mc); /* combine transformations */ if (mp) GLMatrixMultiply(mp, mc, t->matrix); else memcpy(t->matrix, mc, sizeof(float) * 16); /* matrix elements 12..14 contain (forward) translation vector, which is also the origin of model after transform */ e->distanceFromViewOrigin = VectorDist(&t->matrix[12], refdef.viewOrigin); /* we're done */ t->done = true; t->processing = false; return t->matrix; }
/** * @brief Draws a model in 2d mode (for rendering model data from the ui) * @param[in,out] mi All the needed model information to render the model * @param[in,out] pmi The model information of the parent model. This is used * in those cases, where the model that should get rendered here is placed relativly * to an already existing model in the world. * @param[in] tagname If a parent model is given, a @c tagname is given in most cases, too. It's used * to transform the model location relative to the parent model location again. E.g. a * @c tagname of tag_rweapon will transform the location to the right hand of an actor. * @sa R_DrawAliasModel */ void R_DrawModelDirect (modelInfo_t * mi, modelInfo_t * pmi, const char *tagname) { image_t *skin; mAliasMesh_t *mesh; if (Q_strnull(mi->name)) return; /* register the model */ mi->model = R_FindModel(mi->name); /* check if the model exists */ if (!mi->model) { Com_Printf("No model found for '%s'\n", mi->name); return; } skin = R_AliasModelState(mi->model, &mi->mesh, &mi->frame, &mi->oldframe, &mi->skin); if (skin == NULL) { Com_Printf("Model '%s' is broken\n", mi->name); return; } glPushMatrix(); glScalef(viddef.rx, viddef.ry, (viddef.rx + viddef.ry) / 2); R_Color(mi->color); if (pmi) { /* register the parent model */ pmi->model = R_FindModel(pmi->name); /* transform - the next transform for the child model will be relative from the * parent model location now */ R_TransformModelDirect(pmi); /* tag transformation */ if (tagname) { const mAliasTagOrientation_t *current = NULL; const mAliasTagOrientation_t *old = NULL; R_GetTags(pmi->model, tagname, pmi->frame, pmi->oldframe, ¤t, &old); if (current != NULL && old != NULL) { float interpolated[16]; /* do interpolation */ R_InterpolateTransform(pmi->backlerp, pmi->model->alias.num_frames, current, old, interpolated); /* transform */ glMultMatrixf(interpolated); R_CheckError(); } } } /* transform */ R_TransformModelDirect(mi); /* we have to reenable this here - we are in 2d mode here already */ glEnable(GL_DEPTH_TEST); /* draw it */ R_BindTexture(skin->texnum); /* draw the model */ mesh = &mi->model->alias.meshes[0]; refdef.aliasCount += mesh->num_tris; if (mi->model->alias.num_frames == 1) R_DrawAliasStaticWithReset(mesh, vec4_origin); else R_DrawAliasFrameLerp(&mi->model->alias, mesh, mi->backlerp, mi->frame, mi->oldframe, vec4_origin); /* show model bounding box */ if (r_showbox->integer) R_DrawBoundingBox(mi->model->alias.frames[mi->frame].mins, mi->model->alias.frames[mi->frame].maxs); glDisable(GL_DEPTH_TEST); glPopMatrix(); R_Color(NULL); }