00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "tr_local.h"
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046 static void LerpDrawVert( drawVert_t *a, drawVert_t *b, drawVert_t *out ) {
00047 out->xyz[0] = 0.5f * (a->xyz[0] + b->xyz[0]);
00048 out->xyz[1] = 0.5f * (a->xyz[1] + b->xyz[1]);
00049 out->xyz[2] = 0.5f * (a->xyz[2] + b->xyz[2]);
00050
00051 out->st[0] = 0.5f * (a->st[0] + b->st[0]);
00052 out->st[1] = 0.5f * (a->st[1] + b->st[1]);
00053
00054 out->lightmap[0] = 0.5f * (a->lightmap[0] + b->lightmap[0]);
00055 out->lightmap[1] = 0.5f * (a->lightmap[1] + b->lightmap[1]);
00056
00057 out->color[0] = (a->color[0] + b->color[0]) >> 1;
00058 out->color[1] = (a->color[1] + b->color[1]) >> 1;
00059 out->color[2] = (a->color[2] + b->color[2]) >> 1;
00060 out->color[3] = (a->color[3] + b->color[3]) >> 1;
00061 }
00062
00063
00064
00065
00066
00067
00068 static void Transpose( int width, int height, drawVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE] ) {
00069 int i, j;
00070 drawVert_t temp;
00071
00072 if ( width > height ) {
00073 for ( i = 0 ; i < height ; i++ ) {
00074 for ( j = i + 1 ; j < width ; j++ ) {
00075 if ( j < height ) {
00076
00077 temp = ctrl[j][i];
00078 ctrl[j][i] = ctrl[i][j];
00079 ctrl[i][j] = temp;
00080 } else {
00081
00082 ctrl[j][i] = ctrl[i][j];
00083 }
00084 }
00085 }
00086 } else {
00087 for ( i = 0 ; i < width ; i++ ) {
00088 for ( j = i + 1 ; j < height ; j++ ) {
00089 if ( j < width ) {
00090
00091 temp = ctrl[i][j];
00092 ctrl[i][j] = ctrl[j][i];
00093 ctrl[j][i] = temp;
00094 } else {
00095
00096 ctrl[i][j] = ctrl[j][i];
00097 }
00098 }
00099 }
00100 }
00101
00102 }
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112 static void MakeMeshNormals( int width, int height, drawVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE] ) {
00113 int i, j, k, dist;
00114 vec3_t normal;
00115 vec3_t sum;
00116 int count;
00117 vec3_t base;
00118 vec3_t delta;
00119 int x, y;
00120 drawVert_t *dv;
00121 vec3_t around[8], temp;
00122 qboolean good[8];
00123 qboolean wrapWidth, wrapHeight;
00124 float len;
00125 static int neighbors[8][2] = {
00126 {0,1}, {1,1}, {1,0}, {1,-1}, {0,-1}, {-1,-1}, {-1,0}, {-1,1}
00127 };
00128
00129 wrapWidth = qfalse;
00130 for ( i = 0 ; i < height ; i++ ) {
00131 VectorSubtract( ctrl[i][0].xyz, ctrl[i][width-1].xyz, delta );
00132 len = VectorLengthSquared( delta );
00133 if ( len > 1.0 ) {
00134 break;
00135 }
00136 }
00137 if ( i == height ) {
00138 wrapWidth = qtrue;
00139 }
00140
00141 wrapHeight = qfalse;
00142 for ( i = 0 ; i < width ; i++ ) {
00143 VectorSubtract( ctrl[0][i].xyz, ctrl[height-1][i].xyz, delta );
00144 len = VectorLengthSquared( delta );
00145 if ( len > 1.0 ) {
00146 break;
00147 }
00148 }
00149 if ( i == width) {
00150 wrapHeight = qtrue;
00151 }
00152
00153
00154 for ( i = 0 ; i < width ; i++ ) {
00155 for ( j = 0 ; j < height ; j++ ) {
00156 count = 0;
00157 dv = &ctrl[j][i];
00158 VectorCopy( dv->xyz, base );
00159 for ( k = 0 ; k < 8 ; k++ ) {
00160 VectorClear( around[k] );
00161 good[k] = qfalse;
00162
00163 for ( dist = 1 ; dist <= 3 ; dist++ ) {
00164 x = i + neighbors[k][0] * dist;
00165 y = j + neighbors[k][1] * dist;
00166 if ( wrapWidth ) {
00167 if ( x < 0 ) {
00168 x = width - 1 + x;
00169 } else if ( x >= width ) {
00170 x = 1 + x - width;
00171 }
00172 }
00173 if ( wrapHeight ) {
00174 if ( y < 0 ) {
00175 y = height - 1 + y;
00176 } else if ( y >= height ) {
00177 y = 1 + y - height;
00178 }
00179 }
00180
00181 if ( x < 0 || x >= width || y < 0 || y >= height ) {
00182 break;
00183 }
00184 VectorSubtract( ctrl[y][x].xyz, base, temp );
00185 if ( VectorNormalize2( temp, temp ) == 0 ) {
00186 continue;
00187 } else {
00188 good[k] = qtrue;
00189 VectorCopy( temp, around[k] );
00190 break;
00191 }
00192 }
00193 }
00194
00195 VectorClear( sum );
00196 for ( k = 0 ; k < 8 ; k++ ) {
00197 if ( !good[k] || !good[(k+1)&7] ) {
00198 continue;
00199 }
00200 CrossProduct( around[(k+1)&7], around[k], normal );
00201 if ( VectorNormalize2( normal, normal ) == 0 ) {
00202 continue;
00203 }
00204 VectorAdd( normal, sum, sum );
00205 count++;
00206 }
00207 if ( count == 0 ) {
00208
00209 count = 1;
00210 }
00211 VectorNormalize2( sum, dv->normal );
00212 }
00213 }
00214 }
00215
00216
00217
00218
00219
00220
00221
00222 static void InvertCtrl( int width, int height, drawVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE] ) {
00223 int i, j;
00224 drawVert_t temp;
00225
00226 for ( i = 0 ; i < height ; i++ ) {
00227 for ( j = 0 ; j < width/2 ; j++ ) {
00228 temp = ctrl[i][j];
00229 ctrl[i][j] = ctrl[i][width-1-j];
00230 ctrl[i][width-1-j] = temp;
00231 }
00232 }
00233 }
00234
00235
00236
00237
00238
00239
00240
00241 static void InvertErrorTable( float errorTable[2][MAX_GRID_SIZE], int width, int height ) {
00242 int i;
00243 float copy[2][MAX_GRID_SIZE];
00244
00245 Com_Memcpy( copy, errorTable, sizeof( copy ) );
00246
00247 for ( i = 0 ; i < width ; i++ ) {
00248 errorTable[1][i] = copy[0][i];
00249 }
00250
00251 for ( i = 0 ; i < height ; i++ ) {
00252 errorTable[0][i] = copy[1][height-1-i];
00253 }
00254
00255 }
00256
00257
00258
00259
00260
00261
00262 static void PutPointsOnCurve( drawVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE],
00263 int width, int height ) {
00264 int i, j;
00265 drawVert_t prev, next;
00266
00267 for ( i = 0 ; i < width ; i++ ) {
00268 for ( j = 1 ; j < height ; j += 2 ) {
00269 LerpDrawVert( &ctrl[j][i], &ctrl[j+1][i], &prev );
00270 LerpDrawVert( &ctrl[j][i], &ctrl[j-1][i], &next );
00271 LerpDrawVert( &prev, &next, &ctrl[j][i] );
00272 }
00273 }
00274
00275
00276 for ( j = 0 ; j < height ; j++ ) {
00277 for ( i = 1 ; i < width ; i += 2 ) {
00278 LerpDrawVert( &ctrl[j][i], &ctrl[j][i+1], &prev );
00279 LerpDrawVert( &ctrl[j][i], &ctrl[j][i-1], &next );
00280 LerpDrawVert( &prev, &next, &ctrl[j][i] );
00281 }
00282 }
00283 }
00284
00285
00286
00287
00288
00289
00290 srfGridMesh_t *R_CreateSurfaceGridMesh(int width, int height,
00291 drawVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE], float errorTable[2][MAX_GRID_SIZE] ) {
00292 int i, j, size;
00293 drawVert_t *vert;
00294 vec3_t tmpVec;
00295 srfGridMesh_t *grid;
00296
00297
00298 size = (width * height - 1) * sizeof( drawVert_t ) + sizeof( *grid );
00299
00300 #ifdef PATCH_STITCHING
00301 grid = ri.Malloc( size );
00302 Com_Memset(grid, 0, size);
00303
00304 grid->widthLodError = ri.Malloc( width * 4 );
00305 Com_Memcpy( grid->widthLodError, errorTable[0], width * 4 );
00306
00307 grid->heightLodError = ri.Malloc( height * 4 );
00308 Com_Memcpy( grid->heightLodError, errorTable[1], height * 4 );
00309 #else
00310 grid = ri.Hunk_Alloc( size );
00311 Com_Memset(grid, 0, size);
00312
00313 grid->widthLodError = ri.Hunk_Alloc( width * 4 );
00314 Com_Memcpy( grid->widthLodError, errorTable[0], width * 4 );
00315
00316 grid->heightLodError = ri.Hunk_Alloc( height * 4 );
00317 Com_Memcpy( grid->heightLodError, errorTable[1], height * 4 );
00318 #endif
00319
00320 grid->width = width;
00321 grid->height = height;
00322 grid->surfaceType = SF_GRID;
00323 ClearBounds( grid->meshBounds[0], grid->meshBounds[1] );
00324 for ( i = 0 ; i < width ; i++ ) {
00325 for ( j = 0 ; j < height ; j++ ) {
00326 vert = &grid->verts[j*width+i];
00327 *vert = ctrl[j][i];
00328 AddPointToBounds( vert->xyz, grid->meshBounds[0], grid->meshBounds[1] );
00329 }
00330 }
00331
00332
00333 VectorAdd( grid->meshBounds[0], grid->meshBounds[1], grid->localOrigin );
00334 VectorScale( grid->localOrigin, 0.5f, grid->localOrigin );
00335 VectorSubtract( grid->meshBounds[0], grid->localOrigin, tmpVec );
00336 grid->meshRadius = VectorLength( tmpVec );
00337
00338 VectorCopy( grid->localOrigin, grid->lodOrigin );
00339 grid->lodRadius = grid->meshRadius;
00340
00341 return grid;
00342 }
00343
00344
00345
00346
00347
00348
00349 void R_FreeSurfaceGridMesh( srfGridMesh_t *grid ) {
00350 ri.Free(grid->widthLodError);
00351 ri.Free(grid->heightLodError);
00352 ri.Free(grid);
00353 }
00354
00355
00356
00357
00358
00359
00360 srfGridMesh_t *R_SubdividePatchToGrid( int width, int height,
00361 drawVert_t points[MAX_PATCH_SIZE*MAX_PATCH_SIZE] ) {
00362 int i, j, k, l;
00363 drawVert_t prev, next, mid;
00364 float len, maxLen;
00365 int dir;
00366 int t;
00367 MAC_STATIC drawVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE];
00368 float errorTable[2][MAX_GRID_SIZE];
00369
00370 for ( i = 0 ; i < width ; i++ ) {
00371 for ( j = 0 ; j < height ; j++ ) {
00372 ctrl[j][i] = points[j*width+i];
00373 }
00374 }
00375
00376 for ( dir = 0 ; dir < 2 ; dir++ ) {
00377
00378 for ( j = 0 ; j < MAX_GRID_SIZE ; j++ ) {
00379 errorTable[dir][j] = 0;
00380 }
00381
00382
00383 for ( j = 0 ; j + 2 < width ; j += 2 ) {
00384
00385
00386
00387
00388
00389 maxLen = 0;
00390 for ( i = 0 ; i < height ; i++ ) {
00391 vec3_t midxyz;
00392 vec3_t midxyz2;
00393 vec3_t dir;
00394 vec3_t projected;
00395 float d;
00396
00397
00398 for ( l = 0 ; l < 3 ; l++ ) {
00399 midxyz[l] = (ctrl[i][j].xyz[l] + ctrl[i][j+1].xyz[l] * 2
00400 + ctrl[i][j+2].xyz[l] ) * 0.25f;
00401 }
00402
00403
00404
00405
00406
00407 VectorSubtract( midxyz, ctrl[i][j].xyz, midxyz );
00408 VectorSubtract( ctrl[i][j+2].xyz, ctrl[i][j].xyz, dir );
00409 VectorNormalize( dir );
00410
00411 d = DotProduct( midxyz, dir );
00412 VectorScale( dir, d, projected );
00413 VectorSubtract( midxyz, projected, midxyz2);
00414 len = VectorLengthSquared( midxyz2 );
00415 if ( len > maxLen ) {
00416 maxLen = len;
00417 }
00418 }
00419
00420 maxLen = sqrt(maxLen);
00421
00422
00423 if ( maxLen < 0.1f ) {
00424 errorTable[dir][j+1] = 999;
00425 continue;
00426 }
00427
00428
00429 if ( width + 2 > MAX_GRID_SIZE ) {
00430 errorTable[dir][j+1] = 1.0f/maxLen;
00431 continue;
00432 }
00433
00434 if ( maxLen <= r_subdivisions->value ) {
00435 errorTable[dir][j+1] = 1.0f/maxLen;
00436 continue;
00437 }
00438
00439 errorTable[dir][j+2] = 1.0f/maxLen;
00440
00441
00442 width += 2;
00443 for ( i = 0 ; i < height ; i++ ) {
00444 LerpDrawVert( &ctrl[i][j], &ctrl[i][j+1], &prev );
00445 LerpDrawVert( &ctrl[i][j+1], &ctrl[i][j+2], &next );
00446 LerpDrawVert( &prev, &next, &mid );
00447
00448 for ( k = width - 1 ; k > j + 3 ; k-- ) {
00449 ctrl[i][k] = ctrl[i][k-2];
00450 }
00451 ctrl[i][j + 1] = prev;
00452 ctrl[i][j + 2] = mid;
00453 ctrl[i][j + 3] = next;
00454 }
00455
00456
00457 j -= 2;
00458
00459 }
00460
00461 Transpose( width, height, ctrl );
00462 t = width;
00463 width = height;
00464 height = t;
00465 }
00466
00467
00468
00469 PutPointsOnCurve( ctrl, width, height );
00470
00471
00472 for ( i = 1 ; i < width-1 ; i++ ) {
00473 if ( errorTable[0][i] != 999 ) {
00474 continue;
00475 }
00476 for ( j = i+1 ; j < width ; j++ ) {
00477 for ( k = 0 ; k < height ; k++ ) {
00478 ctrl[k][j-1] = ctrl[k][j];
00479 }
00480 errorTable[0][j-1] = errorTable[0][j];
00481 }
00482 width--;
00483 }
00484
00485 for ( i = 1 ; i < height-1 ; i++ ) {
00486 if ( errorTable[1][i] != 999 ) {
00487 continue;
00488 }
00489 for ( j = i+1 ; j < height ; j++ ) {
00490 for ( k = 0 ; k < width ; k++ ) {
00491 ctrl[j-1][k] = ctrl[j][k];
00492 }
00493 errorTable[1][j-1] = errorTable[1][j];
00494 }
00495 height--;
00496 }
00497
00498 #if 1
00499
00500
00501
00502 if ( height > width ) {
00503 Transpose( width, height, ctrl );
00504 InvertErrorTable( errorTable, width, height );
00505 t = width;
00506 width = height;
00507 height = t;
00508 InvertCtrl( width, height, ctrl );
00509 }
00510 #endif
00511
00512
00513 MakeMeshNormals( width, height, ctrl );
00514
00515 return R_CreateSurfaceGridMesh( width, height, ctrl, errorTable );
00516 }
00517
00518
00519
00520
00521
00522
00523 srfGridMesh_t *R_GridInsertColumn( srfGridMesh_t *grid, int column, int row, vec3_t point, float loderror ) {
00524 int i, j;
00525 int width, height, oldwidth;
00526 MAC_STATIC drawVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE];
00527 float errorTable[2][MAX_GRID_SIZE];
00528 float lodRadius;
00529 vec3_t lodOrigin;
00530
00531 oldwidth = 0;
00532 width = grid->width + 1;
00533 if (width > MAX_GRID_SIZE)
00534 return NULL;
00535 height = grid->height;
00536 for (i = 0; i < width; i++) {
00537 if (i == column) {
00538
00539 for (j = 0; j < grid->height; j++) {
00540 LerpDrawVert( &grid->verts[j * grid->width + i-1], &grid->verts[j * grid->width + i], &ctrl[j][i] );
00541 if (j == row)
00542 VectorCopy(point, ctrl[j][i].xyz);
00543 }
00544 errorTable[0][i] = loderror;
00545 continue;
00546 }
00547 errorTable[0][i] = grid->widthLodError[oldwidth];
00548 for (j = 0; j < grid->height; j++) {
00549 ctrl[j][i] = grid->verts[j * grid->width + oldwidth];
00550 }
00551 oldwidth++;
00552 }
00553 for (j = 0; j < grid->height; j++) {
00554 errorTable[1][j] = grid->heightLodError[j];
00555 }
00556
00557
00558
00559 MakeMeshNormals( width, height, ctrl );
00560
00561 VectorCopy(grid->lodOrigin, lodOrigin);
00562 lodRadius = grid->lodRadius;
00563
00564 R_FreeSurfaceGridMesh(grid);
00565
00566 grid = R_CreateSurfaceGridMesh( width, height, ctrl, errorTable );
00567 grid->lodRadius = lodRadius;
00568 VectorCopy(lodOrigin, grid->lodOrigin);
00569 return grid;
00570 }
00571
00572
00573
00574
00575
00576
00577 srfGridMesh_t *R_GridInsertRow( srfGridMesh_t *grid, int row, int column, vec3_t point, float loderror ) {
00578 int i, j;
00579 int width, height, oldheight;
00580 MAC_STATIC drawVert_t ctrl[MAX_GRID_SIZE][MAX_GRID_SIZE];
00581 float errorTable[2][MAX_GRID_SIZE];
00582 float lodRadius;
00583 vec3_t lodOrigin;
00584
00585 oldheight = 0;
00586 width = grid->width;
00587 height = grid->height + 1;
00588 if (height > MAX_GRID_SIZE)
00589 return NULL;
00590 for (i = 0; i < height; i++) {
00591 if (i == row) {
00592
00593 for (j = 0; j < grid->width; j++) {
00594 LerpDrawVert( &grid->verts[(i-1) * grid->width + j], &grid->verts[i * grid->width + j], &ctrl[i][j] );
00595 if (j == column)
00596 VectorCopy(point, ctrl[i][j].xyz);
00597 }
00598 errorTable[1][i] = loderror;
00599 continue;
00600 }
00601 errorTable[1][i] = grid->heightLodError[oldheight];
00602 for (j = 0; j < grid->width; j++) {
00603 ctrl[i][j] = grid->verts[oldheight * grid->width + j];
00604 }
00605 oldheight++;
00606 }
00607 for (j = 0; j < grid->width; j++) {
00608 errorTable[0][j] = grid->widthLodError[j];
00609 }
00610
00611
00612
00613 MakeMeshNormals( width, height, ctrl );
00614
00615 VectorCopy(grid->lodOrigin, lodOrigin);
00616 lodRadius = grid->lodRadius;
00617
00618 R_FreeSurfaceGridMesh(grid);
00619
00620 grid = R_CreateSurfaceGridMesh( width, height, ctrl, errorTable );
00621 grid->lodRadius = lodRadius;
00622 VectorCopy(lodOrigin, grid->lodOrigin);
00623 return grid;
00624 }