terrain.c (31376B)
1 /* 2 =========================================================================== 3 Copyright (C) 1999-2005 Id Software, Inc. 4 5 This file is part of Quake III Arena source code. 6 7 Quake III Arena source code is free software; you can redistribute it 8 and/or modify it under the terms of the GNU General Public License as 9 published by the Free Software Foundation; either version 2 of the License, 10 or (at your option) any later version. 11 12 Quake III Arena source code is distributed in the hope that it will be 13 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with Foobar; if not, write to the Free Software 19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 20 =========================================================================== 21 */ 22 #include "qbsp.h" 23 #include <assert.h> 24 25 #define SURF_WIDTH 2048 26 #define SURF_HEIGHT 2048 27 28 #define GROW_VERTS 512 29 #define GROW_INDICES 512 30 #define GROW_SURFACES 128 31 32 #define VectorSet(v, x, y, z) v[0] = x;v[1] = y;v[2] = z; 33 34 void QuakeTextureVecs( plane_t *plane, vec_t shift[2], vec_t rotate, vec_t scale[2], vec_t mappingVecs[2][4] ); 35 36 typedef struct { 37 shaderInfo_t *shader; 38 int x, y; 39 40 int maxVerts; 41 int numVerts; 42 drawVert_t *verts; 43 44 int maxIndexes; 45 int numIndexes; 46 int *indexes; 47 } terrainSurf_t; 48 49 static terrainSurf_t *surfaces = NULL; 50 static terrainSurf_t *lastSurface = NULL; 51 static int numsurfaces = 0; 52 static int maxsurfaces = 0; 53 54 /* 55 ================ 56 ShaderForLayer 57 ================ 58 */ 59 shaderInfo_t *ShaderForLayer( int minlayer, int maxlayer, const char *shadername ) { 60 char shader[ MAX_QPATH ]; 61 62 if ( minlayer == maxlayer ) { 63 sprintf( shader, "textures/%s_%d", shadername, maxlayer ); 64 } else { 65 sprintf( shader, "textures/%s_%dto%d", shadername, minlayer, maxlayer ); 66 } 67 68 return ShaderInfoForShader( shader ); 69 } 70 71 /* 72 ================ 73 CompareVert 74 ================ 75 */ 76 qboolean CompareVert( drawVert_t *v1, drawVert_t *v2, qboolean checkst ) { 77 int i; 78 79 for( i = 0; i < 3; i++ ) { 80 if ( floor( v1->xyz[ i ] + 0.1 ) != floor( v2->xyz[ i ] + 0.1 ) ) { 81 return qfalse; 82 } 83 if ( checkst && ( ( v1->st[ 0 ] != v2->st[ 0 ] ) || ( v1->st[ 1 ] != v2->st[ 1 ] ) ) ) { 84 return qfalse; 85 } 86 } 87 88 return qtrue; 89 } 90 91 /* 92 ================ 93 LoadAlphaMap 94 ================ 95 */ 96 byte *LoadAlphaMap( int *num_layers, int *alphawidth, int *alphaheight ) { 97 int *alphamap32; 98 byte *alphamap; 99 const char *alphamapname; 100 char ext[ 128 ]; 101 int width; 102 int height; 103 int layers; 104 int size; 105 int i; 106 107 assert( alphawidth ); 108 assert( alphaheight ); 109 assert( num_layers ); 110 111 layers = atoi( ValueForKey( mapent, "layers" ) ); 112 if ( layers < 1 ) { 113 Error ("SetTerrainTextures: invalid value for 'layers' (%d)", layers ); 114 } 115 116 alphamapname = ValueForKey( mapent, "alphamap" ); 117 if ( !alphamapname[ 0 ] ) { 118 Error ("LoadAlphaMap: No alphamap specified on terrain" ); 119 } 120 121 ExtractFileExtension( alphamapname, ext); 122 if ( !Q_stricmp( ext, "tga" ) ) { 123 Load32BitImage( ExpandGamePath( alphamapname ), &alphamap32, &width, &height ); 124 125 size = width * height; 126 alphamap = malloc( size ); 127 for( i = 0; i < size; i++ ) { 128 alphamap[ i ] = ( ( alphamap32[ i ] & 0xff ) * layers ) / 256; 129 if ( alphamap[ i ] >= layers ) { 130 alphamap[ i ] = layers - 1; 131 } 132 } 133 } else { 134 Load256Image( ExpandGamePath( alphamapname ), &alphamap, NULL, &width, &height ); 135 size = width * height; 136 for( i = 0; i < size; i++ ) { 137 if ( alphamap[ i ] >= layers ) { 138 alphamap[ i ] = layers - 1; 139 } 140 } 141 } 142 143 if ( ( width < 2 ) || ( height < 2 ) ) { 144 Error ("LoadAlphaMap: alphamap width/height must be at least 2x2." ); 145 } 146 147 *num_layers = layers; 148 *alphawidth = width; 149 *alphaheight = height; 150 151 return alphamap; 152 } 153 154 /* 155 ================ 156 CalcTerrainSize 157 ================ 158 */ 159 void CalcTerrainSize( vec3_t mins, vec3_t maxs, vec3_t size ) { 160 bspbrush_t *brush; 161 int i; 162 const char *key; 163 164 // calculate the size of the terrain 165 ClearBounds( mins, maxs ); 166 for( brush = mapent->brushes; brush != NULL; brush = brush->next ) { 167 AddPointToBounds( brush->mins, mins, maxs ); 168 AddPointToBounds( brush->maxs, mins, maxs ); 169 } 170 171 key = ValueForKey( mapent, "min" ); 172 if ( key[ 0 ] ) { 173 GetVectorForKey( mapent, "min", mins ); 174 } 175 176 key = ValueForKey( mapent, "max" ); 177 if ( key[ 0 ] ) { 178 GetVectorForKey( mapent, "max", maxs ); 179 } 180 181 for( i = 0; i < 3; i++ ) { 182 mins[ i ] = floor( mins[ i ] + 0.1 ); 183 maxs[ i ] = floor( maxs[ i ] + 0.1 ); 184 } 185 186 VectorSubtract( maxs, mins, size ); 187 188 if ( ( size[ 0 ] <= 0 ) || ( size[ 1 ] <= 0 ) ) { 189 Error ("CalcTerrainSize: Invalid terrain size: %fx%f", size[ 0 ], size[ 1 ] ); 190 } 191 } 192 193 /* 194 ================== 195 IsTriangleDegenerate 196 197 Returns qtrue if all three points are collinear or backwards 198 =================== 199 */ 200 #define COLINEAR_AREA 10 201 static qboolean IsTriangleDegenerate( drawVert_t *points, int a, int b, int c ) { 202 vec3_t v1, v2, v3; 203 float d; 204 205 VectorSubtract( points[b].xyz, points[a].xyz, v1 ); 206 VectorSubtract( points[c].xyz, points[a].xyz, v2 ); 207 CrossProduct( v1, v2, v3 ); 208 d = VectorLength( v3 ); 209 210 // assume all very small or backwards triangles will cause problems 211 if ( d < COLINEAR_AREA ) { 212 return qtrue; 213 } 214 215 return qfalse; 216 } 217 218 /* 219 =============== 220 SideAsTriFan 221 222 The surface can't be represented as a single tristrip without 223 leaving a degenerate triangle (and therefore a crack), so add 224 a point in the middle and create (points-1) triangles in fan order 225 =============== 226 */ 227 static void SideAsTriFan( terrainSurf_t *surf, int *index, int num ) { 228 int i; 229 int colorSum[4]; 230 drawVert_t *mid, *v; 231 232 // make sure we have enough space for a new vert 233 if ( surf->numVerts >= surf->maxVerts ) { 234 surf->maxVerts += GROW_VERTS; 235 surf->verts = realloc( surf->verts, surf->maxVerts * sizeof( *surf->verts ) ); 236 } 237 238 // create a new point in the center of the face 239 mid = &surf->verts[ surf->numVerts ]; 240 surf->numVerts++; 241 242 colorSum[0] = colorSum[1] = colorSum[2] = colorSum[3] = 0; 243 244 for (i = 0 ; i < num; i++ ) { 245 v = &surf->verts[ index[ i ] ]; 246 VectorAdd( mid->xyz, v->xyz, mid->xyz ); 247 mid->st[0] += v->st[0]; 248 mid->st[1] += v->st[1]; 249 mid->lightmap[0] += v->lightmap[0]; 250 mid->lightmap[1] += v->lightmap[1]; 251 252 colorSum[0] += v->color[0]; 253 colorSum[1] += v->color[1]; 254 colorSum[2] += v->color[2]; 255 colorSum[3] += v->color[3]; 256 } 257 258 mid->xyz[0] /= num; 259 mid->xyz[1] /= num; 260 mid->xyz[2] /= num; 261 262 mid->st[0] /= num; 263 mid->st[1] /= num; 264 265 mid->lightmap[0] /= num; 266 mid->lightmap[1] /= num; 267 268 mid->color[0] = colorSum[0] / num; 269 mid->color[1] = colorSum[1] / num; 270 mid->color[2] = colorSum[2] / num; 271 mid->color[3] = colorSum[3] / num; 272 273 // fill in indices in trifan order 274 if ( surf->numIndexes + num * 3 > surf->maxIndexes ) { 275 surf->maxIndexes = surf->numIndexes + num * 3; 276 surf->indexes = realloc( surf->indexes, surf->maxIndexes * sizeof( *surf->indexes ) ); 277 } 278 279 280 for ( i = 0 ; i < num; i++ ) { 281 surf->indexes[ surf->numIndexes++ ] = surf->numVerts - 1; 282 surf->indexes[ surf->numIndexes++ ] = index[ i ]; 283 surf->indexes[ surf->numIndexes++ ] = index[ (i+1) % ( surf->numVerts - 1 ) ]; 284 } 285 } 286 /* 287 ================ 288 SideAsTristrip 289 290 Try to create indices that make (points-2) triangles in tristrip order 291 ================ 292 */ 293 #define MAX_INDICES 1024 294 static void SideAsTristrip( terrainSurf_t *surf, int *index, int num ) { 295 int i; 296 int rotate; 297 int numIndices; 298 int ni; 299 int a, b, c; 300 int indices[ MAX_INDICES ]; 301 302 // determine the triangle strip order 303 numIndices = ( num - 2 ) * 3; 304 if ( numIndices > MAX_INDICES ) { 305 Error( "MAX_INDICES exceeded for surface" ); 306 } 307 308 // try all possible orderings of the points looking 309 // for a strip order that isn't degenerate 310 for ( rotate = 0 ; rotate < num; rotate++ ) { 311 for ( ni = 0, i = 0 ; i < num - 2 - i ; i++ ) { 312 a = index[ ( num - 1 - i + rotate ) % num ]; 313 b = index[ ( i + rotate ) % num ]; 314 c = index[ ( num - 2 - i + rotate ) % num ]; 315 316 if ( IsTriangleDegenerate( surf->verts, a, b, c ) ) { 317 break; 318 } 319 indices[ni++] = a; 320 indices[ni++] = b; 321 indices[ni++] = c; 322 323 if ( i + 1 != num - 1 - i ) { 324 a = index[ ( num - 2 - i + rotate ) % num ]; 325 b = index[ ( i + rotate ) % num ]; 326 c = index[ ( i + 1 + rotate ) % num ]; 327 328 if ( IsTriangleDegenerate( surf->verts, a, b, c ) ) { 329 break; 330 } 331 indices[ni++] = a; 332 indices[ni++] = b; 333 indices[ni++] = c; 334 } 335 } 336 if ( ni == numIndices ) { 337 break; // got it done without degenerate triangles 338 } 339 } 340 341 // if any triangle in the strip is degenerate, 342 // render from a centered fan point instead 343 if ( ni < numIndices ) { 344 SideAsTriFan( surf, index, num ); 345 return; 346 } 347 348 // a normal tristrip 349 if ( surf->numIndexes + ni > surf->maxIndexes ) { 350 surf->maxIndexes = surf->numIndexes + ni; 351 surf->indexes = realloc( surf->indexes, surf->maxIndexes * sizeof( *surf->indexes ) ); 352 } 353 354 memcpy( surf->indexes + surf->numIndexes, indices, ni * sizeof( *surf->indexes ) ); 355 surf->numIndexes += ni; 356 } 357 358 /* 359 ================ 360 CreateTerrainSurface 361 ================ 362 */ 363 void CreateTerrainSurface( terrainSurf_t *surf, shaderInfo_t *shader ) { 364 int i, j, k; 365 drawVert_t *out; 366 drawVert_t *in; 367 mapDrawSurface_t *newsurf; 368 369 newsurf = AllocDrawSurf(); 370 371 newsurf->miscModel = qtrue; 372 newsurf->shaderInfo = shader; 373 newsurf->lightmapNum = -1; 374 newsurf->fogNum = -1; 375 newsurf->numIndexes = surf->numIndexes; 376 newsurf->numVerts = surf->numVerts; 377 378 // copy the indices 379 newsurf->indexes = malloc( surf->numIndexes * sizeof( *newsurf->indexes ) ); 380 memcpy( newsurf->indexes, surf->indexes, surf->numIndexes * sizeof( *newsurf->indexes ) ); 381 382 // allocate the vertices 383 newsurf->verts = malloc( surf->numVerts * sizeof( *newsurf->verts ) ); 384 memset( newsurf->verts, 0, surf->numVerts * sizeof( *newsurf->verts ) ); 385 386 // calculate the surface verts 387 out = newsurf->verts; 388 for( i = 0; i < newsurf->numVerts; i++, out++ ) { 389 VectorCopy( surf->verts[ i ].xyz, out->xyz ); 390 391 // set the texture coordinates 392 out->st[ 0 ] = surf->verts[ i ].st[ 0 ]; 393 out->st[ 1 ] = surf->verts[ i ].st[ 1 ]; 394 395 // the colors will be set by the lighting pass 396 out->color[0] = 255; 397 out->color[1] = 255; 398 out->color[2] = 255; 399 out->color[3] = surf->verts[ i ].color[ 3 ]; 400 401 // calculate the vertex normal 402 VectorClear( out->normal ); 403 for( j = 0; j < numsurfaces; j++ ) { 404 in = surfaces[ j ].verts; 405 for( k = 0; k < surfaces[ j ].numVerts; k++, in++ ) { 406 if ( CompareVert( out, in, qfalse ) ) { 407 VectorAdd( out->normal, in->normal, out->normal ); 408 } 409 } 410 } 411 412 VectorNormalize( out->normal, out->normal ); 413 } 414 } 415 416 /* 417 ================ 418 EmitTerrainVerts 419 ================ 420 */ 421 void EmitTerrainVerts( side_t *side, terrainSurf_t *surf, int maxlayer, int alpha[ MAX_POINTS_ON_WINDING ], qboolean projecttexture ) { 422 int i; 423 int j; 424 drawVert_t *vert; 425 int *indices; 426 int numindices; 427 int maxindices; 428 int xyplane; 429 vec3_t xynorm = { 0, 0, 1 }; 430 vec_t shift[ 2 ] = { 0, 0 }; 431 vec_t scale[ 2 ] = { 0.5, 0.5 }; 432 float vecs[ 2 ][ 4 ]; 433 static int numtimes = 0; 434 435 numtimes++; 436 437 if ( !surf->verts ) { 438 surf->numVerts = 0; 439 surf->maxVerts = GROW_VERTS; 440 surf->verts = malloc( surf->maxVerts * sizeof( *surf->verts ) ); 441 442 surf->numIndexes = 0; 443 surf->maxIndexes = GROW_INDICES; 444 surf->indexes = malloc( surf->maxIndexes * sizeof( *surf->indexes ) ); 445 } 446 447 // calculate the texture coordinate vectors 448 xyplane = FindFloatPlane( xynorm, 0 ); 449 QuakeTextureVecs( &mapplanes[ xyplane ], shift, 0, scale, vecs ); 450 451 // emit the vertexes 452 numindices = 0; 453 maxindices = surf->maxIndexes; 454 indices = malloc ( maxindices * sizeof( *indices ) ); 455 456 for ( i = 0; i < side->winding->numpoints; i++ ) { 457 vert = &surf->verts[ surf->numVerts ]; 458 459 // set the final alpha value--0 for texture 1, 255 for texture 2 460 if ( alpha[ i ] < maxlayer ) { 461 vert->color[3] = 0; 462 } else { 463 vert->color[3] = 255; 464 } 465 466 vert->xyz[ 0 ] = floor( side->winding->p[ i ][ 0 ] + 0.1f ); 467 vert->xyz[ 1 ] = floor( side->winding->p[ i ][ 1 ] + 0.1f ); 468 vert->xyz[ 2 ] = floor( side->winding->p[ i ][ 2 ] + 0.1f ); 469 470 // set the texture coordinates 471 if ( projecttexture ) { 472 vert->st[0] = ( vecs[0][3] + DotProduct( vecs[ 0 ], vert->xyz ) ) / surf->shader->width; 473 vert->st[1] = ( vecs[1][3] + DotProduct( vecs[ 1 ], vert->xyz ) ) / surf->shader->height; 474 } else { 475 vert->st[0] = ( side->vecs[0][3] + DotProduct( side->vecs[ 0 ], vert->xyz ) ) / surf->shader->width; 476 vert->st[1] = ( side->vecs[1][3] + DotProduct( side->vecs[ 1 ], vert->xyz ) ) / surf->shader->height; 477 } 478 479 VectorCopy( mapplanes[ side->planenum ].normal, vert->normal ); 480 481 for( j = 0; j < surf->numVerts; j++ ) { 482 if ( CompareVert( vert, &surf->verts[ j ], qtrue ) ) { 483 break; 484 } 485 } 486 487 if ( numindices >= maxindices ) { 488 maxindices += GROW_INDICES; 489 indices = realloc( indices, maxindices * sizeof( *indices ) ); 490 } 491 492 if ( j != surf->numVerts ) { 493 indices[ numindices++ ] = j; 494 } else { 495 indices[ numindices++ ] = surf->numVerts; 496 surf->numVerts++; 497 if ( surf->numVerts >= surf->maxVerts ) { 498 surf->maxVerts += GROW_VERTS; 499 surf->verts = realloc( surf->verts, surf->maxVerts * sizeof( *surf->verts ) ); 500 } 501 } 502 } 503 504 SideAsTristrip( surf, indices, numindices ); 505 506 free( indices ); 507 } 508 509 /* 510 ================ 511 SurfaceForShader 512 ================ 513 */ 514 terrainSurf_t *SurfaceForShader( shaderInfo_t *shader, int x, int y ) { 515 int i; 516 517 if ( lastSurface && ( lastSurface->shader == shader ) && ( lastSurface->x == x ) && ( lastSurface->y == y ) ) { 518 return lastSurface; 519 } 520 521 lastSurface = surfaces; 522 for( i = 0; i < numsurfaces; i++, lastSurface++ ) { 523 if ( ( lastSurface->shader == shader ) && ( lastSurface->x == x ) && ( lastSurface->y == y ) ) { 524 return lastSurface; 525 } 526 } 527 528 if ( numsurfaces >= maxsurfaces ) { 529 maxsurfaces += GROW_SURFACES; 530 surfaces = realloc( surfaces, maxsurfaces * sizeof( *surfaces ) ); 531 memset( surfaces + numsurfaces + 1, 0, ( maxsurfaces - numsurfaces - 1 ) * sizeof( *surfaces ) ); 532 } 533 534 lastSurface= &surfaces[ numsurfaces++ ]; 535 lastSurface->shader = shader; 536 lastSurface->x = x; 537 lastSurface->y = y; 538 539 return lastSurface; 540 } 541 542 /* 543 ================ 544 SetTerrainTextures 545 ================ 546 */ 547 void SetTerrainTextures( void ) { 548 int i; 549 int x, y; 550 int layer; 551 int minlayer, maxlayer; 552 float s, t; 553 float min_s, min_t; 554 int alpha[ MAX_POINTS_ON_WINDING ]; 555 shaderInfo_t *si, *terrainShader; 556 bspbrush_t *brush; 557 side_t *side; 558 const char *shadername; 559 vec3_t mins, maxs; 560 vec3_t size; 561 int surfwidth, surfheight, surfsize; 562 terrainSurf_t *surf; 563 byte *alphamap; 564 int alphawidth, alphaheight; 565 int num_layers; 566 extern qboolean onlyents; 567 568 if ( onlyents ) { 569 return; 570 } 571 572 shadername = ValueForKey( mapent, "shader" ); 573 if ( !shadername[ 0 ] ) { 574 Error ("SetTerrainTextures: shader not specified" ); 575 } 576 577 alphamap = LoadAlphaMap( &num_layers, &alphawidth, &alphaheight ); 578 579 mapent->firstDrawSurf = numMapDrawSurfs; 580 581 // calculate the size of the terrain 582 CalcTerrainSize( mins, maxs, size ); 583 584 surfwidth = ( size[ 0 ] + SURF_WIDTH - 1 ) / SURF_WIDTH; 585 surfheight = ( size[ 1 ] + SURF_HEIGHT - 1 ) / SURF_HEIGHT; 586 surfsize = surfwidth * surfheight; 587 588 lastSurface = NULL; 589 numsurfaces = 0; 590 maxsurfaces = 0; 591 for( i = num_layers; i > 0; i-- ) { 592 maxsurfaces += i * surfsize; 593 } 594 surfaces = malloc( maxsurfaces * sizeof( *surfaces ) ); 595 memset( surfaces, 0, maxsurfaces * sizeof( *surfaces ) ); 596 597 terrainShader = ShaderInfoForShader( "textures/common/terrain" ); 598 599 for( brush = mapent->brushes; brush != NULL; brush = brush->next ) { 600 // only create surfaces for sides marked as terrain 601 for( side = brush->sides; side < &brush->sides[ brush->numsides ]; side++ ) { 602 if ( !side->shaderInfo ) { 603 continue; 604 } 605 606 if ( ( ( side->surfaceFlags | side->shaderInfo->surfaceFlags ) & SURF_NODRAW ) && !strstr( side->shaderInfo->shader, "terrain" ) ) { 607 continue; 608 } 609 610 minlayer = num_layers; 611 maxlayer = 0; 612 613 // project each point of the winding onto the alphamap to determine which 614 // textures to blend 615 min_s = 1.0; 616 min_t = 1.0; 617 for( i = 0; i < side->winding->numpoints; i++ ) { 618 s = floor( side->winding->p[ i ][ 0 ] + 0.1f - mins[ 0 ] ) / size[ 0 ]; 619 t = floor( side->winding->p[ i ][ 1 ] + 0.1f - mins[ 0 ] ) / size[ 1 ]; 620 621 if ( s < 0 ) { 622 s = 0; 623 } 624 625 if ( t < 0 ) { 626 t = 0; 627 } 628 629 if ( s >= 1.0 ) { 630 s = 1.0; 631 } 632 633 if ( t >= 1.0 ) { 634 t = 1.0; 635 } 636 637 if ( s < min_s ) { 638 min_s = s; 639 } 640 641 if ( t < min_t ) { 642 min_t = t; 643 } 644 645 x = ( alphawidth - 1 ) * s; 646 y = ( alphaheight - 1 ) * t; 647 648 layer = alphamap[ x + y * alphawidth ]; 649 if ( layer < minlayer ) { 650 minlayer = layer; 651 } 652 653 if ( layer > maxlayer ) { 654 maxlayer = layer; 655 } 656 657 alpha[ i ] = layer; 658 } 659 660 x = min_s * surfwidth; 661 if ( x >= surfwidth ) { 662 x = surfwidth - 1; 663 } 664 665 y = min_t * surfheight; 666 if ( y >= surfheight ) { 667 y = surfheight - 1; 668 } 669 670 if ( strstr( side->shaderInfo->shader, "terrain" ) ) { 671 si = ShaderForLayer( minlayer, maxlayer, shadername ); 672 if ( showseams ) { 673 for( i = 0; i < side->winding->numpoints; i++ ) { 674 if ( ( alpha[ i ] != minlayer ) && ( alpha[ i ] != maxlayer ) ) { 675 si = ShaderInfoForShader( "textures/common/white" ); 676 break; 677 } 678 } 679 } 680 surf = SurfaceForShader( si, x, y ); 681 EmitTerrainVerts( side, surf, maxlayer, alpha, qtrue ); 682 } else { 683 si = side->shaderInfo; 684 side->shaderInfo = terrainShader; 685 surf = SurfaceForShader( si, x, y ); 686 EmitTerrainVerts( side, surf, maxlayer, alpha, qfalse ); 687 } 688 } 689 } 690 691 // create the final surfaces 692 for( surf = surfaces, i = 0; i < numsurfaces; i++, surf++ ) { 693 if ( surf->numVerts ) { 694 CreateTerrainSurface( surf, surf->shader ); 695 } 696 } 697 698 // 699 // clean up any allocated memory 700 // 701 for( surf = surfaces, i = 0; i < numsurfaces; i++, surf++ ) { 702 if ( surf->verts ) { 703 free( surf->verts ); 704 free( surf->indexes ); 705 } 706 } 707 free( alphamap ); 708 free( surfaces ); 709 710 surfaces = NULL; 711 lastSurface = NULL; 712 numsurfaces = 0; 713 maxsurfaces = 0; 714 } 715 716 /***************************************************************************** 717 718 New terrain code 719 720 ******************************************************************************/ 721 722 typedef struct terrainFace_s { 723 shaderInfo_t *shaderInfo; 724 //texdef_t texdef; 725 726 float vecs[ 2 ][ 4 ]; // texture coordinate mapping 727 } terrainFace_t; 728 729 typedef struct terrainVert_s { 730 vec3_t xyz; 731 terrainFace_t tri; 732 } terrainVert_t; 733 734 typedef struct terrainMesh_s { 735 float scale_x; 736 float scale_y; 737 vec3_t origin; 738 739 int width, height; 740 terrainVert_t *map; 741 } terrainMesh_t; 742 743 terrainVert_t *Terrain_GetVert( terrainMesh_t *pm, int x, int y ) { 744 return &pm->map[ x + y * pm->width ]; 745 } 746 747 void Terrain_GetTriangles( terrainMesh_t *pm, int x, int y, terrainVert_t **verts ) { 748 if ( ( x + y ) & 1 ) { 749 // first tri 750 verts[ 0 ] = Terrain_GetVert( pm, x, y ); 751 verts[ 1 ] = Terrain_GetVert( pm, x, y + 1 ); 752 verts[ 2 ] = Terrain_GetVert( pm, x + 1, y + 1 ); 753 754 // second tri 755 verts[ 3 ] = verts[ 2 ]; 756 verts[ 4 ] = Terrain_GetVert( pm, x + 1, y ); 757 verts[ 5 ] = verts[ 0 ]; 758 } else { 759 // first tri 760 verts[ 0 ] = Terrain_GetVert( pm, x, y ); 761 verts[ 1 ] = Terrain_GetVert( pm, x, y + 1 ); 762 verts[ 2 ] = Terrain_GetVert( pm, x + 1, y ); 763 764 // second tri 765 verts[ 3 ] = verts[ 2 ]; 766 verts[ 4 ] = verts[ 1 ]; 767 verts[ 5 ] = Terrain_GetVert( pm, x + 1, y + 1 ); 768 } 769 } 770 771 /* 772 ================ 773 EmitTerrainVerts2 774 ================ 775 */ 776 void EmitTerrainVerts2( terrainSurf_t *surf, terrainVert_t **verts, int alpha[ 3 ] ) { 777 int i; 778 int j; 779 drawVert_t *vert; 780 int *indices; 781 int numindices; 782 int maxindices; 783 int xyplane; 784 vec3_t xynorm = { 0, 0, 1 }; 785 vec_t shift[ 2 ] = { 0, 0 }; 786 vec_t scale[ 2 ] = { 0.5, 0.5 }; 787 float vecs[ 2 ][ 4 ]; 788 vec4_t plane; 789 790 if ( !surf->verts ) { 791 surf->numVerts = 0; 792 surf->maxVerts = GROW_VERTS; 793 surf->verts = malloc( surf->maxVerts * sizeof( *surf->verts ) ); 794 795 surf->numIndexes = 0; 796 surf->maxIndexes = GROW_INDICES; 797 surf->indexes = malloc( surf->maxIndexes * sizeof( *surf->indexes ) ); 798 } 799 800 // calculate the texture coordinate vectors 801 xyplane = FindFloatPlane( xynorm, 0 ); 802 QuakeTextureVecs( &mapplanes[ xyplane ], shift, 0, scale, vecs ); 803 804 // emit the vertexes 805 numindices = 0; 806 maxindices = surf->maxIndexes; 807 assert( maxindices >= 0 ); 808 indices = malloc ( maxindices * sizeof( *indices ) ); 809 810 PlaneFromPoints( plane, verts[ 0 ]->xyz, verts[ 1 ]->xyz, verts[ 2 ]->xyz ); 811 812 for ( i = 0; i < 3; i++ ) { 813 vert = &surf->verts[ surf->numVerts ]; 814 815 if ( alpha[ i ] ) { 816 vert->color[3] = 255; 817 } else { 818 vert->color[3] = 0; 819 } 820 821 vert->xyz[ 0 ] = floor( verts[ i ]->xyz[ 0 ] + 0.1f ); 822 vert->xyz[ 1 ] = floor( verts[ i ]->xyz[ 1 ] + 0.1f ); 823 vert->xyz[ 2 ] = floor( verts[ i ]->xyz[ 2 ] + 0.1f ); 824 825 // set the texture coordinates 826 vert->st[0] = ( vecs[0][3] + DotProduct( vecs[ 0 ], vert->xyz ) ) / surf->shader->width; 827 vert->st[1] = ( vecs[1][3] + DotProduct( vecs[ 1 ], vert->xyz ) ) / surf->shader->height; 828 829 VectorCopy( plane, vert->normal ); 830 831 for( j = 0; j < surf->numVerts; j++ ) { 832 if ( CompareVert( vert, &surf->verts[ j ], qtrue ) ) { 833 break; 834 } 835 } 836 837 if ( numindices >= maxindices ) { 838 maxindices += GROW_INDICES; 839 indices = realloc( indices, maxindices * sizeof( *indices ) ); 840 } 841 842 if ( j != surf->numVerts ) { 843 indices[ numindices++ ] = j; 844 } else { 845 indices[ numindices++ ] = surf->numVerts; 846 surf->numVerts++; 847 if ( surf->numVerts >= surf->maxVerts ) { 848 surf->maxVerts += GROW_VERTS; 849 surf->verts = realloc( surf->verts, surf->maxVerts * sizeof( *surf->verts ) ); 850 } 851 } 852 } 853 854 SideAsTristrip( surf, indices, numindices ); 855 856 free( indices ); 857 } 858 859 int MapPlaneFromPoints( vec3_t p0, vec3_t p1, vec3_t p2 ); 860 void QuakeTextureVecs( plane_t *plane, vec_t shift[2], vec_t rotate, vec_t scale[2], vec_t mappingVecs[2][4] ); 861 qboolean RemoveDuplicateBrushPlanes( bspbrush_t *b ); 862 void SetBrushContents( bspbrush_t *b ); 863 864 void AddBrushSide( vec3_t v1, vec3_t v2, vec3_t v3, shaderInfo_t *terrainShader ) { 865 side_t *side; 866 int planenum; 867 868 side = &buildBrush->sides[ buildBrush->numsides ]; 869 memset( side, 0, sizeof( *side ) ); 870 buildBrush->numsides++; 871 872 side->shaderInfo = terrainShader; 873 874 // find the plane number 875 planenum = MapPlaneFromPoints( v1, v2, v3 ); 876 side->planenum = planenum; 877 } 878 879 void MakeBrushFromTriangle( vec3_t v1, vec3_t v2, vec3_t v3, shaderInfo_t *terrainShader ) { 880 bspbrush_t *b; 881 vec3_t d1; 882 vec3_t d2; 883 vec3_t d3; 884 885 VectorSet( d1, v1[ 0 ], v1[ 1 ], MIN_WORLD_COORD + 10 ); //FIXME 886 VectorSet( d2, v2[ 0 ], v2[ 1 ], MIN_WORLD_COORD + 10 ); 887 VectorSet( d3, v3[ 0 ], v3[ 1 ], MIN_WORLD_COORD + 10 ); 888 889 buildBrush->numsides = 0; 890 buildBrush->detail = qfalse; 891 892 AddBrushSide( v1, v2, v3, terrainShader ); 893 AddBrushSide( v1, d1, v2, terrainShader ); 894 AddBrushSide( v2, d2, v3, terrainShader ); 895 AddBrushSide( v3, d3, v1, terrainShader ); 896 AddBrushSide( d3, d2, d1, terrainShader ); 897 898 buildBrush->portalareas[0] = -1; 899 buildBrush->portalareas[1] = -1; 900 buildBrush->entitynum = num_entities-1; 901 buildBrush->brushnum = entitySourceBrushes; 902 903 // if there are mirrored planes, the entire brush is invalid 904 if ( !RemoveDuplicateBrushPlanes( buildBrush ) ) { 905 return; 906 } 907 908 // get the content for the entire brush 909 SetBrushContents( buildBrush ); 910 buildBrush->contents |= CONTENTS_DETAIL; 911 912 b = FinishBrush(); 913 if ( !b ) { 914 return; 915 } 916 } 917 918 void MakeTerrainIntoBrushes( terrainMesh_t *tm ) { 919 int index[ 6 ]; 920 int y; 921 int x; 922 terrainVert_t *verts; 923 shaderInfo_t *terrainShader; 924 925 terrainShader = ShaderInfoForShader( "textures/common/terrain" ); 926 927 verts = tm->map; 928 for( y = 0; y < tm->height - 1; y++ ) { 929 for( x = 0; x < tm->width - 1; x++ ) { 930 if ( ( x + y ) & 1 ) { 931 // first tri 932 index[ 0 ] = x + y * tm->width; 933 index[ 1 ] = x + ( y + 1 ) * tm->width; 934 index[ 2 ] = ( x + 1 ) + ( y + 1 ) * tm->width; 935 index[ 3 ] = ( x + 1 ) + ( y + 1 ) * tm->width; 936 index[ 4 ] = ( x + 1 ) + y * tm->width; 937 index[ 5 ] = x + y * tm->width; 938 } else { 939 // first tri 940 index[ 0 ] = x + y * tm->width; 941 index[ 1 ] = x + ( y + 1 ) * tm->width; 942 index[ 2 ] = ( x + 1 ) + y * tm->width; 943 index[ 3 ] = ( x + 1 ) + y * tm->width; 944 index[ 4 ] = x + ( y + 1 ) * tm->width; 945 index[ 5 ] = ( x + 1 ) + ( y + 1 ) * tm->width; 946 } 947 948 MakeBrushFromTriangle( verts[ index[ 0 ] ].xyz, verts[ index[ 1 ] ].xyz, verts[ index[ 2 ] ].xyz, terrainShader ); 949 MakeBrushFromTriangle( verts[ index[ 3 ] ].xyz, verts[ index[ 4 ] ].xyz, verts[ index[ 5 ] ].xyz, terrainShader ); 950 } 951 } 952 } 953 954 void Terrain_ParseFace( terrainFace_t *face ) { 955 shaderInfo_t *si; 956 vec_t shift[ 2 ]; 957 vec_t rotate; 958 vec_t scale[ 2 ]; 959 char name[ MAX_QPATH ]; 960 char shader[ MAX_QPATH ]; 961 plane_t p; 962 963 // read the texturedef 964 GetToken( qfalse ); 965 strcpy( name, token ); 966 967 GetToken( qfalse ); 968 shift[ 0 ] = atof(token); 969 GetToken( qfalse ); 970 shift[ 1 ] = atof( token ); 971 GetToken( qfalse ); 972 rotate = atof( token ); 973 GetToken( qfalse ); 974 scale[ 0 ] = atof( token ); 975 GetToken( qfalse ); 976 scale[ 1 ] = atof( token ); 977 978 // find default flags and values 979 sprintf( shader, "textures/%s", name ); 980 si = ShaderInfoForShader( shader ); 981 face->shaderInfo = si; 982 //face->texdef = si->texdef; 983 984 // skip over old contents 985 GetToken( qfalse ); 986 987 // skip over old flags 988 GetToken( qfalse ); 989 990 // skip over old value 991 GetToken( qfalse ); 992 993 //Surface_Parse( &face->texdef ); 994 //Surface_BuildTexdef( &face->texdef ); 995 996 // make a fake horizontal plane 997 VectorSet( p.normal, 0, 0, 1 ); 998 p.dist = 0; 999 p.type = PlaneTypeForNormal( p.normal ); 1000 1001 QuakeTextureVecs( &p, shift, rotate, scale, face->vecs ); 1002 } 1003 1004 #define MAX_TERRAIN_TEXTURES 128 1005 static int numtextures = 0;; 1006 static shaderInfo_t *textures[ MAX_TERRAIN_TEXTURES ]; 1007 1008 void Terrain_AddTexture( shaderInfo_t *texture ) { 1009 int i; 1010 1011 if ( !texture ) { 1012 return; 1013 } 1014 1015 for( i = 0; i < numtextures; i++ ) { 1016 if ( textures[ i ] == texture ) { 1017 return; 1018 } 1019 } 1020 1021 if ( numtextures >= MAX_TERRAIN_TEXTURES ) { 1022 Error( "Too many textures on terrain" ); 1023 return; 1024 } 1025 1026 textures[ numtextures++ ] = texture; 1027 } 1028 1029 int LayerForShader( shaderInfo_t *shader ) { 1030 int i; 1031 int l; 1032 1033 l = strlen( shader->shader ); 1034 for( i = l - 1; i >= 0; i-- ) { 1035 if ( shader->shader[ i ] == '_' ) { 1036 return atoi( &shader->shader[ i + 1 ] ); 1037 break; 1038 } 1039 } 1040 1041 return 0; 1042 } 1043 1044 /* 1045 ================= 1046 ParseTerrain 1047 1048 Creates a mapDrawSurface_t from the terrain text 1049 ================= 1050 */ 1051 1052 void ParseTerrain( void ) { 1053 int i, j; 1054 int x, y; 1055 int x1, y1; 1056 terrainMesh_t t; 1057 int index; 1058 terrainVert_t *verts[ 6 ]; 1059 int num_layers; 1060 int layer, minlayer, maxlayer; 1061 int alpha[ 6 ]; 1062 shaderInfo_t *si, *terrainShader; 1063 int surfwidth, surfheight, surfsize; 1064 terrainSurf_t *surf; 1065 char shadername[ MAX_QPATH ]; 1066 1067 mapent->firstDrawSurf = numMapDrawSurfs; 1068 1069 memset( &t, 0, sizeof( t ) ); 1070 1071 MatchToken( "{" ); 1072 1073 // get width 1074 GetToken( qtrue ); 1075 t.width = atoi( token ); 1076 1077 // get height 1078 GetToken( qfalse ); 1079 t.height = atoi( token ); 1080 1081 // get scale_x 1082 GetToken( qfalse ); 1083 t.scale_x = atof( token ); 1084 1085 // get scale_y 1086 GetToken( qfalse ); 1087 t.scale_y = atof( token ); 1088 1089 // get origin 1090 GetToken( qtrue ); 1091 t.origin[ 0 ] = atof( token ); 1092 GetToken( qfalse ); 1093 t.origin[ 1 ] = atof( token ); 1094 GetToken( qfalse ); 1095 t.origin[ 2 ] = atof( token ); 1096 1097 t.map = malloc( t.width * t.height * sizeof( t.map[ 0 ] ) ); 1098 1099 if ( t.width <= 0 || t.height <= 0 ) { 1100 Error( "ParseTerrain: bad size" ); 1101 } 1102 1103 numtextures = 0; 1104 index = 0; 1105 for ( i = 0; i < t.height; i++ ) { 1106 for( j = 0; j < t.width; j++, index++ ) { 1107 // get height 1108 GetToken( qtrue ); 1109 t.map[ index ].xyz[ 0 ] = t.origin[ 0 ] + t.scale_x * ( float )j; 1110 t.map[ index ].xyz[ 1 ] = t.origin[ 1 ] + t.scale_y * ( float )i; 1111 t.map[ index ].xyz[ 2 ] = t.origin[ 2 ] + atof( token ); 1112 1113 Terrain_ParseFace( &t.map[ index ].tri ); 1114 Terrain_AddTexture( t.map[ index ].tri.shaderInfo ); 1115 } 1116 } 1117 1118 MatchToken( "}" ); 1119 MatchToken( "}" ); 1120 1121 MakeTerrainIntoBrushes( &t ); 1122 1123 surfwidth = ( ( t.scale_x * t.width ) + SURF_WIDTH - 1 ) / SURF_WIDTH; 1124 surfheight = ( ( t.scale_y * t.height ) + SURF_HEIGHT - 1 ) / SURF_HEIGHT; 1125 surfsize = surfwidth * surfheight; 1126 1127 //FIXME 1128 num_layers = 0; 1129 for( i = 0; i < numtextures; i++ ) { 1130 layer = LayerForShader( textures[ i ] ) + 1; 1131 if ( layer > num_layers ) { 1132 num_layers = layer; 1133 } 1134 } 1135 num_layers = 4; 1136 1137 memset( alpha, 0, sizeof( alpha ) ); 1138 1139 lastSurface = NULL; 1140 numsurfaces = 0; 1141 maxsurfaces = 0; 1142 for( i = num_layers; i > 0; i-- ) { 1143 maxsurfaces += i * surfsize; 1144 } 1145 1146 surfaces = malloc( maxsurfaces * sizeof( *surfaces ) ); 1147 memset( surfaces, 0, maxsurfaces * sizeof( *surfaces ) ); 1148 1149 terrainShader = ShaderInfoForShader( "textures/common/terrain" ); 1150 1151 // get the shadername 1152 if ( Q_strncasecmp( textures[ 0 ]->shader, "textures/", 9 ) == 0 ) { 1153 strcpy( shadername, &textures[ 0 ]->shader[ 9 ] ); 1154 } else { 1155 strcpy( shadername, textures[ 0 ]->shader ); 1156 } 1157 j = strlen( shadername ); 1158 for( i = j - 1; i >= 0; i-- ) { 1159 if ( shadername[ i ] == '_' ) { 1160 shadername[ i ] = 0; 1161 break; 1162 } 1163 } 1164 1165 for( y = 0; y < t.height - 1; y++ ) { 1166 for( x = 0; x < t.width - 1; x++ ) { 1167 Terrain_GetTriangles( &t, x, y, verts ); 1168 1169 x1 = ( ( float )x / ( float )( t.width - 1 ) ) * surfwidth; 1170 if ( x1 >= surfwidth ) { 1171 x1 = surfwidth - 1; 1172 } 1173 1174 y1 = ( ( float )y / ( float )( t.height - 1 ) ) * surfheight; 1175 if ( y1 >= surfheight ) { 1176 y1 = surfheight - 1; 1177 } 1178 1179 maxlayer = minlayer = LayerForShader( verts[ 0 ]->tri.shaderInfo ); 1180 for( i = 0; i < 3; i++ ) { 1181 layer = LayerForShader( verts[ i ]->tri.shaderInfo ); 1182 if ( layer < minlayer ) { 1183 minlayer = layer; 1184 } 1185 if ( layer > maxlayer ) { 1186 maxlayer = layer; 1187 } 1188 } 1189 1190 for( i = 0; i < 3; i++ ) { 1191 layer = LayerForShader( verts[ i ]->tri.shaderInfo ); 1192 if ( layer > minlayer ) { 1193 alpha[ i ] = 1.0f; 1194 } else { 1195 alpha[ i ] = 0.0f; 1196 } 1197 } 1198 1199 si = ShaderForLayer( minlayer, maxlayer, shadername ); 1200 surf = SurfaceForShader( si, x1, y1 ); 1201 EmitTerrainVerts2( surf, &verts[ 0 ], &alpha[ 0 ] ); 1202 1203 // second triangle 1204 maxlayer = minlayer = LayerForShader( verts[ 3 ]->tri.shaderInfo ); 1205 for( i = 3; i < 6; i++ ) { 1206 layer = LayerForShader( verts[ i ]->tri.shaderInfo ); 1207 if ( layer < minlayer ) { 1208 minlayer = layer; 1209 } 1210 if ( layer > maxlayer ) { 1211 maxlayer = layer; 1212 } 1213 } 1214 1215 for( i = 3; i < 6; i++ ) { 1216 layer = LayerForShader( verts[ i ]->tri.shaderInfo ); 1217 if ( layer > minlayer ) { 1218 alpha[ i ] = 1.0f; 1219 } else { 1220 alpha[ i ] = 0.0f; 1221 } 1222 } 1223 1224 si = ShaderForLayer( minlayer, maxlayer, shadername ); 1225 surf = SurfaceForShader( si, x1, y1 ); 1226 EmitTerrainVerts2( surf, &verts[ 3 ], &alpha[ 3 ] ); 1227 } 1228 } 1229 1230 // create the final surfaces 1231 for( surf = surfaces, i = 0; i < numsurfaces; i++, surf++ ) { 1232 if ( surf->numVerts ) { 1233 CreateTerrainSurface( surf, surf->shader ); 1234 } 1235 } 1236 1237 // 1238 // clean up any allocated memory 1239 // 1240 for( surf = surfaces, i = 0; i < numsurfaces; i++, surf++ ) { 1241 if ( surf->verts ) { 1242 free( surf->verts ); 1243 free( surf->indexes ); 1244 } 1245 } 1246 free( surfaces ); 1247 1248 surfaces = NULL; 1249 lastSurface = NULL; 1250 numsurfaces = 0; 1251 maxsurfaces = 0; 1252 1253 free( t.map ); 1254 } 1255