00001
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
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
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
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
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
00143 if (taghdr == NULL)
00144 return NULL;
00145
00146 assert(tagName);
00147
00148
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
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
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
00200 mi->model = R_RegisterModelShort(mi->name);
00201
00202
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
00221 pmi->model = R_RegisterModelShort(pmi->name);
00222
00223
00224
00225 R_TransformModelDirect(pmi);
00226
00227
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
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
00242 glMultMatrixf(interpolated);
00243 R_CheckError();
00244 }
00245 }
00246 }
00247
00248
00249 R_TransformModelDirect(mi);
00250
00251
00252 glEnable(GL_DEPTH_TEST);
00253
00254
00255 R_BindTexture(skin->texnum);
00256
00257
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
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
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
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
00305 R_BindTexture(skin->texnum);
00306
00307
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
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
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
00352 angles[YAW] = -angles[YAW];
00353 AngleVectors(angles, vectors[0], vectors[1], vectors[2]);
00354
00355
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
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
00381
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
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
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
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) {
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
00458 for (i = 0; i < 3; i++) {
00459 if (color[i] > g)
00460 g = color[i];
00461 }
00462
00463
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
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 }