00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "tr_local.h"
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036 static world_t s_worldData;
00037 static byte *fileBase;
00038
00039 int c_subdivisions;
00040 int c_gridVerts;
00041
00042
00043
00044 static void HSVtoRGB( float h, float s, float v, float rgb[3] )
00045 {
00046 int i;
00047 float f;
00048 float p, q, t;
00049
00050 h *= 5;
00051
00052 i = floor( h );
00053 f = h - i;
00054
00055 p = v * ( 1 - s );
00056 q = v * ( 1 - s * f );
00057 t = v * ( 1 - s * ( 1 - f ) );
00058
00059 switch ( i )
00060 {
00061 case 0:
00062 rgb[0] = v;
00063 rgb[1] = t;
00064 rgb[2] = p;
00065 break;
00066 case 1:
00067 rgb[0] = q;
00068 rgb[1] = v;
00069 rgb[2] = p;
00070 break;
00071 case 2:
00072 rgb[0] = p;
00073 rgb[1] = v;
00074 rgb[2] = t;
00075 break;
00076 case 3:
00077 rgb[0] = p;
00078 rgb[1] = q;
00079 rgb[2] = v;
00080 break;
00081 case 4:
00082 rgb[0] = t;
00083 rgb[1] = p;
00084 rgb[2] = v;
00085 break;
00086 case 5:
00087 rgb[0] = v;
00088 rgb[1] = p;
00089 rgb[2] = q;
00090 break;
00091 }
00092 }
00093
00094
00095
00096
00097
00098
00099
00100 static void R_ColorShiftLightingBytes( byte in[4], byte out[4] ) {
00101 int shift, r, g, b;
00102
00103
00104 shift = r_mapOverBrightBits->integer - tr.overbrightBits;
00105
00106
00107 r = in[0] << shift;
00108 g = in[1] << shift;
00109 b = in[2] << shift;
00110
00111
00112 if ( ( r | g | b ) > 255 ) {
00113 int max;
00114
00115 max = r > g ? r : g;
00116 max = max > b ? max : b;
00117 r = r * 255 / max;
00118 g = g * 255 / max;
00119 b = b * 255 / max;
00120 }
00121
00122 out[0] = r;
00123 out[1] = g;
00124 out[2] = b;
00125 out[3] = in[3];
00126 }
00127
00128
00129
00130
00131
00132
00133
00134 #define LIGHTMAP_SIZE 128
00135 static void R_LoadLightmaps( lump_t *l ) {
00136 byte *buf, *buf_p;
00137 int len;
00138 MAC_STATIC byte image[LIGHTMAP_SIZE*LIGHTMAP_SIZE*4];
00139 int i, j;
00140 float maxIntensity = 0;
00141 double sumIntensity = 0;
00142
00143 len = l->filelen;
00144 if ( !len ) {
00145 return;
00146 }
00147 buf = fileBase + l->fileofs;
00148
00149
00150 R_SyncRenderThread();
00151
00152
00153 tr.numLightmaps = len / (LIGHTMAP_SIZE * LIGHTMAP_SIZE * 3);
00154 if ( tr.numLightmaps == 1 ) {
00155
00156
00157 tr.numLightmaps++;
00158 }
00159
00160
00161 if ( r_vertexLight->integer || glConfig.hardwareType == GLHW_PERMEDIA2 ) {
00162 return;
00163 }
00164
00165 for ( i = 0 ; i < tr.numLightmaps ; i++ ) {
00166
00167 buf_p = buf + i * LIGHTMAP_SIZE*LIGHTMAP_SIZE * 3;
00168
00169 if ( r_lightmap->integer == 2 )
00170 {
00171 for ( j = 0; j < LIGHTMAP_SIZE * LIGHTMAP_SIZE; j++ )
00172 {
00173 float r = buf_p[j*3+0];
00174 float g = buf_p[j*3+1];
00175 float b = buf_p[j*3+2];
00176 float intensity;
00177 float out[3];
00178
00179 intensity = 0.33f * r + 0.685f * g + 0.063f * b;
00180
00181 if ( intensity > 255 )
00182 intensity = 1.0f;
00183 else
00184 intensity /= 255.0f;
00185
00186 if ( intensity > maxIntensity )
00187 maxIntensity = intensity;
00188
00189 HSVtoRGB( intensity, 1.00, 0.50, out );
00190
00191 image[j*4+0] = out[0] * 255;
00192 image[j*4+1] = out[1] * 255;
00193 image[j*4+2] = out[2] * 255;
00194 image[j*4+3] = 255;
00195
00196 sumIntensity += intensity;
00197 }
00198 } else {
00199 for ( j = 0 ; j < LIGHTMAP_SIZE * LIGHTMAP_SIZE; j++ ) {
00200 R_ColorShiftLightingBytes( &buf_p[j*3], &image[j*4] );
00201 image[j*4+3] = 255;
00202 }
00203 }
00204 tr.lightmaps[i] = R_CreateImage( va("*lightmap%d",i), image,
00205 LIGHTMAP_SIZE, LIGHTMAP_SIZE, qfalse, qfalse, GL_CLAMP );
00206 }
00207
00208 if ( r_lightmap->integer == 2 ) {
00209 ri.Printf( PRINT_ALL, "Brightest lightmap value: %d\n", ( int ) ( maxIntensity * 255 ) );
00210 }
00211 }
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222 void RE_SetWorldVisData( const byte *vis ) {
00223 tr.externalVisData = vis;
00224 }
00225
00226
00227
00228
00229
00230
00231
00232 static void R_LoadVisibility( lump_t *l ) {
00233 int len;
00234 byte *buf;
00235
00236 len = ( s_worldData.numClusters + 63 ) & ~63;
00237 s_worldData.novis = ri.Hunk_Alloc( len, h_low );
00238 Com_Memset( s_worldData.novis, 0xff, len );
00239
00240 len = l->filelen;
00241 if ( !len ) {
00242 return;
00243 }
00244 buf = fileBase + l->fileofs;
00245
00246 s_worldData.numClusters = LittleLong( ((int *)buf)[0] );
00247 s_worldData.clusterBytes = LittleLong( ((int *)buf)[1] );
00248
00249
00250
00251 if ( tr.externalVisData ) {
00252 s_worldData.vis = tr.externalVisData;
00253 } else {
00254 byte *dest;
00255
00256 dest = ri.Hunk_Alloc( len - 8, h_low );
00257 Com_Memcpy( dest, buf + 8, len - 8 );
00258 s_worldData.vis = dest;
00259 }
00260 }
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270 static shader_t *ShaderForShaderNum( int shaderNum, int lightmapNum ) {
00271 shader_t *shader;
00272 dshader_t *dsh;
00273
00274 shaderNum = LittleLong( shaderNum );
00275 if ( shaderNum < 0 || shaderNum >= s_worldData.numShaders ) {
00276 ri.Error( ERR_DROP, "ShaderForShaderNum: bad num %i", shaderNum );
00277 }
00278 dsh = &s_worldData.shaders[ shaderNum ];
00279
00280 if ( r_vertexLight->integer || glConfig.hardwareType == GLHW_PERMEDIA2 ) {
00281 lightmapNum = LIGHTMAP_BY_VERTEX;
00282 }
00283
00284 if ( r_fullbright->integer ) {
00285 lightmapNum = LIGHTMAP_WHITEIMAGE;
00286 }
00287
00288 shader = R_FindShader( dsh->shader, lightmapNum, qtrue );
00289
00290
00291 if ( shader->defaultShader ) {
00292 return tr.defaultShader;
00293 }
00294
00295 return shader;
00296 }
00297
00298
00299
00300
00301
00302
00303 static void ParseFace( dsurface_t *ds, drawVert_t *verts, msurface_t *surf, int *indexes ) {
00304 int i, j;
00305 srfSurfaceFace_t *cv;
00306 int numPoints, numIndexes;
00307 int lightmapNum;
00308 int sfaceSize, ofsIndexes;
00309
00310 lightmapNum = LittleLong( ds->lightmapNum );
00311
00312
00313 surf->fogIndex = LittleLong( ds->fogNum ) + 1;
00314
00315
00316 surf->shader = ShaderForShaderNum( ds->shaderNum, lightmapNum );
00317 if ( r_singleShader->integer && !surf->shader->isSky ) {
00318 surf->shader = tr.defaultShader;
00319 }
00320
00321 numPoints = LittleLong( ds->numVerts );
00322 if (numPoints > MAX_FACE_POINTS) {
00323 ri.Printf( PRINT_WARNING, "WARNING: MAX_FACE_POINTS exceeded: %i\n", numPoints);
00324 numPoints = MAX_FACE_POINTS;
00325 surf->shader = tr.defaultShader;
00326 }
00327
00328 numIndexes = LittleLong( ds->numIndexes );
00329
00330
00331 sfaceSize = ( int ) &((srfSurfaceFace_t *)0)->points[numPoints];
00332 ofsIndexes = sfaceSize;
00333 sfaceSize += sizeof( int ) * numIndexes;
00334
00335 cv = ri.Hunk_Alloc( sfaceSize, h_low );
00336 cv->surfaceType = SF_FACE;
00337 cv->numPoints = numPoints;
00338 cv->numIndices = numIndexes;
00339 cv->ofsIndices = ofsIndexes;
00340
00341 verts += LittleLong( ds->firstVert );
00342 for ( i = 0 ; i < numPoints ; i++ ) {
00343 for ( j = 0 ; j < 3 ; j++ ) {
00344 cv->points[i][j] = LittleFloat( verts[i].xyz[j] );
00345 }
00346 for ( j = 0 ; j < 2 ; j++ ) {
00347 cv->points[i][3+j] = LittleFloat( verts[i].st[j] );
00348 cv->points[i][5+j] = LittleFloat( verts[i].lightmap[j] );
00349 }
00350 R_ColorShiftLightingBytes( verts[i].color, (byte *)&cv->points[i][7] );
00351 }
00352
00353 indexes += LittleLong( ds->firstIndex );
00354 for ( i = 0 ; i < numIndexes ; i++ ) {
00355 ((int *)((byte *)cv + cv->ofsIndices ))[i] = LittleLong( indexes[ i ] );
00356 }
00357
00358
00359 for ( i = 0 ; i < 3 ; i++ ) {
00360 cv->plane.normal[i] = LittleFloat( ds->lightmapVecs[2][i] );
00361 }
00362 cv->plane.dist = DotProduct( cv->points[0], cv->plane.normal );
00363 SetPlaneSignbits( &cv->plane );
00364 cv->plane.type = PlaneTypeForNormal( cv->plane.normal );
00365
00366 surf->data = (surfaceType_t *)cv;
00367 }
00368
00369
00370
00371
00372
00373
00374
00375 static void ParseMesh ( dsurface_t *ds, drawVert_t *verts, msurface_t *surf ) {
00376 srfGridMesh_t *grid;
00377 int i, j;
00378 int width, height, numPoints;
00379 MAC_STATIC drawVert_t points[MAX_PATCH_SIZE*MAX_PATCH_SIZE];
00380 int lightmapNum;
00381 vec3_t bounds[2];
00382 vec3_t tmpVec;
00383 static surfaceType_t skipData = SF_SKIP;
00384
00385 lightmapNum = LittleLong( ds->lightmapNum );
00386
00387
00388 surf->fogIndex = LittleLong( ds->fogNum ) + 1;
00389
00390
00391 surf->shader = ShaderForShaderNum( ds->shaderNum, lightmapNum );
00392 if ( r_singleShader->integer && !surf->shader->isSky ) {
00393 surf->shader = tr.defaultShader;
00394 }
00395
00396
00397
00398 if ( s_worldData.shaders[ LittleLong( ds->shaderNum ) ].surfaceFlags & SURF_NODRAW ) {
00399 surf->data = &skipData;
00400 return;
00401 }
00402
00403 width = LittleLong( ds->patchWidth );
00404 height = LittleLong( ds->patchHeight );
00405
00406 verts += LittleLong( ds->firstVert );
00407 numPoints = width * height;
00408 for ( i = 0 ; i < numPoints ; i++ ) {
00409 for ( j = 0 ; j < 3 ; j++ ) {
00410 points[i].xyz[j] = LittleFloat( verts[i].xyz[j] );
00411 points[i].normal[j] = LittleFloat( verts[i].normal[j] );
00412 }
00413 for ( j = 0 ; j < 2 ; j++ ) {
00414 points[i].st[j] = LittleFloat( verts[i].st[j] );
00415 points[i].lightmap[j] = LittleFloat( verts[i].lightmap[j] );
00416 }
00417 R_ColorShiftLightingBytes( verts[i].color, points[i].color );
00418 }
00419
00420
00421 grid = R_SubdividePatchToGrid( width, height, points );
00422 surf->data = (surfaceType_t *)grid;
00423
00424
00425
00426
00427 for ( i = 0 ; i < 3 ; i++ ) {
00428 bounds[0][i] = LittleFloat( ds->lightmapVecs[0][i] );
00429 bounds[1][i] = LittleFloat( ds->lightmapVecs[1][i] );
00430 }
00431 VectorAdd( bounds[0], bounds[1], bounds[1] );
00432 VectorScale( bounds[1], 0.5f, grid->lodOrigin );
00433 VectorSubtract( bounds[0], grid->lodOrigin, tmpVec );
00434 grid->lodRadius = VectorLength( tmpVec );
00435 }
00436
00437
00438
00439
00440
00441
00442 static void ParseTriSurf( dsurface_t *ds, drawVert_t *verts, msurface_t *surf, int *indexes ) {
00443 srfTriangles_t *tri;
00444 int i, j;
00445 int numVerts, numIndexes;
00446
00447
00448 surf->fogIndex = LittleLong( ds->fogNum ) + 1;
00449
00450
00451 surf->shader = ShaderForShaderNum( ds->shaderNum, LIGHTMAP_BY_VERTEX );
00452 if ( r_singleShader->integer && !surf->shader->isSky ) {
00453 surf->shader = tr.defaultShader;
00454 }
00455
00456 numVerts = LittleLong( ds->numVerts );
00457 numIndexes = LittleLong( ds->numIndexes );
00458
00459 tri = ri.Hunk_Alloc( sizeof( *tri ) + numVerts * sizeof( tri->verts[0] )
00460 + numIndexes * sizeof( tri->indexes[0] ), h_low );
00461 tri->surfaceType = SF_TRIANGLES;
00462 tri->numVerts = numVerts;
00463 tri->numIndexes = numIndexes;
00464 tri->verts = (drawVert_t *)(tri + 1);
00465 tri->indexes = (int *)(tri->verts + tri->numVerts );
00466
00467 surf->data = (surfaceType_t *)tri;
00468
00469
00470 ClearBounds( tri->bounds[0], tri->bounds[1] );
00471 verts += LittleLong( ds->firstVert );
00472 for ( i = 0 ; i < numVerts ; i++ ) {
00473 for ( j = 0 ; j < 3 ; j++ ) {
00474 tri->verts[i].xyz[j] = LittleFloat( verts[i].xyz[j] );
00475 tri->verts[i].normal[j] = LittleFloat( verts[i].normal[j] );
00476 }
00477 AddPointToBounds( tri->verts[i].xyz, tri->bounds[0], tri->bounds[1] );
00478 for ( j = 0 ; j < 2 ; j++ ) {
00479 tri->verts[i].st[j] = LittleFloat( verts[i].st[j] );
00480 tri->verts[i].lightmap[j] = LittleFloat( verts[i].lightmap[j] );
00481 }
00482
00483 R_ColorShiftLightingBytes( verts[i].color, tri->verts[i].color );
00484 }
00485
00486
00487 indexes += LittleLong( ds->firstIndex );
00488 for ( i = 0 ; i < numIndexes ; i++ ) {
00489 tri->indexes[i] = LittleLong( indexes[i] );
00490 if ( tri->indexes[i] < 0 || tri->indexes[i] >= numVerts ) {
00491 ri.Error( ERR_DROP, "Bad index in triangle surface" );
00492 }
00493 }
00494 }
00495
00496
00497
00498
00499
00500
00501 static void ParseFlare( dsurface_t *ds, drawVert_t *verts, msurface_t *surf, int *indexes ) {
00502 srfFlare_t *flare;
00503 int i;
00504
00505
00506 surf->fogIndex = LittleLong( ds->fogNum ) + 1;
00507
00508
00509 surf->shader = ShaderForShaderNum( ds->shaderNum, LIGHTMAP_BY_VERTEX );
00510 if ( r_singleShader->integer && !surf->shader->isSky ) {
00511 surf->shader = tr.defaultShader;
00512 }
00513
00514 flare = ri.Hunk_Alloc( sizeof( *flare ), h_low );
00515 flare->surfaceType = SF_FLARE;
00516
00517 surf->data = (surfaceType_t *)flare;
00518
00519 for ( i = 0 ; i < 3 ; i++ ) {
00520 flare->origin[i] = LittleFloat( ds->lightmapOrigin[i] );
00521 flare->color[i] = LittleFloat( ds->lightmapVecs[0][i] );
00522 flare->normal[i] = LittleFloat( ds->lightmapVecs[2][i] );
00523 }
00524 }
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534 int R_MergedWidthPoints(srfGridMesh_t *grid, int offset) {
00535 int i, j;
00536
00537 for (i = 1; i < grid->width-1; i++) {
00538 for (j = i + 1; j < grid->width-1; j++) {
00539 if ( fabs(grid->verts[i + offset].xyz[0] - grid->verts[j + offset].xyz[0]) > .1) continue;
00540 if ( fabs(grid->verts[i + offset].xyz[1] - grid->verts[j + offset].xyz[1]) > .1) continue;
00541 if ( fabs(grid->verts[i + offset].xyz[2] - grid->verts[j + offset].xyz[2]) > .1) continue;
00542 return qtrue;
00543 }
00544 }
00545 return qfalse;
00546 }
00547
00548
00549
00550
00551
00552
00553
00554
00555 int R_MergedHeightPoints(srfGridMesh_t *grid, int offset) {
00556 int i, j;
00557
00558 for (i = 1; i < grid->height-1; i++) {
00559 for (j = i + 1; j < grid->height-1; j++) {
00560 if ( fabs(grid->verts[grid->width * i + offset].xyz[0] - grid->verts[grid->width * j + offset].xyz[0]) > .1) continue;
00561 if ( fabs(grid->verts[grid->width * i + offset].xyz[1] - grid->verts[grid->width * j + offset].xyz[1]) > .1) continue;
00562 if ( fabs(grid->verts[grid->width * i + offset].xyz[2] - grid->verts[grid->width * j + offset].xyz[2]) > .1) continue;
00563 return qtrue;
00564 }
00565 }
00566 return qfalse;
00567 }
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578 void R_FixSharedVertexLodError_r( int start, srfGridMesh_t *grid1 ) {
00579 int j, k, l, m, n, offset1, offset2, touch;
00580 srfGridMesh_t *grid2;
00581
00582 for ( j = start; j < s_worldData.numsurfaces; j++ ) {
00583
00584 grid2 = (srfGridMesh_t *) s_worldData.surfaces[j].data;
00585
00586 if ( grid2->surfaceType != SF_GRID ) continue;
00587
00588 if ( grid2->lodFixed == 2 ) continue;
00589
00590 if ( grid1->lodRadius != grid2->lodRadius ) continue;
00591
00592 if ( grid1->lodOrigin[0] != grid2->lodOrigin[0] ) continue;
00593 if ( grid1->lodOrigin[1] != grid2->lodOrigin[1] ) continue;
00594 if ( grid1->lodOrigin[2] != grid2->lodOrigin[2] ) continue;
00595
00596 touch = qfalse;
00597 for (n = 0; n < 2; n++) {
00598
00599 if (n) offset1 = (grid1->height-1) * grid1->width;
00600 else offset1 = 0;
00601 if (R_MergedWidthPoints(grid1, offset1)) continue;
00602 for (k = 1; k < grid1->width-1; k++) {
00603 for (m = 0; m < 2; m++) {
00604
00605 if (m) offset2 = (grid2->height-1) * grid2->width;
00606 else offset2 = 0;
00607 if (R_MergedWidthPoints(grid2, offset2)) continue;
00608 for ( l = 1; l < grid2->width-1; l++) {
00609
00610 if ( fabs(grid1->verts[k + offset1].xyz[0] - grid2->verts[l + offset2].xyz[0]) > .1) continue;
00611 if ( fabs(grid1->verts[k + offset1].xyz[1] - grid2->verts[l + offset2].xyz[1]) > .1) continue;
00612 if ( fabs(grid1->verts[k + offset1].xyz[2] - grid2->verts[l + offset2].xyz[2]) > .1) continue;
00613
00614 grid2->widthLodError[l] = grid1->widthLodError[k];
00615 touch = qtrue;
00616 }
00617 }
00618 for (m = 0; m < 2; m++) {
00619
00620 if (m) offset2 = grid2->width-1;
00621 else offset2 = 0;
00622 if (R_MergedHeightPoints(grid2, offset2)) continue;
00623 for ( l = 1; l < grid2->height-1; l++) {
00624
00625 if ( fabs(grid1->verts[k + offset1].xyz[0] - grid2->verts[grid2->width * l + offset2].xyz[0]) > .1) continue;
00626 if ( fabs(grid1->verts[k + offset1].xyz[1] - grid2->verts[grid2->width * l + offset2].xyz[1]) > .1) continue;
00627 if ( fabs(grid1->verts[k + offset1].xyz[2] - grid2->verts[grid2->width * l + offset2].xyz[2]) > .1) continue;
00628
00629 grid2->heightLodError[l] = grid1->widthLodError[k];
00630 touch = qtrue;
00631 }
00632 }
00633 }
00634 }
00635 for (n = 0; n < 2; n++) {
00636
00637 if (n) offset1 = grid1->width-1;
00638 else offset1 = 0;
00639 if (R_MergedHeightPoints(grid1, offset1)) continue;
00640 for (k = 1; k < grid1->height-1; k++) {
00641 for (m = 0; m < 2; m++) {
00642
00643 if (m) offset2 = (grid2->height-1) * grid2->width;
00644 else offset2 = 0;
00645 if (R_MergedWidthPoints(grid2, offset2)) continue;
00646 for ( l = 1; l < grid2->width-1; l++) {
00647
00648 if ( fabs(grid1->verts[grid1->width * k + offset1].xyz[0] - grid2->verts[l + offset2].xyz[0]) > .1) continue;
00649 if ( fabs(grid1->verts[grid1->width * k + offset1].xyz[1] - grid2->verts[l + offset2].xyz[1]) > .1) continue;
00650 if ( fabs(grid1->verts[grid1->width * k + offset1].xyz[2] - grid2->verts[l + offset2].xyz[2]) > .1) continue;
00651
00652 grid2->widthLodError[l] = grid1->heightLodError[k];
00653 touch = qtrue;
00654 }
00655 }
00656 for (m = 0; m < 2; m++) {
00657
00658 if (m) offset2 = grid2->width-1;
00659 else offset2 = 0;
00660 if (R_MergedHeightPoints(grid2, offset2)) continue;
00661 for ( l = 1; l < grid2->height-1; l++) {
00662
00663 if ( fabs(grid1->verts[grid1->width * k + offset1].xyz[0] - grid2->verts[grid2->width * l + offset2].xyz[0]) > .1) continue;
00664 if ( fabs(grid1->verts[grid1->width * k + offset1].xyz[1] - grid2->verts[grid2->width * l + offset2].xyz[1]) > .1) continue;
00665 if ( fabs(grid1->verts[grid1->width * k + offset1].xyz[2] - grid2->verts[grid2->width * l + offset2].xyz[2]) > .1) continue;
00666
00667 grid2->heightLodError[l] = grid1->heightLodError[k];
00668 touch = qtrue;
00669 }
00670 }
00671 }
00672 }
00673 if (touch) {
00674 grid2->lodFixed = 2;
00675 R_FixSharedVertexLodError_r ( start, grid2 );
00676
00677
00678 }
00679 }
00680 }
00681
00682
00683
00684
00685
00686
00687
00688
00689
00690 void R_FixSharedVertexLodError( void ) {
00691 int i;
00692 srfGridMesh_t *grid1;
00693
00694 for ( i = 0; i < s_worldData.numsurfaces; i++ ) {
00695
00696 grid1 = (srfGridMesh_t *) s_worldData.surfaces[i].data;
00697
00698 if ( grid1->surfaceType != SF_GRID )
00699 continue;
00700
00701 if ( grid1->lodFixed )
00702 continue;
00703
00704 grid1->lodFixed = 2;
00705
00706 R_FixSharedVertexLodError_r( i + 1, grid1);
00707 }
00708 }
00709
00710
00711
00712
00713
00714
00715
00716 int R_StitchPatches( int grid1num, int grid2num ) {
00717 float *v1, *v2;
00718 srfGridMesh_t *grid1, *grid2;
00719 int k, l, m, n, offset1, offset2, row, column;
00720
00721 grid1 = (srfGridMesh_t *) s_worldData.surfaces[grid1num].data;
00722 grid2 = (srfGridMesh_t *) s_worldData.surfaces[grid2num].data;
00723 for (n = 0; n < 2; n++) {
00724
00725 if (n) offset1 = (grid1->height-1) * grid1->width;
00726 else offset1 = 0;
00727 if (R_MergedWidthPoints(grid1, offset1))
00728 continue;
00729 for (k = 0; k < grid1->width-2; k += 2) {
00730
00731 for (m = 0; m < 2; m++) {
00732
00733 if ( grid2->width >= MAX_GRID_SIZE )
00734 break;
00735 if (m) offset2 = (grid2->height-1) * grid2->width;
00736 else offset2 = 0;
00737 for ( l = 0; l < grid2->width-1; l++) {
00738
00739 v1 = grid1->verts[k + offset1].xyz;
00740 v2 = grid2->verts[l + offset2].xyz;
00741 if ( fabs(v1[0] - v2[0]) > .1)
00742 continue;
00743 if ( fabs(v1[1] - v2[1]) > .1)
00744 continue;
00745 if ( fabs(v1[2] - v2[2]) > .1)
00746 continue;
00747
00748 v1 = grid1->verts[k + 2 + offset1].xyz;
00749 v2 = grid2->verts[l + 1 + offset2].xyz;
00750 if ( fabs(v1[0] - v2[0]) > .1)
00751 continue;
00752 if ( fabs(v1[1] - v2[1]) > .1)
00753 continue;
00754 if ( fabs(v1[2] - v2[2]) > .1)
00755 continue;
00756
00757 v1 = grid2->verts[l + offset2].xyz;
00758 v2 = grid2->verts[l + 1 + offset2].xyz;
00759 if ( fabs(v1[0] - v2[0]) < .01 &&
00760 fabs(v1[1] - v2[1]) < .01 &&
00761 fabs(v1[2] - v2[2]) < .01)
00762 continue;
00763
00764
00765
00766 if (m) row = grid2->height-1;
00767 else row = 0;
00768 grid2 = R_GridInsertColumn( grid2, l+1, row,
00769 grid1->verts[k + 1 + offset1].xyz, grid1->widthLodError[k+1]);
00770 grid2->lodStitched = qfalse;
00771 s_worldData.surfaces[grid2num].data = (void *) grid2;
00772 return qtrue;
00773 }
00774 }
00775 for (m = 0; m < 2; m++) {
00776
00777 if (grid2->height >= MAX_GRID_SIZE)
00778 break;
00779 if (m) offset2 = grid2->width-1;
00780 else offset2 = 0;
00781 for ( l = 0; l < grid2->height-1; l++) {
00782
00783 v1 = grid1->verts[k + offset1].xyz;
00784 v2 = grid2->verts[grid2->width * l + offset2].xyz;
00785 if ( fabs(v1[0] - v2[0]) > .1)
00786 continue;
00787 if ( fabs(v1[1] - v2[1]) > .1)
00788 continue;
00789 if ( fabs(v1[2] - v2[2]) > .1)
00790 continue;
00791
00792 v1 = grid1->verts[k + 2 + offset1].xyz;
00793 v2 = grid2->verts[grid2->width * (l + 1) + offset2].xyz;
00794 if ( fabs(v1[0] - v2[0]) > .1)
00795 continue;
00796 if ( fabs(v1[1] - v2[1]) > .1)
00797 continue;
00798 if ( fabs(v1[2] - v2[2]) > .1)
00799 continue;
00800
00801 v1 = grid2->verts[grid2->width * l + offset2].xyz;
00802 v2 = grid2->verts[grid2->width * (l + 1) + offset2].xyz;
00803 if ( fabs(v1[0] - v2[0]) < .01 &&
00804 fabs(v1[1] - v2[1]) < .01 &&
00805 fabs(v1[2] - v2[2]) < .01)
00806 continue;
00807
00808
00809
00810 if (m) column = grid2->width-1;
00811 else column = 0;
00812 grid2 = R_GridInsertRow( grid2, l+1, column,
00813 grid1->verts[k + 1 + offset1].xyz, grid1->widthLodError[k+1]);
00814 grid2->lodStitched = qfalse;
00815 s_worldData.surfaces[grid2num].data = (void *) grid2;
00816 return qtrue;
00817 }
00818 }
00819 }
00820 }
00821 for (n = 0; n < 2; n++) {
00822
00823 if (n) offset1 = grid1->width-1;
00824 else offset1 = 0;
00825 if (R_MergedHeightPoints(grid1, offset1))
00826 continue;
00827 for (k = 0; k < grid1->height-2; k += 2) {
00828 for (m = 0; m < 2; m++) {
00829
00830 if ( grid2->width >= MAX_GRID_SIZE )
00831 break;
00832 if (m) offset2 = (grid2->height-1) * grid2->width;
00833 else offset2 = 0;
00834 for ( l = 0; l < grid2->width-1; l++) {
00835
00836 v1 = grid1->verts[grid1->width * k + offset1].xyz;
00837 v2 = grid2->verts[l + offset2].xyz;
00838 if ( fabs(v1[0] - v2[0]) > .1)
00839 continue;
00840 if ( fabs(v1[1] - v2[1]) > .1)
00841 continue;
00842 if ( fabs(v1[2] - v2[2]) > .1)
00843 continue;
00844
00845 v1 = grid1->verts[grid1->width * (k + 2) + offset1].xyz;
00846 v2 = grid2->verts[l + 1 + offset2].xyz;
00847 if ( fabs(v1[0] - v2[0]) > .1)
00848 continue;
00849 if ( fabs(v1[1] - v2[1]) > .1)
00850 continue;
00851 if ( fabs(v1[2] - v2[2]) > .1)
00852 continue;
00853
00854 v1 = grid2->verts[l + offset2].xyz;
00855 v2 = grid2->verts[(l + 1) + offset2].xyz;
00856 if ( fabs(v1[0] - v2[0]) < .01 &&
00857 fabs(v1[1] - v2[1]) < .01 &&
00858 fabs(v1[2] - v2[2]) < .01)
00859 continue;
00860
00861
00862
00863 if (m) row = grid2->height-1;
00864 else row = 0;
00865 grid2 = R_GridInsertColumn( grid2, l+1, row,
00866 grid1->verts[grid1->width * (k + 1) + offset1].xyz, grid1->heightLodError[k+1]);
00867 grid2->lodStitched = qfalse;
00868 s_worldData.surfaces[grid2num].data = (void *) grid2;
00869 return qtrue;
00870 }
00871 }
00872 for (m = 0; m < 2; m++) {
00873
00874 if (grid2->height >= MAX_GRID_SIZE)
00875 break;
00876 if (m) offset2 = grid2->width-1;
00877 else offset2 = 0;
00878 for ( l = 0; l < grid2->height-1; l++) {
00879
00880 v1 = grid1->verts[grid1->width * k + offset1].xyz;
00881 v2 = grid2->verts[grid2->width * l + offset2].xyz;
00882 if ( fabs(v1[0] - v2[0]) > .1)
00883 continue;
00884 if ( fabs(v1[1] - v2[1]) > .1)
00885 continue;
00886 if ( fabs(v1[2] - v2[2]) > .1)
00887 continue;
00888
00889 v1 = grid1->verts[grid1->width * (k + 2) + offset1].xyz;
00890 v2 = grid2->verts[grid2->width * (l + 1) + offset2].xyz;
00891 if ( fabs(v1[0] - v2[0]) > .1)
00892 continue;
00893 if ( fabs(v1[1] - v2[1]) > .1)
00894 continue;
00895 if ( fabs(v1[2] - v2[2]) > .1)
00896 continue;
00897
00898 v1 = grid2->verts[grid2->width * l + offset2].xyz;
00899 v2 = grid2->verts[grid2->width * (l + 1) + offset2].xyz;
00900 if ( fabs(v1[0] - v2[0]) < .01 &&
00901 fabs(v1[1] - v2[1]) < .01 &&
00902 fabs(v1[2] - v2[2]) < .01)
00903 continue;
00904
00905
00906
00907 if (m) column = grid2->width-1;
00908 else column = 0;
00909 grid2 = R_GridInsertRow( grid2, l+1, column,
00910 grid1->verts[grid1->width * (k + 1) + offset1].xyz, grid1->heightLodError[k+1]);
00911 grid2->lodStitched = qfalse;
00912 s_worldData.surfaces[grid2num].data = (void *) grid2;
00913 return qtrue;
00914 }
00915 }
00916 }
00917 }
00918 for (n = 0; n < 2; n++) {
00919
00920 if (n) offset1 = (grid1->height-1) * grid1->width;
00921 else offset1 = 0;
00922 if (R_MergedWidthPoints(grid1, offset1))
00923 continue;
00924 for (k = grid1->width-1; k > 1; k -= 2) {
00925
00926 for (m = 0; m < 2; m++) {
00927
00928 if ( grid2->width >= MAX_GRID_SIZE )
00929 break;
00930 if (m) offset2 = (grid2->height-1) * grid2->width;
00931 else offset2 = 0;
00932 for ( l = 0; l < grid2->width-1; l++) {
00933
00934 v1 = grid1->verts[k + offset1].xyz;
00935 v2 = grid2->verts[l + offset2].xyz;
00936 if ( fabs(v1[0] - v2[0]) > .1)
00937 continue;
00938 if ( fabs(v1[1] - v2[1]) > .1)
00939 continue;
00940 if ( fabs(v1[2] - v2[2]) > .1)
00941 continue;
00942
00943 v1 = grid1->verts[k - 2 + offset1].xyz;
00944 v2 = grid2->verts[l + 1 + offset2].xyz;
00945 if ( fabs(v1[0] - v2[0]) > .1)
00946 continue;
00947 if ( fabs(v1[1] - v2[1]) > .1)
00948 continue;
00949 if ( fabs(v1[2] - v2[2]) > .1)
00950 continue;
00951
00952 v1 = grid2->verts[l + offset2].xyz;
00953 v2 = grid2->verts[(l + 1) + offset2].xyz;
00954 if ( fabs(v1[0] - v2[0]) < .01 &&
00955 fabs(v1[1] - v2[1]) < .01 &&
00956 fabs(v1[2] - v2[2]) < .01)
00957 continue;
00958
00959
00960
00961 if (m) row = grid2->height-1;
00962 else row = 0;
00963 grid2 = R_GridInsertColumn( grid2, l+1, row,
00964 grid1->verts[k - 1 + offset1].xyz, grid1->widthLodError[k+1]);
00965 grid2->lodStitched = qfalse;
00966 s_worldData.surfaces[grid2num].data = (void *) grid2;
00967 return qtrue;
00968 }
00969 }
00970 for (m = 0; m < 2; m++) {
00971
00972 if (grid2->height >= MAX_GRID_SIZE)
00973 break;
00974 if (m) offset2 = grid2->width-1;
00975 else offset2 = 0;
00976 for ( l = 0; l < grid2->height-1; l++) {
00977
00978 v1 = grid1->verts[k + offset1].xyz;
00979 v2 = grid2->verts[grid2->width * l + offset2].xyz;
00980 if ( fabs(v1[0] - v2[0]) > .1)
00981 continue;
00982 if ( fabs(v1[1] - v2[1]) > .1)
00983 continue;
00984 if ( fabs(v1[2] - v2[2]) > .1)
00985 continue;
00986
00987 v1 = grid1->verts[k - 2 + offset1].xyz;
00988 v2 = grid2->verts[grid2->width * (l + 1) + offset2].xyz;
00989 if ( fabs(v1[0] - v2[0]) > .1)
00990 continue;
00991 if ( fabs(v1[1] - v2[1]) > .1)
00992 continue;
00993 if ( fabs(v1[2] - v2[2]) > .1)
00994 continue;
00995
00996