r_mesh.c

Go to the documentation of this file.
00001 
00006 /*
00007 All original material Copyright (C) 2002-2010 UFO: Alien Invasion.
00008 
00009 Copyright (C) 1997-2001 Id Software, Inc.
00010 
00011 This program is free software; you can redistribute it and/or
00012 modify it under the terms of the GNU General Public License
00013 as published by the Free Software Foundation; either version 2
00014 of the License, or (at your option) any later version.
00015 
00016 This program is distributed in the hope that it will be useful,
00017 but WITHOUT ANY WARRANTY; without even the implied warranty of
00018 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00019 
00020 See the GNU General Public License for more details.
00021 
00022 You should have received a copy of the GNU General Public License
00023 along with this program; if not, write to the Free Software
00024 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00025 
00026 */
00027 
00028 #include "r_local.h"
00029 #include "r_lightmap.h"
00030 #include "r_light.h"
00031 #include "r_mesh.h"
00032 #include "r_mesh_anim.h"
00033 #include "r_error.h"
00034 #include "r_draw.h"
00035 
00036 static void R_TransformModelDirect (modelInfo_t * mi)
00037 {
00038     /* translate and rotate */
00039     glTranslatef(mi->origin[0], mi->origin[1], mi->origin[2]);
00040 
00041     glRotatef(mi->angles[0], 0, 0, 1);
00042     glRotatef(mi->angles[1], 0, 1, 0);
00043     glRotatef(mi->angles[2], 1, 0, 0);
00044 
00045     /* scale by parameters */
00046     if (mi->scale)
00047         glScalef(mi->scale[0], mi->scale[1], mi->scale[2]);
00048     if (mi->center)
00049         glTranslatef(mi->center[0], mi->center[1], mi->center[2]);
00050 }
00051 
00052 
00053 
00059 static void R_DrawMeshModelShell (const mAliasMesh_t *mesh, const vec4_t color)
00060 {
00061     /* check whether rgb is set */
00062     if (!VectorNotEmpty(color))
00063         return;
00064 
00065     R_Color(color);
00066 
00067     R_BindTexture(r_envmaptextures[1]->texnum);
00068 
00069     R_EnableShell(qtrue);
00070 
00071     glDrawArrays(GL_TRIANGLES, 0, mesh->num_tris * 3);
00072 
00073     R_EnableShell(qfalse);
00074 
00075     R_Color(NULL);
00076 }
00077 
00082 static void R_DrawAliasFrameLerp (mAliasModel_t* mod, mAliasMesh_t *mesh, float backlerp, int framenum, int oldframenum, const vec4_t shellColor)
00083 {
00084     R_FillArrayData(mod, mesh, backlerp, framenum, oldframenum, qfalse);
00085 
00086     R_EnableAnimation(mesh, backlerp, qtrue);
00087 
00088     glDrawArrays(GL_TRIANGLES, 0, mesh->num_tris * 3);
00089 
00090     R_DrawMeshModelShell(mesh, shellColor);
00091 
00092     R_EnableAnimation(NULL, 0.0, qfalse);
00093 
00094     R_CheckError();
00095 }
00096 
00101 static void R_DrawAliasStatic (const mAliasMesh_t *mesh, const vec4_t shellColor)
00102 {
00103     R_BindArray(GL_VERTEX_ARRAY, GL_FLOAT, mesh->verts);
00104     R_BindArray(GL_NORMAL_ARRAY, GL_FLOAT, mesh->normals);
00105     if (r_state.bumpmap_enabled || r_state.dynamic_lighting_enabled)
00106         R_BindArray(GL_TANGENT_ARRAY, GL_FLOAT, mesh->tangents);
00107     R_BindArray(GL_TEXTURE_COORD_ARRAY, GL_FLOAT, mesh->texcoords);
00108 
00109     glDrawArrays(GL_TRIANGLES, 0, mesh->num_tris * 3);
00110 
00111     R_DrawMeshModelShell(mesh, shellColor);
00112 
00113     R_BindDefaultArray(GL_VERTEX_ARRAY);
00114     R_BindDefaultArray(GL_NORMAL_ARRAY);
00115     if (r_state.bumpmap_enabled || r_state.dynamic_lighting_enabled)
00116         R_BindDefaultArray(GL_TANGENT_ARRAY);
00117     R_BindDefaultArray(GL_TEXTURE_COORD_ARRAY);
00118 }
00119 
00131 const float* R_GetTagMatrix (const model_t* mod, const char* tagName)
00132 {
00133     int i;
00134     const dMD2tag_t *taghdr;
00135     const char *name;
00136 
00137     if (!mod)
00138         return NULL;
00139 
00140     taghdr = (const dMD2tag_t *) mod->alias.tagdata;
00141 
00142     /* no tag data found for this model */
00143     if (taghdr == NULL)
00144         return NULL;
00145 
00146     assert(tagName);
00147 
00148     /* find the right tag */
00149     name = (const char *) taghdr + taghdr->ofs_names;
00150     for (i = 0; i < taghdr->num_tags; i++, name += MD2_MAX_TAGNAME) {
00151         if (!strcmp(name, tagName)) {
00152             /* found the tag (matrix) */
00153             const float *tag = (const float *) ((const byte *) taghdr + taghdr->ofs_tags);
00154             tag += i * 16 * taghdr->num_frames;
00155             return tag;
00156         }
00157     }
00158     return NULL;
00159 }
00160 
00171 void R_ModelAutoScale (const vec2_t boxSize, modelInfo_t *mi, vec3_t scale, vec3_t center)
00172 {
00173     const float width = mi->model->maxs[0] - mi->model->mins[0];
00174     const float height = mi->model->maxs[2] - mi->model->mins[2];
00175     const float factorX = boxSize[0] / width;
00176     const float factorY = boxSize[1] / height;
00177     const float size = min(factorX, factorY);
00178 
00179     /* get center */
00180     VectorCenterFromMinsMaxs(mi->model->mins, mi->model->maxs, center);
00181     VectorNegate(center, center);
00182     VectorSet(scale, size, size, size);
00183 
00184     mi->center = center;
00185     mi->scale = scale;
00186 }
00187 
00191 void R_DrawModelDirect (modelInfo_t * mi, modelInfo_t * pmi, const char *tagname)
00192 {
00193     image_t *skin;
00194     mAliasMesh_t *mesh;
00195 
00196     if (!mi->name || mi->name[0] == '\0')
00197         return;
00198 
00199     /* register the model */
00200     mi->model = R_RegisterModelShort(mi->name);
00201 
00202     /* check if the model exists */
00203     if (!mi->model) {
00204         Com_Printf("No model found for '%s'\n", mi->name);
00205         return;
00206     }
00207 
00208     skin = R_AliasModelState(mi->model, &mi->mesh, &mi->frame, &mi->oldframe, &mi->skin);
00209     if (skin == NULL) {
00210         Com_Printf("Model '%s' is broken\n", mi->name);
00211         return;
00212     }
00213 
00214     glPushMatrix();
00215     glScalef(viddef.rx, viddef.ry, (viddef.rx + viddef.ry) / 2);
00216 
00217     R_Color(mi->color);
00218 
00219     if (pmi) {
00220         /* register the parent model */
00221         pmi->model = R_RegisterModelShort(pmi->name);
00222 
00223         /* transform - the next transform for the child model will be relative from the
00224          * parent model location now */
00225         R_TransformModelDirect(pmi);
00226 
00227         /* tag transformation */
00228         if (tagname) {
00229             const float *tag = R_GetTagMatrix(pmi->model, tagname);
00230             if (tag) {
00231                 float interpolated[16];
00232                 animState_t as;
00233                 dMD2tag_t *taghdr = (dMD2tag_t *) pmi->model->alias.tagdata;
00234 
00235                 /* do interpolation */
00236                 as.frame = pmi->frame;
00237                 as.oldframe = pmi->oldframe;
00238                 as.backlerp = pmi->backlerp;
00239                 R_InterpolateTransform(&as, taghdr->num_frames, tag, interpolated);
00240 
00241                 /* transform */
00242                 glMultMatrixf(interpolated);
00243                 R_CheckError();
00244             }
00245         }
00246     }
00247 
00248     /* transform */
00249     R_TransformModelDirect(mi);
00250 
00251     /* we have to reenable this here - we are in 2d mode here already */
00252     glEnable(GL_DEPTH_TEST);
00253 
00254     /* draw it */
00255     R_BindTexture(skin->texnum);
00256 
00257     /* draw the model */
00258     mesh = &mi->model->alias.meshes[0];
00259     refdef.aliasCount += mesh->num_tris;
00260     if (mi->model->alias.num_frames == 1)
00261         R_DrawAliasStatic(mesh, vec4_origin);
00262     else
00263         R_DrawAliasFrameLerp(&mi->model->alias, mesh, mi->backlerp, mi->frame, mi->oldframe, vec4_origin);
00264 
00265     /* show model bounding box */
00266     if (r_showbox->integer)
00267         R_DrawBoundingBox(mi->model->alias.frames[mi->frame].mins, mi->model->alias.frames[mi->frame].maxs);
00268 
00269     glDisable(GL_DEPTH_TEST);
00270 
00271     glPopMatrix();
00272 
00273     R_Color(NULL);
00274 }
00275 
00279 void R_DrawModelParticle (modelInfo_t * mi)
00280 {
00281     image_t *skin;
00282     mAliasMesh_t *mesh;
00283 
00284     /* check if the model exists */
00285     if (!mi->model)
00286         return;
00287 
00288     skin = R_AliasModelState(mi->model, &mi->mesh, &mi->frame, &mi->oldframe, &mi->skin);
00289     if (skin == NULL) {
00290         Com_Printf("Model '%s' is broken\n", mi->name);
00291         return;
00292     }
00293 
00294     R_Color(mi->color);
00295 
00296     /* draw all the triangles */
00297     glPushMatrix();
00298 
00299     glTranslatef(mi->origin[0], mi->origin[1], mi->origin[2]);
00300     glRotatef(mi->angles[YAW], 0, 0, 1);
00301     glRotatef(mi->angles[PITCH], 0, 1, 0);
00302     glRotatef(-mi->angles[ROLL], 1, 0, 0);
00303 
00304     /* draw it */
00305     R_BindTexture(skin->texnum);
00306 
00307     /* draw the model */
00308     mesh = &mi->model->alias.meshes[0];
00309     refdef.aliasCount += mesh->num_tris;
00310     if (mi->model->alias.num_frames == 1)
00311         R_DrawAliasStatic(mesh, vec4_origin);
00312     else
00313         R_DrawAliasFrameLerp(&mi->model->alias, mesh, mi->backlerp, mi->frame, mi->oldframe, vec4_origin);
00314 
00315     /* show model bounding box */
00316     if (r_showbox->integer)
00317         R_DrawBoundingBox(mi->model->alias.frames[mi->frame].mins, mi->model->alias.frames[mi->frame].maxs);
00318 
00319     glPopMatrix();
00320 
00321     R_Color(NULL);
00322 }
00323 
00324 qboolean R_CullMeshModel (entity_t *e)
00325 {
00326     int i;
00327     uint32_t aggregatemask;
00328     vec3_t mins, maxs, origin, angles;
00329     vec3_t vectors[3];
00330     vec4_t bbox[8];
00331 
00332     if (e->tagent) {
00333         VectorCopy(e->tagent->origin, origin);
00334         VectorCopy(e->tagent->angles, angles);
00335     } else {
00336         VectorCopy(e->origin, origin);
00337         VectorCopy(e->angles, angles);
00338     }
00339 
00340     /* determine scaled mins/maxs */
00341     for (i = 0; i < 3; i++) {
00342         if (e->scale[i]) {
00343             mins[i] = e->model->mins[i] * e->scale[i];
00344             maxs[i] = e->model->maxs[i] * e->scale[i];
00345         } else {
00346             mins[i] = e->model->mins[i];
00347             maxs[i] = e->model->maxs[i];
00348         }
00349     }
00350 
00351     /* rotate the bounding box */
00352     angles[YAW] = -angles[YAW];
00353     AngleVectors(angles, vectors[0], vectors[1], vectors[2]);
00354 
00355     /* compute translated and rotate bounding box */
00356     for (i = 0; i < 8; i++) {
00357         vec3_t tmp;
00358 
00359         tmp[0] = (i & 1) ? mins[0] : maxs[0];
00360         tmp[1] = (i & 2) ? mins[1] : maxs[1];
00361         tmp[2] = (i & 4) ? mins[2] : maxs[2];
00362 
00363         bbox[i][0] = DotProduct(vectors[0], tmp);
00364         bbox[i][1] = -DotProduct(vectors[1], tmp);
00365         bbox[i][2] = DotProduct(vectors[2], tmp);
00366 
00367         VectorAdd(origin, bbox[i], bbox[i]);
00368     }
00369 
00370     /* compute a full bounding box */
00371     aggregatemask = ~0;
00372 
00373     for (i = 0; i < 8; i++) {
00374         int mask = 0;
00375         int j;
00376         const int size = lengthof(r_locals.frustum);
00377 
00378         for (j = 0; j < size; j++) {
00379             const cBspPlane_t *bspPlane = &r_locals.frustum[j];
00380             /* get the distance between the frustum normal vector and the
00381              * current vector of the bounding box */
00382             const float f = DotProduct(bspPlane->normal, bbox[i]);
00383             if (f - bspPlane->dist < 0)
00384                 mask |= (1 << j);
00385         }
00386 
00387         aggregatemask &= mask;
00388     }
00389 
00390     if (aggregatemask)
00391         return qtrue;
00392 
00393     return qfalse;
00394 }
00395 
00402 static mAliasMesh_t* R_GetLevelOfDetailForModel (const vec3_t origin, const mAliasModel_t* mod)
00403 {
00404     if (mod->num_meshes == 1 || (refdef.rendererFlags & RDF_NOWORLDMODEL)) {
00405         return &mod->meshes[0];
00406     } else {
00407         vec3_t dist;
00408         vec_t length;
00409 
00410         /* get distance, set lod if available */
00411         VectorSubtract(refdef.viewOrigin, origin, dist);
00412         length = VectorLength(dist);
00413         if (mod->num_meshes > 3 && length > 700) {
00414             return &mod->meshes[3];
00415         } if (mod->num_meshes > 2 && length > 600) {
00416             return &mod->meshes[2];
00417         } else if (length > 500) {
00418             return &mod->meshes[1];
00419         }
00420 
00421         return &mod->meshes[0];
00422     }
00423 }
00424 
00430 void R_DrawAliasModel (entity_t *e)
00431 {
00432     mAliasModel_t *mod = (mAliasModel_t *)&e->model->alias;
00433     /* the values are sane here already - see R_DrawEntities */
00434     const image_t *skin = mod->meshes[e->as.mesh].skins[e->skinnum].skin;
00435     int i;
00436     float g;
00437     vec4_t color = {0.8, 0.8, 0.8, 1.0};
00438     mAliasMesh_t* lodMesh;
00439 
00440     glPushMatrix();
00441 
00442     glMultMatrixf(e->transform.matrix);
00443 
00444     if (VectorNotEmpty(e->scale))
00445         glScalef(e->scale[0], e->scale[1], e->scale[2]);
00446 
00447     /* IR goggles override color for entities that are affected */
00448     if (refdef.rendererFlags & RDF_IRGOGGLES && e->flags & RF_IRGOGGLES)
00449         Vector4Set(e->shell, 1.0, 0.3, 0.3, 1.0);
00450 
00451     if (e->flags & RF_PULSE) {  /* and then adding in a pulse */
00452         const float f = 1.0 + sin((refdef.time + (e->model->alias.meshes[0].num_tris)) * 6.0) * 0.33;
00453         VectorScale(color, 1.0 + f, color);
00454     }
00455 
00456     g = 0.0;
00457     /* find brightest component */
00458     for (i = 0; i < 3; i++) {
00459         if (color[i] > g)  /* keep it */
00460             g = color[i];
00461     }
00462 
00463     /* scale it back to 1.0 */
00464     if (g > 1.0)
00465         VectorScale(color, 1.0 / g, color);
00466 
00467     R_Color(color);
00468 
00469     assert(skin->texnum > 0);
00470     R_BindTexture(skin->texnum);
00471 
00472     R_EnableGlowMap(skin->glowmap, qtrue);
00473 
00474     R_UpdateLightList(e);
00475     R_EnableDynamicLights(e, qtrue);
00476 
00477     if (skin->normalmap)
00478         R_EnableBumpmap(skin->normalmap, qtrue);
00479 
00480     if (skin->specularmap)
00481         R_EnableSpecularMap(skin->specularmap, qtrue);
00482 
00483     if (skin->roughnessmap)
00484         R_EnableRoughnessMap(skin->roughnessmap, qtrue);
00485 
00486     R_ResetArrayState();
00487 
00488     lodMesh = R_GetLevelOfDetailForModel(e->origin, mod);
00489     refdef.aliasCount += lodMesh->num_tris;
00490     if (mod->num_frames == 1)
00491         R_DrawAliasStatic(lodMesh, e->shell);
00492     else
00493         R_DrawAliasFrameLerp(mod, lodMesh, e->as.backlerp, e->as.frame, e->as.oldframe, e->shell);
00494 
00495     if (r_state.specularmap_enabled)
00496         R_EnableSpecularMap(NULL, qfalse);
00497 
00498     if (r_state.roughnessmap_enabled)
00499         R_EnableRoughnessMap(NULL, qfalse);
00500 
00501     R_EnableDynamicLights(NULL, qfalse);
00502 
00503     if (r_state.glowmap_enabled)
00504         R_EnableGlowMap(NULL, qfalse);
00505 
00506     if (r_state.bumpmap_enabled)
00507         R_EnableBumpmap(NULL, qfalse);
00508 
00509     /* show model bounding box */
00510     if (r_showbox->integer)
00511         R_DrawBoundingBox(mod->frames[e->as.frame].mins, mod->frames[e->as.frame].maxs);
00512 
00513     glPopMatrix();
00514 
00515     R_Color(NULL);
00516 }

Generated by  doxygen 1.6.2