r_model_brush.c

Go to the documentation of this file.
00001 
00006 /*
00007 Copyright (C) 1997-2001 Id Software, Inc.
00008 
00009 This program is free software; you can redistribute it and/or
00010 modify it under the terms of the GNU General Public License
00011 as published by the Free Software Foundation; either version 2
00012 of the License, or (at your option) any later version.
00013 
00014 This program is distributed in the hope that it will be useful,
00015 but WITHOUT ANY WARRANTY; without even the implied warranty of
00016 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00017 
00018 See the GNU General Public License for more details.
00019 
00020 You should have received a copy of the GNU General Public License
00021 along with this program; if not, write to the Free Software
00022 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00023 
00024 */
00025 
00026 #include "r_local.h"
00027 #include "r_lightmap.h"
00028 #include "../../shared/parse.h"
00029 #include "r_light.h"
00030 
00031 /*
00032 ===============================================================================
00033 BRUSHMODEL LOADING
00034 ===============================================================================
00035 */
00036 
00040 static const byte *mod_base;
00045 static ipos3_t shift;
00050 static model_t *r_worldmodel;
00051 
00055 static void R_ModLoadLighting (const lump_t *l)
00056 {
00057     /* map has no lightmap */
00058     if (l->filelen == 0)
00059         return;
00060 
00061     r_worldmodel->bsp.lightdata = (byte *)Mem_PoolAlloc(l->filelen, vid_lightPool, 0);
00062     r_worldmodel->bsp.lightquant = *(const byte *) (mod_base + l->fileofs);
00063     memcpy(r_worldmodel->bsp.lightdata, mod_base + l->fileofs, l->filelen);
00064 }
00065 
00066 static void R_ModLoadVertexes (const lump_t *l)
00067 {
00068     const dBspVertex_t *in;
00069     mBspVertex_t *out;
00070     int i, count;
00071 
00072     in = (const dBspVertex_t *) (mod_base + l->fileofs);
00073     if (l->filelen % sizeof(*in))
00074         Com_Error(ERR_DROP, "R_ModLoadVertexes: funny lump size in %s", r_worldmodel->name);
00075     count = l->filelen / sizeof(*in);
00076     out = (mBspVertex_t *)Mem_PoolAlloc(count * sizeof(*out), vid_modelPool, 0);
00077     Com_DPrintf(DEBUG_RENDERER, "...verts: %i\n", count);
00078 
00079     r_worldmodel->bsp.vertexes = out;
00080     r_worldmodel->bsp.numvertexes = count;
00081 
00082     for (i = 0; i < count; i++, in++, out++) {
00083         out->position[0] = LittleFloat(in->point[0]);
00084         out->position[1] = LittleFloat(in->point[1]);
00085         out->position[2] = LittleFloat(in->point[2]);
00086     }
00087 }
00088 
00089 static void R_ModLoadNormals (const lump_t *l)
00090 {
00091     const dBspNormal_t *in;
00092     mBspVertex_t *out;
00093     int i, count;
00094 
00095     in = (const dBspNormal_t *)(mod_base + l->fileofs);
00096     if (l->filelen % sizeof(*in)) {
00097         Com_Error(ERR_DROP, "R_LoadNormals: Funny lump size in %s.", r_worldmodel->name);
00098     }
00099     count = l->filelen / sizeof(*in);
00100 
00101     if (count != r_worldmodel->bsp.numvertexes) {  /* ensure sane normals count */
00102         Com_Error(ERR_DROP, "R_LoadNormals: unexpected normals count in %s: (%d != %d).",
00103                 r_worldmodel->name, count, r_worldmodel->bsp.numvertexes);
00104     }
00105 
00106     out = r_worldmodel->bsp.vertexes;
00107 
00108     for (i = 0; i < count; i++, in++, out++) {
00109         out->normal[0] = LittleFloat(in->normal[0]);
00110         out->normal[1] = LittleFloat(in->normal[1]);
00111         out->normal[2] = LittleFloat(in->normal[2]);
00112     }
00113 }
00114 
00115 static inline float R_RadiusFromBounds (const vec3_t mins, const vec3_t maxs)
00116 {
00117     int i;
00118     vec3_t corner;
00119 
00120     for (i = 0; i < 3; i++)
00121         corner[i] = fabsf(mins[i]) > fabsf(maxs[i]) ? fabsf(mins[i]) : fabsf(maxs[i]);
00122 
00123     return VectorLength(corner);
00124 }
00125 
00126 
00131 static void R_ModLoadSubmodels (const lump_t *l)
00132 {
00133     const dBspModel_t *in;
00134     mBspHeader_t *out;
00135     int i, j, count;
00136 
00137     in = (const dBspModel_t *) (mod_base + l->fileofs);
00138     if (l->filelen % sizeof(*in))
00139         Com_Error(ERR_DROP, "R_ModLoadSubmodels: funny lump size in %s", r_worldmodel->name);
00140     count = l->filelen / sizeof(*in);
00141     out = (mBspHeader_t *)Mem_PoolAlloc(count * sizeof(*out), vid_modelPool, 0);
00142     Com_DPrintf(DEBUG_RENDERER, "...submodels: %i\n", count);
00143 
00144     r_worldmodel->bsp.submodels = out;
00145     r_worldmodel->bsp.numsubmodels = count;
00146 
00147     for (i = 0; i < count; i++, in++, out++) {
00148         /* spread the mins / maxs by a pixel */
00149         for (j = 0; j < 3; j++) {
00150             out->mins[j] = LittleFloat(in->mins[j]) - 1.0f + (float)shift[j];
00151             out->maxs[j] = LittleFloat(in->maxs[j]) + 1.0f + (float)shift[j];
00152             out->origin[j] = LittleFloat(in->origin[j]) + (float)shift[j];
00153         }
00154         out->radius = R_RadiusFromBounds(out->mins, out->maxs);
00155         out->headnode = LittleLong(in->headnode);
00156         out->firstface = LittleLong(in->firstface);
00157         out->numfaces = LittleLong(in->numfaces);
00158     }
00159 }
00160 
00161 static void R_ModLoadEdges (const lump_t *l)
00162 {
00163     const dBspEdge_t *in;
00164     mBspEdge_t *out;
00165     int i, count;
00166 
00167     in = (const dBspEdge_t *) (mod_base + l->fileofs);
00168     if (l->filelen % sizeof(*in))
00169         Com_Error(ERR_DROP, "R_ModLoadEdges: funny lump size in %s", r_worldmodel->name);
00170     count = l->filelen / sizeof(*in);
00171     out = (mBspEdge_t *)Mem_PoolAlloc((count + 1) * sizeof(*out), vid_modelPool, 0);
00172     Com_DPrintf(DEBUG_RENDERER, "...edges: %i\n", count);
00173 
00174     r_worldmodel->bsp.edges = out;
00175     r_worldmodel->bsp.numedges = count;
00176 
00177     for (i = 0; i < count; i++, in++, out++) {
00178         out->v[0] = (unsigned short) LittleShort(in->v[0]);
00179         out->v[1] = (unsigned short) LittleShort(in->v[1]);
00180     }
00181 }
00182 
00186 static void R_ModLoadTexinfo (const lump_t *l)
00187 {
00188     const dBspTexinfo_t *in;
00189     mBspTexInfo_t *out;
00190     int i, j, count;
00191     char name[MAX_QPATH];
00192 
00193     in = (const dBspTexinfo_t *) (mod_base + l->fileofs);
00194     if (l->filelen % sizeof(*in))
00195         Com_Error(ERR_DROP, "R_ModLoadTexinfo: funny lump size in %s", r_worldmodel->name);
00196     count = l->filelen / sizeof(*in);
00197     out = (mBspTexInfo_t *)Mem_PoolAlloc(count * sizeof(*out), vid_modelPool, 0);
00198     Com_DPrintf(DEBUG_RENDERER, "...texinfo: %i\n", count);
00199 
00200     r_worldmodel->bsp.texinfo = out;
00201     r_worldmodel->bsp.numtexinfo = count;
00202 
00203     for (i = 0; i < count; i++, in++, out++) {
00204         for (j = 0; j < 3; j++) {
00205             out->uv[j] = LittleFloat(in->vecs[0][j]);
00206             out->vv[j] = LittleFloat(in->vecs[1][j]);
00207         }
00208         out->u_offset = LittleFloat(in->vecs[0][3]);
00209         out->v_offset = LittleFloat(in->vecs[1][3]);
00210 
00211         out->flags = LittleLong(in->surfaceFlags);
00212 
00213         /* exchange the textures with the ones that are needed for base assembly */
00214         if (refdef.mapZone && strstr(in->texture, "tex_terrain/dummy"))
00215             Com_sprintf(name, sizeof(name), "textures/tex_terrain/%s", refdef.mapZone);
00216         else
00217             Com_sprintf(name, sizeof(name), "textures/%s", in->texture);
00218 
00219         out->image = R_FindImage(name, it_world);
00220     }
00221 }
00222 
00226 static void R_SetSurfaceExtents (mBspSurface_t *surf, const model_t* mod)
00227 {
00228     vec3_t mins, maxs;
00229     vec2_t stmins, stmaxs;
00230     int i, j;
00231     const mBspTexInfo_t *tex;
00232 
00233     VectorSet(mins, 999999, 999999, 999999);
00234     VectorSet(maxs, -999999, -999999, -999999);
00235 
00236     Vector2Set(stmins, 999999, 999999);
00237     Vector2Set(stmaxs, -999999, -999999);
00238 
00239     tex = surf->texinfo;
00240 
00241     for (i = 0; i < surf->numedges; i++) {
00242         const int e = mod->bsp.surfedges[surf->firstedge + i];
00243         const mBspVertex_t *v;
00244         vec3_t position;
00245         if (e >= 0)
00246             v = &mod->bsp.vertexes[mod->bsp.edges[e].v[0]];
00247         else
00248             v = &mod->bsp.vertexes[mod->bsp.edges[-e].v[1]];
00249 
00250         VectorCopy(v->position, position);
00251 
00252         for (j = 0; j < 3; j++) {  /* calculate mins, maxs */
00253             position[j] += (float)shift[j];
00254             if (position[j] > maxs[j])
00255                 maxs[j] = position[j];
00256             if (position[j] < mins[j])
00257                 mins[j] = position[j];
00258         }
00259 
00260         {  /* calculate stmins, stmaxs */
00261             const float valS = DotProduct(v->position, tex->uv) + tex->u_offset;
00262             const float valT = DotProduct(v->position, tex->vv) + tex->v_offset;
00263             stmins[0] = min(valS, stmins[0]);
00264             stmaxs[0] = max(valS, stmaxs[0]);
00265             stmins[1] = min(valT, stmins[1]);
00266             stmaxs[1] = max(valT, stmaxs[1]);
00267         }
00268     }
00269 
00270     VectorCopy(mins, surf->mins);
00271     VectorCopy(maxs, surf->maxs);
00272     VectorCenterFromMinsMaxs(surf->mins, surf->maxs, surf->center);
00273 
00274     for (i = 0; i < 2; i++) {
00275         const int bmins = floor(stmins[i] / surf->lightmap_scale);
00276         const int bmaxs = ceil(stmaxs[i] / surf->lightmap_scale);
00277 
00278         surf->stmins[i] = bmins * surf->lightmap_scale;
00279         surf->stmaxs[i] = bmaxs * surf->lightmap_scale;
00280 
00281         surf->stcenter[i] = (surf->stmaxs[i] + surf->stmins[i]) / 2.0;
00282         surf->stextents[i] = (bmaxs - bmins) * surf->lightmap_scale;
00283     }
00284 }
00285 
00286 static void R_ModLoadSurfaces (qboolean day, const lump_t *l)
00287 {
00288     const dBspSurface_t *in;
00289     mBspSurface_t *out;
00290     int i, count, surfnum;
00291     int planenum, side;
00292     int ti;
00293 
00294     in = (const dBspSurface_t *) (mod_base + l->fileofs);
00295     if (l->filelen % sizeof(*in))
00296         Com_Error(ERR_DROP, "R_ModLoadSurfaces: funny lump size in %s", r_worldmodel->name);
00297     count = l->filelen / sizeof(*in);
00298     out = (mBspSurface_t *)Mem_PoolAlloc(count * sizeof(*out), vid_modelPool, 0);
00299     Com_DPrintf(DEBUG_RENDERER, "...faces: %i\n", count);
00300 
00301     r_worldmodel->bsp.surfaces = out;
00302     r_worldmodel->bsp.numsurfaces = count;
00303 
00304     for (surfnum = 0; surfnum < count; surfnum++, in++, out++) {
00305         out->firstedge = LittleLong(in->firstedge);
00306         out->numedges = LittleShort(in->numedges);
00307 
00308         /* resolve plane */
00309         planenum = LittleShort(in->planenum);
00310         assert(planenum >= 0);
00311         out->plane = r_worldmodel->bsp.planes + planenum;
00312 
00313         /* and sideness */
00314         side = LittleShort(in->side);
00315         if (side) {
00316             out->flags |= MSURF_PLANEBACK;
00317             VectorNegate(out->plane->normal, out->normal);
00318         } else {
00319             VectorCopy(out->plane->normal, out->normal);
00320         }
00321 
00322         ti = LittleShort(in->texinfo);
00323         if (ti < 0 || ti >= r_worldmodel->bsp.numtexinfo)
00324             Com_Error(ERR_DROP, "R_ModLoadSurfaces: bad texinfo number");
00325         out->texinfo = r_worldmodel->bsp.texinfo + ti;
00326 
00327         out->lightmap_scale = (1 << r_worldmodel->bsp.lightquant);
00328 
00329         /* and size, texcoords, etc */
00330         R_SetSurfaceExtents(out, r_worldmodel);
00331 
00332         if (!(out->texinfo->flags & SURF_WARP))
00333             out->flags |= MSURF_LIGHTMAP;
00334 
00335         /* lastly lighting info */
00336         if (day)
00337             i = LittleLong(in->lightofs[LIGHTMAP_DAY]);
00338         else
00339             i = LittleLong(in->lightofs[LIGHTMAP_NIGHT]);
00340 
00341         if (i == -1)
00342             out->samples = NULL;
00343         else
00344             out->samples = r_worldmodel->bsp.lightdata + i;
00345 
00346         /* create lightmaps */
00347         R_CreateSurfaceLightmap(out);
00348 
00349         out->tile = r_numMapTiles - 1;
00350     }
00351 }
00352 
00357 static void R_ModLoadNodes (const lump_t *l)
00358 {
00359     int i, j, count;
00360     const dBspNode_t *in;
00361     mBspNode_t *out;
00362     mBspNode_t *parent = NULL;
00363 
00364     in = (const dBspNode_t *) (mod_base + l->fileofs);
00365     if (l->filelen % sizeof(*in))
00366         Com_Error(ERR_DROP, "R_ModLoadNodes: funny lump size in %s", r_worldmodel->name);
00367     count = l->filelen / sizeof(*in);
00368     out = (mBspNode_t *)Mem_PoolAlloc(count * sizeof(*out), vid_modelPool, 0);
00369     Com_DPrintf(DEBUG_RENDERER, "...nodes: %i\n", count);
00370 
00371     r_worldmodel->bsp.nodes = out;
00372     r_worldmodel->bsp.numnodes = count;
00373 
00374     for (i = 0; i < count; i++, in++, out++) {
00375         const int p = LittleLong(in->planenum);
00376 
00377         /* skip special pathfinding nodes - they have a negative index */
00378         if (p == PLANENUM_LEAF) {
00379             /* in case of "special" pathfinding nodes (they don't have a plane)
00380              * we have to set this to NULL */
00381             out->plane = NULL;
00382             out->contents = CONTENTS_PATHFINDING_NODE;
00383             parent = NULL;
00384         } else {
00385             out->plane = r_worldmodel->bsp.planes + p;
00386             /* differentiate from leafs */
00387             out->contents = CONTENTS_NODE;
00388             parent = out;
00389         }
00390 
00391         for (j = 0; j < 3; j++) {
00392             out->minmaxs[j] = LittleShort(in->mins[j]) + (float)shift[j];
00393             out->minmaxs[3 + j] = LittleShort(in->maxs[j]) + (float)shift[j];
00394         }
00395 
00396         out->firstsurface = LittleShort(in->firstface);
00397         out->numsurfaces = LittleShort(in->numfaces);
00398 
00399         for (j = 0; j < 2; j++) {
00400             const int p2 = LittleLong(in->children[j]);
00401             if (p2 > LEAFNODE) {
00402                 assert(p2 < r_worldmodel->bsp.numnodes);
00403                 out->children[j] = r_worldmodel->bsp.nodes + p2;
00404             } else {
00405                 assert((LEAFNODE - p2) < r_worldmodel->bsp.numleafs);
00406                 out->children[j] = (mBspNode_t *) (r_worldmodel->bsp.leafs + (LEAFNODE - p2));
00407             }
00408             out->children[j]->parent = parent;
00409         }
00410     }
00411 }
00412 
00413 static void R_ModLoadLeafs (const lump_t *l)
00414 {
00415     const dBspLeaf_t *in;
00416     mBspLeaf_t *out;
00417     int i, j, count;
00418 
00419     in = (const dBspLeaf_t *) (mod_base + l->fileofs);
00420     if (l->filelen % sizeof(*in))
00421         Com_Error(ERR_DROP, "R_ModLoadLeafs: funny lump size in %s", r_worldmodel->name);
00422     count = l->filelen / sizeof(*in);
00423     out = (mBspLeaf_t *)Mem_PoolAlloc(count * sizeof(*out), vid_modelPool, 0);
00424     Com_DPrintf(DEBUG_RENDERER, "...leafs: %i\n", count);
00425 
00426     r_worldmodel->bsp.leafs = out;
00427     r_worldmodel->bsp.numleafs = count;
00428 
00429     for (i = 0; i < count; i++, in++, out++) {
00430         for (j = 0; j < 3; j++) {
00431             out->minmaxs[j] = LittleShort(in->mins[j]) + (float)shift[j];
00432             out->minmaxs[3 + j] = LittleShort(in->maxs[j]) + (float)shift[j];
00433         }
00434 
00435         out->contents = LittleLong(in->contentFlags);
00436     }
00437 }
00438 
00439 static void R_ModLoadSurfedges (const lump_t *l)
00440 {
00441     int i, count;
00442     const int *in;
00443     int *out;
00444 
00445     in = (const int *) (mod_base + l->fileofs);
00446     if (l->filelen % sizeof(*in))
00447         Com_Error(ERR_DROP, "R_ModLoadSurfedges: funny lump size in %s", r_worldmodel->name);
00448     count = l->filelen / sizeof(*in);
00449     if (count < 1 || count >= MAX_MAP_SURFEDGES)
00450         Com_Error(ERR_DROP, "R_ModLoadSurfedges: bad surfedges count in %s: %i", r_worldmodel->name, count);
00451 
00452     out = (int *) Mem_PoolAlloc(count * sizeof(*out), vid_modelPool, 0);
00453     Com_DPrintf(DEBUG_RENDERER, "...surface edges: %i\n", count);
00454 
00455     r_worldmodel->bsp.surfedges = out;
00456     r_worldmodel->bsp.numsurfedges = count;
00457 
00458     for (i = 0; i < count; i++)
00459         out[i] = LittleLong(in[i]);
00460 }
00461 
00465 static void R_ModLoadPlanes (const lump_t *l)
00466 {
00467     int i, j;
00468     cBspPlane_t *out;
00469     const dBspPlane_t *in;
00470     int count;
00471 
00472     in = (const dBspPlane_t *) (mod_base + l->fileofs);
00473     if (l->filelen % sizeof(*in))
00474         Com_Error(ERR_DROP, "R_ModLoadPlanes: funny lump size in %s", r_worldmodel->name);
00475     count = l->filelen / sizeof(*in);
00476     out = (cBspPlane_t *)Mem_PoolAlloc(count * 2 * sizeof(*out), vid_modelPool, 0);
00477     Com_DPrintf(DEBUG_RENDERER, "...planes: %i\n", count);
00478 
00479     r_worldmodel->bsp.planes = out;
00480     r_worldmodel->bsp.numplanes = count;
00481 
00482     for (i = 0; i < count; i++, in++, out++) {
00483         for (j = 0; j < 3; j++)
00484             out->normal[j] = LittleFloat(in->normal[j]);
00485         out->dist = LittleFloat(in->dist);
00486         out->type = LittleLong(in->type);
00487     }
00488 }
00489 
00499 static void R_ModShiftTile (void)
00500 {
00501     mBspVertex_t *vert;
00502     cBspPlane_t *plane;
00503     int i, j;
00504 
00505     /* we can't do this instantly, because of rounding errors on extents calculation */
00506     /* shift vertexes */
00507     for (i = 0, vert = r_worldmodel->bsp.vertexes; i < r_worldmodel->bsp.numvertexes; i++, vert++)
00508         for (j = 0; j < 3; j++)
00509             vert->position[j] += shift[j];
00510 
00511     /* shift planes */
00512     for (i = 0, plane = r_worldmodel->bsp.planes; i < r_worldmodel->bsp.numplanes; i++, plane++)
00513         for (j = 0; j < 3; j++)
00514             plane->dist += plane->normal[j] * shift[j];
00515 }
00516 
00525 static void R_LoadBspVertexArrays (model_t *mod)
00526 {
00527     int i, j;
00528     int vertind, coordind, tangind;
00529     float *vecShifted;
00530     float soff, toff, s, t;
00531     float *point, *sdir, *tdir;
00532     vec4_t tangent;
00533     vec3_t binormal;
00534     mBspSurface_t *surf;
00535     mBspVertex_t *vert;
00536     int vertexcount;
00537 
00538     vertind = coordind = tangind = vertexcount = 0;
00539 
00540     for (i = 0, surf = mod->bsp.surfaces; i < mod->bsp.numsurfaces; i++, surf++)
00541         for (j = 0; j < surf->numedges; j++)
00542             vertexcount++;
00543 
00544     surf = mod->bsp.surfaces;
00545 
00546     /* allocate the vertex arrays */
00547     mod->bsp.texcoords = (GLfloat *)Mem_PoolAlloc(vertexcount * 2 * sizeof(GLfloat), vid_modelPool, 0);
00548     mod->bsp.lmtexcoords = (GLfloat *)Mem_PoolAlloc(vertexcount * 2 * sizeof(GLfloat), vid_modelPool, 0);
00549     mod->bsp.verts = (GLfloat *)Mem_PoolAlloc(vertexcount * 3 * sizeof(GLfloat), vid_modelPool, 0);
00550     mod->bsp.normals = (GLfloat *)Mem_PoolAlloc(vertexcount * 3 * sizeof(GLfloat), vid_modelPool, 0);
00551     mod->bsp.tangents = (GLfloat *)Mem_PoolAlloc(vertexcount * 4 * sizeof(GLfloat), vid_modelPool, 0);
00552 
00553     for (i = 0; i < mod->bsp.numsurfaces; i++, surf++) {
00554         surf->index = vertind / 3;
00555 
00556         for (j = 0; j < surf->numedges; j++) {
00557             const float *normal;
00558             const int index = mod->bsp.surfedges[surf->firstedge + j];
00559 
00560             if (vertind >= MAX_GL_ARRAY_LENGTH * 3)
00561                 Com_Error(ERR_DROP, "R_LoadBspVertexArrays: Exceeded MAX_GL_ARRAY_LENGTH %i", vertind);
00562 
00563             /* vertex */
00564             if (index > 0) {  /* negative indices to differentiate which end of the edge */
00565                 const mBspEdge_t *edge = &mod->bsp.edges[index];
00566                 vert = &mod->bsp.vertexes[edge->v[0]];
00567             } else {
00568                 const mBspEdge_t *edge = &mod->bsp.edges[-index];
00569                 vert = &mod->bsp.vertexes[edge->v[1]];
00570             }
00571 
00572             point = vert->position;
00573 
00574             /* shift it for assembled maps */
00575             vecShifted = &mod->bsp.verts[vertind];
00576             /* origin (func_door, func_rotating) bmodels must not have shifted vertices,
00577              * they are translated by their entity origin value */
00578             if (surf->isOriginBrushModel)
00579                 VectorCopy(point, vecShifted);
00580             else
00581                 VectorAdd(point, shift, vecShifted);
00582 
00583             /* texture directional vectors and offsets */
00584             sdir = surf->texinfo->uv;
00585             soff = surf->texinfo->u_offset;
00586 
00587             tdir = surf->texinfo->vv;
00588             toff = surf->texinfo->v_offset;
00589 
00590             /* texture coordinates */
00591             s = DotProduct(point, sdir) + soff;
00592             s /= surf->texinfo->image->width;
00593 
00594             t = DotProduct(point, tdir) + toff;
00595             t /= surf->texinfo->image->height;
00596 
00597             mod->bsp.texcoords[coordind + 0] = s;
00598             mod->bsp.texcoords[coordind + 1] = t;
00599 
00600             if (surf->flags & MSURF_LIGHTMAP) {  /* lightmap coordinates */
00601                 s = DotProduct(point, sdir) + soff;
00602                 s -= surf->stmins[0];
00603                 s += surf->light_s * surf->lightmap_scale;
00604                 s += surf->lightmap_scale / 2.0;
00605                 s /= r_lightmaps.size * surf->lightmap_scale;
00606 
00607                 t = DotProduct(point, tdir) + toff;
00608                 t -= surf->stmins[1];
00609                 t += surf->light_t * surf->lightmap_scale;
00610                 t += surf->lightmap_scale / 2.0;
00611                 t /= r_lightmaps.size * surf->lightmap_scale;
00612             }
00613 
00614             mod->bsp.lmtexcoords[coordind + 0] = s;
00615             mod->bsp.lmtexcoords[coordind + 1] = t;
00616 
00617             /* normal vectors */
00618             if (surf->texinfo->flags & SURF_PHONG &&
00619                     !VectorCompare(vert->normal, vec3_origin))
00620                 normal = vert->normal; /* phong shaded */
00621             else
00622                 normal = surf->normal; /* per plane */
00623 
00624             memcpy(&mod->bsp.normals[vertind], normal, sizeof(vec3_t));
00625 
00626             /* tangent vector */
00627             TangentVectors(normal, sdir, tdir, tangent, binormal);
00628             memcpy(&mod->bsp.tangents[tangind], tangent, sizeof(vec4_t));
00629 
00630             vertind += 3;
00631             coordind += 2;
00632             tangind += 4;
00633         }
00634     }
00635 
00636     if (qglBindBuffer) {
00637         /* and also the vertex buffer objects */
00638         qglGenBuffers(1, &mod->bsp.vertex_buffer);
00639         qglBindBuffer(GL_ARRAY_BUFFER, mod->bsp.vertex_buffer);
00640         qglBufferData(GL_ARRAY_BUFFER, vertind * sizeof(GLfloat), mod->bsp.verts, GL_STATIC_DRAW);
00641 
00642         qglGenBuffers(1, &mod->bsp.texcoord_buffer);
00643         qglBindBuffer(GL_ARRAY_BUFFER, mod->bsp.texcoord_buffer);
00644         qglBufferData(GL_ARRAY_BUFFER, coordind * sizeof(GLfloat), mod->bsp.texcoords, GL_STATIC_DRAW);
00645 
00646         qglGenBuffers(1, &mod->bsp.lmtexcoord_buffer);
00647         qglBindBuffer(GL_ARRAY_BUFFER, mod->bsp.lmtexcoord_buffer);
00648         qglBufferData(GL_ARRAY_BUFFER, coordind * sizeof(GLfloat), mod->bsp.lmtexcoords, GL_STATIC_DRAW);
00649 
00650         qglGenBuffers(1, &mod->bsp.normal_buffer);
00651         qglBindBuffer(GL_ARRAY_BUFFER, mod->bsp.normal_buffer);
00652         qglBufferData(GL_ARRAY_BUFFER, vertind * sizeof(GLfloat), mod->bsp.normals, GL_STATIC_DRAW);
00653 
00654         qglGenBuffers(1, &mod->bsp.tangent_buffer);
00655         qglBindBuffer(GL_ARRAY_BUFFER, mod->bsp.tangent_buffer);
00656         qglBufferData(GL_ARRAY_BUFFER, tangind * sizeof(GLfloat), mod->bsp.tangents, GL_STATIC_DRAW);
00657 
00658         qglBindBuffer(GL_ARRAY_BUFFER, 0);
00659     }
00660 }
00661 
00663 static mBspSurfaces_t *r_sorted_surfaces[MAX_GL_TEXTURES];
00664 
00665 static void R_SortSurfacesArrays_ (mBspSurfaces_t *surfs)
00666 {
00667     int i, j;
00668 
00669     for (i = 0; i < surfs->count; i++) {
00670         const int texnum = surfs->surfaces[i]->texinfo->image->texnum;
00671         R_SurfaceToSurfaces(r_sorted_surfaces[texnum], surfs->surfaces[i]);
00672     }
00673 
00674     surfs->count = 0;
00675 
00676     for (i = 0; i < r_numImages; i++) {
00677         mBspSurfaces_t *sorted = r_sorted_surfaces[r_images[i].texnum];
00678         if (sorted && sorted->count) {
00679             for (j = 0; j < sorted->count; j++)
00680                 R_SurfaceToSurfaces(surfs, sorted->surfaces[j]);
00681 
00682             sorted->count = 0;
00683         }
00684     }
00685 }
00686 
00691 static void R_SortSurfacesArrays (const model_t *mod)
00692 {
00693     const mBspSurface_t *surf, *s;
00694     int i, ns;
00695 
00696     /* resolve the start surface and total surface count */
00697     if (mod->type == mod_bsp) {  /*  world model */
00698         s = mod->bsp.surfaces;
00699         ns = mod->bsp.numsurfaces;
00700     } else {  /* submodels */
00701         s = &mod->bsp.surfaces[mod->bsp.firstmodelsurface];
00702         ns = mod->bsp.nummodelsurfaces;
00703     }
00704 
00705     memset(r_sorted_surfaces, 0, sizeof(r_sorted_surfaces));
00706 
00707     /* allocate the per-texture surfaces arrays and determine counts */
00708     for (i = 0, surf = s; i < ns; i++, surf++) {
00709         mBspSurfaces_t *surfs = r_sorted_surfaces[surf->texinfo->image->texnum];
00710         if (!surfs) {  /* allocate it */
00711             surfs = (mBspSurfaces_t *)Mem_PoolAlloc(sizeof(*surfs), vid_modelPool, 0);
00712             r_sorted_surfaces[surf->texinfo->image->texnum] = surfs;
00713         }
00714 
00715         surfs->count++;
00716     }
00717 
00718     /* allocate the surfaces pointers based on counts */
00719     for (i = 0; i < r_numImages; i++) {
00720         mBspSurfaces_t *surfs = r_sorted_surfaces[r_images[i].texnum];
00721         if (surfs) {
00722             surfs->surfaces = (mBspSurface_t **)Mem_PoolAlloc(sizeof(mBspSurface_t *) * surfs->count, vid_modelPool, 0);
00723             surfs->count = 0;
00724         }
00725     }
00726 
00727     /* sort the model's surfaces arrays into the per-texture arrays */
00728     for (i = 0; i < NUM_SURFACES_ARRAYS; i++) {
00729         if (mod->bsp.sorted_surfaces[i]->count) {
00730             R_SortSurfacesArrays_(mod->bsp.sorted_surfaces[i]);
00731             Com_DPrintf(DEBUG_RENDERER, "%i: #%i surfaces\n", i, mod->bsp.sorted_surfaces[i]->count);
00732         }
00733     }
00734 
00735     /* free the per-texture surfaces arrays */
00736     for (i = 0; i < r_numImages; i++) {
00737         mBspSurfaces_t *surfs = r_sorted_surfaces[r_images[i].texnum];
00738         if (surfs) {
00739             if (surfs->surfaces)
00740                 Mem_Free(surfs->surfaces);
00741             Mem_Free(surfs);
00742         }
00743     }
00744 }
00745 
00746 static void R_LoadSurfacesArrays_ (model_t *mod)
00747 {
00748     mBspSurface_t *surf, *s;
00749     int i, ns;
00750 
00751     /* allocate the surfaces array structures */
00752     for (i = 0; i < NUM_SURFACES_ARRAYS; i++)
00753         mod->bsp.sorted_surfaces[i] = (mBspSurfaces_t *)Mem_PoolAlloc(sizeof(mBspSurfaces_t), vid_modelPool, 0);
00754 
00755     /* resolve the start surface and total surface count */
00756     if (mod->type == mod_bsp) {  /* world model */
00757         s = mod->bsp.surfaces;
00758         ns = mod->bsp.numsurfaces;
00759     } else {  /* submodels */
00760         s = &mod->bsp.surfaces[mod->bsp.firstmodelsurface];
00761         ns = mod->bsp.nummodelsurfaces;
00762     }
00763 
00764     /* determine the maximum counts for each rendered type in order to
00765      * allocate only what is necessary for the specified model */
00766     for (i = 0, surf = s; i < ns; i++, surf++) {
00767         const mBspTexInfo_t *texinfo = surf->texinfo;
00768         const material_t *material = &texinfo->image->material;
00769         if (texinfo->flags & (SURF_BLEND33 | SURF_BLEND66)) {
00770             if (texinfo->flags & SURF_WARP)
00771                 mod->bsp.blend_warp_surfaces->count++;
00772             else
00773                 mod->bsp.blend_surfaces->count++;
00774         } else {
00775             if (texinfo->flags & SURF_WARP)
00776                 mod->bsp.opaque_warp_surfaces->count++;
00777             else if (texinfo->flags & SURF_ALPHATEST)
00778                 mod->bsp.alpha_test_surfaces->count++;
00779             else
00780                 mod->bsp.opaque_surfaces->count++;
00781         }
00782 
00783         if (material->flags & STAGE_RENDER)
00784             mod->bsp.material_surfaces->count++;
00785 
00786         if (material->flags & STAGE_FLARE)
00787             mod->bsp.flare_surfaces->count++;
00788     }
00789 
00790     /* allocate the surfaces pointers based on the counts */
00791     for (i = 0; i < NUM_SURFACES_ARRAYS; i++) {
00792         mBspSurfaces_t *surfaces = mod->bsp.sorted_surfaces[i];
00793         if (surfaces->count) {
00794             surfaces->surfaces = (mBspSurface_t **)Mem_PoolAlloc(sizeof(*surfaces) * surfaces->count, vid_modelPool, 0);
00795             surfaces->count = 0;
00796         }
00797     }
00798 
00799     /* iterate the surfaces again, populating the allocated arrays based
00800      * on primary render type */
00801     for (i = 0, surf = s; i < ns; i++, surf++) {
00802         const mBspTexInfo_t *texinfo = surf->texinfo;
00803         const material_t *material = &texinfo->image->material;
00804         if (texinfo->flags & (SURF_BLEND33 | SURF_BLEND66)) {
00805             if (texinfo->flags & SURF_WARP)
00806                 R_SurfaceToSurfaces(mod->bsp.blend_warp_surfaces, surf);
00807             else
00808                 R_SurfaceToSurfaces(mod->bsp.blend_surfaces, surf);
00809         } else {
00810             if (texinfo->flags & SURF_WARP)
00811                 R_SurfaceToSurfaces(mod->bsp.opaque_warp_surfaces, surf);
00812             else if (texinfo->flags & SURF_ALPHATEST)
00813                 R_SurfaceToSurfaces(mod->bsp.alpha_test_surfaces, surf);
00814             else
00815                 R_SurfaceToSurfaces(mod->bsp.opaque_surfaces, surf);
00816         }
00817 
00818         if (material->flags & STAGE_RENDER)
00819             R_SurfaceToSurfaces(mod->bsp.material_surfaces, surf);
00820 
00821         if (material->flags & STAGE_FLARE)
00822             R_SurfaceToSurfaces(mod->bsp.flare_surfaces, surf);
00823     }
00824 
00825     /* now sort them by texture */
00826     R_SortSurfacesArrays(mod);
00827 }
00828 
00829 static void R_LoadSurfacesArrays (void)
00830 {
00831     int i;
00832 
00833     for (i = 0; i < r_numMapTiles; i++)
00834         R_LoadSurfacesArrays_(r_mapTiles[i]);
00835 
00836     for (i = 0; i < r_numModelsInline; i++)
00837         R_LoadSurfacesArrays_(&r_modelsInline[i]);
00838 }
00839 
00843 static void R_SetModel (mBspNode_t *node, model_t *mod)
00844 {
00845     node->model = mod;
00846 
00847     if (node->contents > CONTENTS_NODE)
00848         return;
00849 
00850     R_SetModel(node->children[0], mod);
00851     R_SetModel(node->children[1], mod);
00852 }
00853 
00854 
00858 static void R_RecursiveSetModel (mBspNode_t *node, model_t *mod)
00859 {
00860     /* skip special pathfinding nodes */
00861     if (node->contents == CONTENTS_PATHFINDING_NODE) {
00862         R_RecursiveSetModel(node->children[0], mod);
00863         R_RecursiveSetModel(node->children[1], mod);
00864     } else {
00865         R_SetModel(node, mod);
00866     }
00867 }
00868 
00872 static void R_SetupSubmodels (void)
00873 {
00874     int i, j;
00875 
00876     /* set up the submodels, the first 255 submodels are the models of the
00877      * different levels, don't care about them */
00878     for (i = NUM_REGULAR_MODELS; i < r_worldmodel->bsp.numsubmodels; i++) {
00879         model_t *mod = &r_modelsInline[r_numModelsInline];
00880         const mBspHeader_t *sub = &r_worldmodel->bsp.submodels[i];
00881 
00882         /* copy most info from world */
00883         *mod = *r_worldmodel;
00884         mod->type = mod_bsp_submodel;
00885 
00886         Com_sprintf(mod->name, sizeof(mod->name), "*%d", i);
00887 
00888         /* copy the rest from the submodel */
00889         VectorCopy(sub->maxs, mod->maxs);
00890         VectorCopy(sub->mins, mod->mins);
00891         mod->radius = sub->radius;
00892 
00893         mod->bsp.firstnode = sub->headnode;
00894         mod->bsp.nodes = &r_worldmodel->bsp.nodes[mod->bsp.firstnode];
00895         mod->bsp.maptile = r_numMapTiles - 1;
00896         if (mod->bsp.firstnode >= r_worldmodel->bsp.numnodes)
00897             Com_Error(ERR_DROP, "R_SetupSubmodels: Inline model %i has bad firstnode", i);
00898 
00899         R_RecursiveSetModel(mod->bsp.nodes, mod);
00900 
00901         mod->bsp.firstmodelsurface = sub->firstface;
00902         mod->bsp.nummodelsurfaces = sub->numfaces;
00903 
00904         /* submodel vertices of the surfaces must not be shifted in case of rmas */
00905         for (j = mod->bsp.firstmodelsurface; j < mod->bsp.firstmodelsurface + mod->bsp.nummodelsurfaces; j++) {
00906             mod->bsp.surfaces[j].isOriginBrushModel = (mod->bsp.surfaces[j].texinfo->flags & SURF_ORIGIN);
00907         }
00908 
00909         /*mod->bsp.numleafs = sub->visleafs;*/
00910         r_numModelsInline++;
00911     }
00912 }
00913 
00924 static void R_ModAddMapTile (const char *name, qboolean day, int sX, int sY, int sZ)
00925 {
00926     int i;
00927     byte *buffer;
00928     dBspHeader_t *header;
00929     const int lightingLump = day ? LUMP_LIGHTING_DAY : LUMP_LIGHTING_NIGHT;
00930 
00931     /* get new model */
00932     if (r_numModels < 0 || r_numModels >= MAX_MOD_KNOWN)
00933         Com_Error(ERR_DROP, "R_ModAddMapTile: r_numModels >= MAX_MOD_KNOWN");
00934 
00935     if (r_numMapTiles < 0 || r_numMapTiles >= MAX_MAPTILES)
00936         Com_Error(ERR_DROP, "R_ModAddMapTile: Too many map tiles");
00937 
00938     /* alloc model and tile */
00939     r_worldmodel = &r_models[r_numModels++];
00940     r_mapTiles[r_numMapTiles++] = r_worldmodel;
00941     memset(r_worldmodel, 0, sizeof(*r_worldmodel));
00942     Com_sprintf(r_worldmodel->name, sizeof(r_worldmodel->name), "maps/%s.bsp", name);
00943 
00944     /* load the file */
00945     FS_LoadFile(r_worldmodel->name, &buffer);
00946     if (!buffer)
00947         Com_Error(ERR_DROP, "R_ModAddMapTile: %s not found", r_worldmodel->name);
00948 
00949     /* init */
00950     r_worldmodel->type = mod_bsp;
00951 
00952     /* prepare shifting */
00953     VectorSet(shift, sX * UNIT_SIZE, sY * UNIT_SIZE, sZ * UNIT_SIZE);
00954 
00955     /* test version */
00956     header = (dBspHeader_t *) buffer;
00957     i = LittleLong(header->version);
00958     if (i != BSPVERSION)
00959         Com_Error(ERR_DROP, "R_ModAddMapTile: %s has wrong version number (%i should be %i)", r_worldmodel->name, i, BSPVERSION);
00960 
00961     /* swap all the lumps */
00962     mod_base = (byte *) header;
00963 
00964     for (i = 0; i < (int)sizeof(dBspHeader_t) / 4; i++)
00965         ((int *) header)[i] = LittleLong(((int *) header)[i]);
00966 
00967     /* load into heap */
00968     R_ModLoadVertexes(&header->lumps[LUMP_VERTEXES]);
00969     R_ModLoadNormals(&header->lumps[LUMP_NORMALS]);
00970     R_ModLoadEdges(&header->lumps[LUMP_EDGES]);
00971     R_ModLoadSurfedges(&header->lumps[LUMP_SURFEDGES]);
00972     R_ModLoadLighting(&header->lumps[lightingLump]);
00973     R_ModLoadPlanes(&header->lumps[LUMP_PLANES]);
00974     R_ModLoadTexinfo(&header->lumps[LUMP_TEXINFO]);
00975     R_ModLoadSurfaces(day, &header->lumps[LUMP_FACES]);
00976     R_ModLoadLeafs(&header->lumps[LUMP_LEAFS]);
00977     R_ModLoadNodes(&header->lumps[LUMP_NODES]);
00978     R_ModLoadSubmodels(&header->lumps[LUMP_MODELS]);
00979 
00980     R_SetupSubmodels();
00981 
00982     R_LoadBspVertexArrays(r_worldmodel);
00983 
00984     /* in case of random map assembly shift some vectors */
00985     if (VectorNotEmpty(shift))
00986         R_ModShiftTile();
00987 
00988     FS_FreeFile(buffer);
00989 }
00990 
00991 static void R_ModEndLoading (const char *mapName)
00992 {
00993     R_EndBuildingLightmaps();
00994     R_LoadMaterials(mapName);
00995     R_LoadSurfacesArrays();
00996 }
00997 
01017 void R_ModBeginLoading (const char *tiles, qboolean day, const char *pos, const char *mapName)
01018 {
01019     char name[MAX_VAR];
01020     char base[MAX_QPATH];
01021     ipos3_t sh;
01022     int i;
01023 
01024     assert(mapName);
01025 
01026     R_FreeWorldImages();
01027 
01028     /* clear any lights leftover in the active list from previous maps */
01029     R_ClearActiveLights();
01030 
01031     /* init */
01032     R_BeginBuildingLightmaps();
01033     r_numModelsInline = 0;
01034     r_numMapTiles = 0;
01035 
01036     /* load tiles */
01037     while (tiles) {
01038         /* get tile name */
01039         const char *token = Com_Parse(&tiles);
01040         if (!tiles) {
01041             /* finish */
01042             R_ModEndLoading(mapName);
01043             return;
01044         }
01045 
01046         /* get base path */
01047         if (token[0] == '-') {
01048             Q_strncpyz(base, token + 1, sizeof(base));
01049             continue;
01050         }
01051 
01052         /* get tile name */
01053         if (token[0] == '+')
01054             Com_sprintf(name, sizeof(name), "%s%s", base, token + 1);
01055         else
01056             Q_strncpyz(name, token, sizeof(name));
01057 
01058         if (pos && pos[0]) {
01059             /* get grid position and add a tile */
01060             for (i = 0; i < 3; i++) {
01061                 token = Com_Parse(&pos);
01062                 if (!pos)
01063                     Com_Error(ERR_DROP, "R_ModBeginLoading: invalid positions\n");
01064                 sh[i] = atoi(token);
01065             }
01066             if (sh[0] <= -(PATHFINDING_WIDTH / 2) || sh[0] >= PATHFINDING_WIDTH / 2)
01067                 Com_Error(ERR_DROP, "R_ModBeginLoading: invalid x position given: %i\n", sh[0]);
01068             if (sh[1] <= -(PATHFINDING_WIDTH / 2) || sh[1] >= PATHFINDING_WIDTH / 2)
01069                 Com_Error(ERR_DROP, "R_ModBeginLoading: invalid y position given: %i\n", sh[1]);
01070             if (sh[2] >= PATHFINDING_HEIGHT)
01071                 Com_Error(ERR_DROP, "R_ModBeginLoading: invalid z position given: %i\n", sh[2]);
01072             R_ModAddMapTile(name, day, sh[0], sh[1], sh[2]);
01073         } else {
01074             /* load only a single tile, if no positions are specified */
01075             R_ModAddMapTile(name, day, 0, 0, 0);
01076             R_ModEndLoading(mapName);
01077             return;
01078         }
01079     }
01080 
01081     Com_Error(ERR_DROP, "R_ModBeginLoading: invalid tile names\n");
01082 }
01083 
01087 void R_ModReloadSurfacesArrays (void)
01088 {
01089     int i, j;
01090 
01091     for (i = 0; i < r_numMapTiles; i++) {
01092         model_t *mod = r_mapTiles[i];
01093         const size_t size = lengthof(mod->bsp.sorted_surfaces);
01094         for (j = 0; j < size; j++)
01095             if (mod->bsp.sorted_surfaces[j]) {
01096                 Mem_Free(mod->bsp.sorted_surfaces[j]);
01097                 mod->bsp.sorted_surfaces[j] = NULL;
01098             }
01099     }
01100     R_LoadSurfacesArrays();
01101 }

Generated by  doxygen 1.6.2