00001
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
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
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
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) {
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
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
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++) {
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 {
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
00309 planenum = LittleShort(in->planenum);
00310 assert(planenum >= 0);
00311 out->plane = r_worldmodel->bsp.planes + planenum;
00312
00313
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
00330 R_SetSurfaceExtents(out, r_worldmodel);
00331
00332 if (!(out->texinfo->flags & SURF_WARP))
00333 out->flags |= MSURF_LIGHTMAP;
00334
00335
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
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
00378 if (p == PLANENUM_LEAF) {
00379
00380
00381 out->plane = NULL;
00382 out->contents = CONTENTS_PATHFINDING_NODE;
00383 parent = NULL;
00384 } else {
00385 out->plane = r_worldmodel->bsp.planes + p;
00386
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
00506
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
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
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
00564 if (index > 0) {
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
00575 vecShifted = &mod->bsp.verts[vertind];
00576
00577
00578 if (surf->isOriginBrushModel)
00579 VectorCopy(point, vecShifted);
00580 else
00581 VectorAdd(point, shift, vecShifted);
00582
00583
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
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) {
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
00618 if (surf->texinfo->flags & SURF_PHONG &&
00619 !VectorCompare(vert->normal, vec3_origin))
00620 normal = vert->normal;
00621 else
00622 normal = surf->normal;
00623
00624 memcpy(&mod->bsp.normals[vertind], normal, sizeof(vec3_t));
00625
00626
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
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
00697 if (mod->type == mod_bsp) {
00698 s = mod->bsp.surfaces;
00699 ns = mod->bsp.numsurfaces;
00700 } else {
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
00708 for (i = 0, surf = s; i < ns; i++, surf++) {
00709 mBspSurfaces_t *surfs = r_sorted_surfaces[surf->texinfo->image->texnum];
00710 if (!surfs) {
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
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
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
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
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
00756 if (mod->type == mod_bsp) {
00757 s = mod->bsp.surfaces;
00758 ns = mod->bsp.numsurfaces;
00759 } else {
00760 s = &mod->bsp.surfaces[mod->bsp.firstmodelsurface];
00761 ns = mod->bsp.nummodelsurfaces;
00762 }
00763
00764
00765
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
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
00800
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
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
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
00877
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
00883 *mod = *r_worldmodel;
00884 mod->type = mod_bsp_submodel;
00885
00886 Com_sprintf(mod->name, sizeof(mod->name), "*%d", i);
00887
00888
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
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
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
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
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
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
00950 r_worldmodel->type = mod_bsp;
00951
00952
00953 VectorSet(shift, sX * UNIT_SIZE, sY * UNIT_SIZE, sZ * UNIT_SIZE);
00954
00955
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
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
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
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
01029 R_ClearActiveLights();
01030
01031
01032 R_BeginBuildingLightmaps();
01033 r_numModelsInline = 0;
01034 r_numMapTiles = 0;
01035
01036
01037 while (tiles) {
01038
01039 const char *token = Com_Parse(&tiles);
01040 if (!tiles) {
01041
01042 R_ModEndLoading(mapName);
01043 return;
01044 }
01045
01046
01047 if (token[0] == '-') {
01048 Q_strncpyz(base, token + 1, sizeof(base));
01049 continue;
01050 }
01051
01052
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
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
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 }