surface.c (28518B)
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 23 #include "qbsp.h" 24 25 26 mapDrawSurface_t mapDrawSurfs[MAX_MAP_DRAW_SURFS]; 27 int numMapDrawSurfs; 28 29 /* 30 ============================================================================= 31 32 DRAWSURF CONSTRUCTION 33 34 ============================================================================= 35 */ 36 37 /* 38 ================= 39 AllocDrawSurf 40 ================= 41 */ 42 mapDrawSurface_t *AllocDrawSurf( void ) { 43 mapDrawSurface_t *ds; 44 45 if ( numMapDrawSurfs >= MAX_MAP_DRAW_SURFS ) { 46 Error( "MAX_MAP_DRAW_SURFS"); 47 } 48 ds = &mapDrawSurfs[ numMapDrawSurfs ]; 49 numMapDrawSurfs++; 50 51 return ds; 52 } 53 54 /* 55 ================= 56 DrawSurfaceForSide 57 ================= 58 */ 59 #define SNAP_FLOAT_TO_INT 8 60 #define SNAP_INT_TO_FLOAT (1.0/SNAP_FLOAT_TO_INT) 61 62 mapDrawSurface_t *DrawSurfaceForSide( bspbrush_t *b, side_t *s, winding_t *w ) { 63 mapDrawSurface_t *ds; 64 int i, j; 65 shaderInfo_t *si; 66 drawVert_t *dv; 67 float mins[2], maxs[2]; 68 69 // brush primitive : 70 // axis base 71 vec3_t texX,texY; 72 vec_t x,y; 73 74 if ( w->numpoints > 64 ) { 75 Error( "DrawSurfaceForSide: w->numpoints = %i", w->numpoints ); 76 } 77 78 si = s->shaderInfo; 79 80 ds = AllocDrawSurf(); 81 82 ds->shaderInfo = si; 83 ds->mapBrush = b; 84 ds->side = s; 85 ds->fogNum = -1; 86 ds->numVerts = w->numpoints; 87 ds->verts = malloc( ds->numVerts * sizeof( *ds->verts ) ); 88 memset( ds->verts, 0, ds->numVerts * sizeof( *ds->verts ) ); 89 90 mins[0] = mins[1] = 99999; 91 maxs[0] = maxs[1] = -99999; 92 93 // compute s/t coordinates from brush primitive texture matrix 94 // compute axis base 95 ComputeAxisBase( mapplanes[s->planenum].normal, texX, texY ); 96 97 for ( j = 0 ; j < w->numpoints ; j++ ) { 98 dv = ds->verts + j; 99 100 // round the xyz to a given precision 101 for ( i = 0 ; i < 3 ; i++ ) { 102 dv->xyz[i] = SNAP_INT_TO_FLOAT * floor( w->p[j][i] * SNAP_FLOAT_TO_INT + 0.5 ); 103 } 104 105 if (g_bBrushPrimit==BPRIMIT_OLDBRUSHES) 106 { 107 // calculate texture s/t 108 dv->st[0] = s->vecs[0][3] + DotProduct( s->vecs[0], dv->xyz ); 109 dv->st[1] = s->vecs[1][3] + DotProduct( s->vecs[1], dv->xyz ); 110 dv->st[0] /= si->width; 111 dv->st[1] /= si->height; 112 } 113 else 114 { 115 // calculate texture s/t from brush primitive texture matrix 116 x = DotProduct( dv->xyz, texX ); 117 y = DotProduct( dv->xyz, texY ); 118 dv->st[0]=s->texMat[0][0]*x+s->texMat[0][1]*y+s->texMat[0][2]; 119 dv->st[1]=s->texMat[1][0]*x+s->texMat[1][1]*y+s->texMat[1][2]; 120 } 121 122 for ( i = 0 ; i < 2 ; i++ ) { 123 if ( dv->st[i] < mins[i] ) { 124 mins[i] = dv->st[i]; 125 } 126 if ( dv->st[i] > maxs[i] ) { 127 maxs[i] = dv->st[i]; 128 } 129 } 130 131 // copy normal 132 VectorCopy ( mapplanes[s->planenum].normal, dv->normal ); 133 } 134 135 // adjust the texture coordinates to be as close to 0 as possible 136 if ( !si->globalTexture ) { 137 mins[0] = floor( mins[0] ); 138 mins[1] = floor( mins[1] ); 139 for ( i = 0 ; i < w->numpoints ; i++ ) { 140 dv = ds->verts + i; 141 dv->st[0] -= mins[0]; 142 dv->st[1] -= mins[1]; 143 } 144 } 145 146 return ds; 147 } 148 149 150 //========================================================================= 151 152 153 154 155 typedef struct { 156 int planenum; 157 shaderInfo_t *shaderInfo; 158 int count; 159 } sideRef_t; 160 161 #define MAX_SIDE_REFS MAX_MAP_PLANES 162 163 sideRef_t sideRefs[MAX_SIDE_REFS]; 164 int numSideRefs; 165 166 void AddSideRef( side_t *side ) { 167 int i; 168 169 for ( i = 0 ; i < numSideRefs ; i++ ) { 170 if ( side->planenum == sideRefs[i].planenum 171 && side->shaderInfo == sideRefs[i].shaderInfo ) { 172 sideRefs[i].count++; 173 return; 174 } 175 } 176 177 if ( numSideRefs == MAX_SIDE_REFS ) { 178 Error( "MAX_SIDE_REFS" ); 179 } 180 181 sideRefs[i].planenum = side->planenum; 182 sideRefs[i].shaderInfo = side->shaderInfo; 183 sideRefs[i].count++; 184 numSideRefs++; 185 } 186 187 188 /* 189 ===================== 190 MergeSides 191 192 ===================== 193 */ 194 void MergeSides( entity_t *e, tree_t *tree ) { 195 int i; 196 197 qprintf( "----- MergeSides -----\n"); 198 199 for ( i = e->firstDrawSurf ; i < numMapDrawSurfs ; i++ ) { 200 // AddSideRef( side ); 201 } 202 203 qprintf( "%5i siderefs\n", numSideRefs ); 204 } 205 206 //===================================================================== 207 208 /* 209 =================== 210 SubdivideDrawSurf 211 =================== 212 */ 213 void SubdivideDrawSurf( mapDrawSurface_t *ds, winding_t *w, float subdivisions ) { 214 int i; 215 int axis; 216 vec3_t bounds[2]; 217 const float epsilon = 0.1; 218 int subFloor, subCeil; 219 winding_t *frontWinding, *backWinding; 220 mapDrawSurface_t *newds; 221 222 if ( !w ) { 223 return; 224 } 225 if ( w->numpoints < 3 ) { 226 Error( "SubdivideDrawSurf: Bad w->numpoints" ); 227 } 228 229 ClearBounds( bounds[0], bounds[1] ); 230 for ( i = 0 ; i < w->numpoints ; i++ ) { 231 AddPointToBounds( w->p[i], bounds[0], bounds[1] ); 232 } 233 234 for ( axis = 0 ; axis < 3 ; axis++ ) { 235 vec3_t planePoint = { 0, 0, 0 }; 236 vec3_t planeNormal = { 0, 0, 0 }; 237 float d; 238 239 subFloor = floor( bounds[0][axis] / subdivisions ) * subdivisions; 240 subCeil = ceil( bounds[1][axis] / subdivisions ) * subdivisions; 241 242 planePoint[axis] = subFloor + subdivisions; 243 planeNormal[axis] = -1; 244 245 d = DotProduct( planePoint, planeNormal ); 246 247 // subdivide if necessary 248 if ( subCeil - subFloor > subdivisions ) { 249 // gotta clip polygon into two polygons 250 ClipWindingEpsilon( w, planeNormal, d, epsilon, &frontWinding, &backWinding ); 251 252 // the clip may not produce two polygons if it was epsilon close 253 if ( !frontWinding ) { 254 w = backWinding; 255 } else if ( !backWinding ) { 256 w = frontWinding; 257 } else { 258 SubdivideDrawSurf( ds, frontWinding, subdivisions ); 259 SubdivideDrawSurf( ds, backWinding, subdivisions ); 260 261 return; 262 } 263 } 264 } 265 266 // emit this polygon 267 newds = DrawSurfaceForSide( ds->mapBrush, ds->side, w ); 268 newds->fogNum = ds->fogNum; 269 } 270 271 272 /* 273 ===================== 274 SubdivideDrawSurfs 275 276 Chop up surfaces that have subdivision attributes 277 ===================== 278 */ 279 void SubdivideDrawSurfs( entity_t *e, tree_t *tree ) { 280 int i; 281 mapDrawSurface_t *ds; 282 int numBaseDrawSurfs; 283 winding_t *w; 284 float subdivision; 285 shaderInfo_t *si; 286 287 qprintf( "----- SubdivideDrawSurfs -----\n"); 288 numBaseDrawSurfs = numMapDrawSurfs; 289 for ( i = e->firstDrawSurf ; i < numBaseDrawSurfs ; i++ ) { 290 ds = &mapDrawSurfs[i]; 291 292 // only subdivide brush sides, not patches or misc_models 293 if ( !ds->side ) { 294 continue; 295 } 296 297 // check subdivision for shader 298 si = ds->side->shaderInfo; 299 if ( !si ) { 300 continue; 301 } 302 303 if (ds->shaderInfo->autosprite || si->autosprite) { 304 continue; 305 } 306 307 subdivision = si->subdivisions; 308 if ( !subdivision ) { 309 continue; 310 } 311 312 w = WindingFromDrawSurf( ds ); 313 ds->numVerts = 0; // remove this reference 314 SubdivideDrawSurf( ds, w, subdivision ); 315 } 316 317 } 318 319 320 //=================================================================================== 321 322 /* 323 ==================== 324 ClipSideIntoTree_r 325 326 Adds non-opaque leaf fragments to the convex hull 327 ==================== 328 */ 329 void ClipSideIntoTree_r( winding_t *w, side_t *side, node_t *node ) { 330 plane_t *plane; 331 winding_t *front, *back; 332 333 if ( !w ) { 334 return; 335 } 336 337 if ( node->planenum != PLANENUM_LEAF ) { 338 if ( side->planenum == node->planenum ) { 339 ClipSideIntoTree_r( w, side, node->children[0] ); 340 return; 341 } 342 if ( side->planenum == ( node->planenum ^ 1) ) { 343 ClipSideIntoTree_r( w, side, node->children[1] ); 344 return; 345 } 346 347 plane = &mapplanes[ node->planenum ]; 348 ClipWindingEpsilon ( w, plane->normal, plane->dist, 349 ON_EPSILON, &front, &back ); 350 FreeWinding( w ); 351 352 ClipSideIntoTree_r( front, side, node->children[0] ); 353 ClipSideIntoTree_r( back, side, node->children[1] ); 354 355 return; 356 } 357 358 // if opaque leaf, don't add 359 if ( !node->opaque ) { 360 AddWindingToConvexHull( w, &side->visibleHull, mapplanes[ side->planenum ].normal ); 361 } 362 363 FreeWinding( w ); 364 return; 365 } 366 367 368 /* 369 ===================== 370 ClipSidesIntoTree 371 372 Creates side->visibleHull for all visible sides 373 374 The drawsurf for a side will consist of the convex hull of 375 all points in non-opaque clusters, which allows overlaps 376 to be trimmed off automatically. 377 ===================== 378 */ 379 void ClipSidesIntoTree( entity_t *e, tree_t *tree ) { 380 bspbrush_t *b; 381 int i; 382 winding_t *w; 383 side_t *side, *newSide; 384 shaderInfo_t *si; 385 386 qprintf( "----- ClipSidesIntoTree -----\n"); 387 388 for ( b = e->brushes ; b ; b = b->next ) { 389 for ( i = 0 ; i < b->numsides ; i++ ) { 390 side = &b->sides[i]; 391 if ( !side->winding) { 392 continue; 393 } 394 w = CopyWinding( side->winding ); 395 side->visibleHull = NULL; 396 ClipSideIntoTree_r( w, side, tree->headnode ); 397 398 w = side->visibleHull; 399 if ( !w ) { 400 continue; 401 } 402 si = side->shaderInfo; 403 if ( !si ) { 404 continue; 405 } 406 // don't create faces for non-visible sides 407 if ( si->surfaceFlags & SURF_NODRAW ) { 408 continue; 409 } 410 411 // always use the original quad winding for auto sprites 412 if ( side->shaderInfo->autosprite ) { 413 w = side->winding; 414 } 415 // 416 if ( side->bevel ) { 417 Error( "monkey tried to create draw surface for brush bevel" ); 418 } 419 // save this winding as a visible surface 420 DrawSurfaceForSide( b, side, w ); 421 422 // make a back side for it if needed 423 if ( !(si->contents & CONTENTS_FOG) ) { 424 continue; 425 } 426 427 // duplicate the up-facing side 428 w = ReverseWinding( w ); 429 430 newSide = malloc( sizeof( *side ) ); 431 *newSide = *side; 432 newSide->visibleHull = w; 433 newSide->planenum ^= 1; 434 435 // save this winding as a visible surface 436 DrawSurfaceForSide( b, newSide, w ); 437 438 } 439 } 440 } 441 442 /* 443 =================================================================================== 444 445 FILTER REFERENCES DOWN THE TREE 446 447 =================================================================================== 448 */ 449 450 /* 451 ==================== 452 FilterDrawSurfIntoTree 453 454 Place a reference to the given drawsurf in every leaf it contacts 455 We assume that the point mesh aproximation to the curve will get a 456 reference into all the leafs we need. 457 ==================== 458 */ 459 int FilterMapDrawSurfIntoTree( vec3_t point, mapDrawSurface_t *ds, node_t *node ) { 460 drawSurfRef_t *dsr; 461 float d; 462 plane_t *plane; 463 int c; 464 465 if ( node->planenum != PLANENUM_LEAF ) { 466 plane = &mapplanes[ node->planenum ]; 467 d = DotProduct( point, plane->normal ) - plane->dist; 468 c = 0; 469 if ( d >= -ON_EPSILON ) { 470 c += FilterMapDrawSurfIntoTree( point, ds, node->children[0] ); 471 } 472 if ( d <= ON_EPSILON ) { 473 c += FilterMapDrawSurfIntoTree( point, ds, node->children[1] ); 474 } 475 return c; 476 } 477 478 // if opaque leaf, don't add 479 if ( node->opaque ) { 480 return 0; 481 } 482 483 // add the drawsurf if it hasn't been already 484 for ( dsr = node->drawSurfReferences ; dsr ; dsr = dsr->nextRef ) { 485 if ( dsr->outputNumber == numDrawSurfaces ) { 486 return 0; // already referenced 487 } 488 } 489 490 dsr = malloc( sizeof( *dsr ) ); 491 dsr->outputNumber = numDrawSurfaces; 492 dsr->nextRef = node->drawSurfReferences; 493 node->drawSurfReferences = dsr; 494 return 1; 495 } 496 497 /* 498 ==================== 499 FilterDrawSurfIntoTree_r 500 501 Place a reference to the given drawsurf in every leaf it is in 502 ==================== 503 */ 504 int FilterMapDrawSurfIntoTree_r( winding_t *w, mapDrawSurface_t *ds, node_t *node ) { 505 drawSurfRef_t *dsr; 506 plane_t *plane; 507 int total; 508 winding_t *front, *back; 509 510 if ( node->planenum != PLANENUM_LEAF ) { 511 plane = &mapplanes[ node->planenum ]; 512 ClipWindingEpsilon ( w, plane->normal, plane->dist, 513 ON_EPSILON, &front, &back ); 514 515 total = 0; 516 if ( front ) { 517 total += FilterMapDrawSurfIntoTree_r( front, ds, node->children[0] ); 518 } 519 if ( back ) { 520 total += FilterMapDrawSurfIntoTree_r( back, ds, node->children[1] ); 521 } 522 523 FreeWinding( w ); 524 return total; 525 } 526 527 // if opaque leaf, don't add 528 if ( node->opaque ) { 529 return 0; 530 } 531 532 // add the drawsurf if it hasn't been already 533 for ( dsr = node->drawSurfReferences ; dsr ; dsr = dsr->nextRef ) { 534 if ( dsr->outputNumber == numDrawSurfaces ) { 535 return 0; // already referenced 536 } 537 } 538 539 dsr = malloc( sizeof( *dsr ) ); 540 dsr->outputNumber = numDrawSurfaces; 541 dsr->nextRef = node->drawSurfReferences; 542 node->drawSurfReferences = dsr; 543 return 1; 544 } 545 546 /* 547 ==================== 548 FilterSideIntoTree_r 549 550 Place a reference to the given drawsurf in every leaf it contacts 551 ==================== 552 */ 553 int FilterSideIntoTree_r( winding_t *w, side_t *side, mapDrawSurface_t *ds, node_t *node ) { 554 drawSurfRef_t *dsr; 555 plane_t *plane; 556 winding_t *front, *back; 557 int total; 558 559 if ( !w ) { 560 return 0; 561 } 562 563 if ( node->planenum != PLANENUM_LEAF ) { 564 if ( side->planenum == node->planenum ) { 565 return FilterSideIntoTree_r( w, side, ds, node->children[0] ); 566 } 567 if ( side->planenum == ( node->planenum ^ 1) ) { 568 return FilterSideIntoTree_r( w, side, ds, node->children[1] ); 569 } 570 571 plane = &mapplanes[ node->planenum ]; 572 ClipWindingEpsilon ( w, plane->normal, plane->dist, 573 ON_EPSILON, &front, &back ); 574 575 total = FilterSideIntoTree_r( front, side, ds, node->children[0] ); 576 total += FilterSideIntoTree_r( back, side, ds, node->children[1] ); 577 578 FreeWinding( w ); 579 return total; 580 } 581 582 // if opaque leaf, don't add 583 if ( node->opaque ) { 584 return 0; 585 } 586 587 dsr = malloc( sizeof( *dsr ) ); 588 dsr->outputNumber = numDrawSurfaces; 589 dsr->nextRef = node->drawSurfReferences; 590 node->drawSurfReferences = dsr; 591 592 FreeWinding( w ); 593 return 1; 594 } 595 596 597 /* 598 ===================== 599 FilterFaceIntoTree 600 ===================== 601 */ 602 int FilterFaceIntoTree( mapDrawSurface_t *ds, tree_t *tree ) { 603 int l; 604 winding_t *w; 605 606 w = WindingFromDrawSurf( ds ); 607 l = FilterSideIntoTree_r( w, ds->side, ds, tree->headnode ); 608 609 return l; 610 } 611 612 613 614 /* 615 ===================== 616 FilterPatchSurfIntoTree 617 ===================== 618 */ 619 #define SUBDIVISION_LIMIT 8.0 620 int FilterPatchSurfIntoTree( mapDrawSurface_t *ds, tree_t *tree ) { 621 int i, j; 622 int l; 623 mesh_t baseMesh, *subdividedMesh; 624 winding_t *w; 625 626 baseMesh.width = ds->patchWidth; 627 baseMesh.height = ds->patchHeight; 628 baseMesh.verts = ds->verts; 629 subdividedMesh = SubdivideMesh( baseMesh, SUBDIVISION_LIMIT, 32 ); 630 631 l = 0; 632 for (i = 0; i < subdividedMesh->width-1; i++) { 633 for (j = 0; j < subdividedMesh->height-1; j++) { 634 w = AllocWinding(3); 635 VectorCopy(subdividedMesh->verts[j * subdividedMesh->width + i].xyz, w->p[0]); 636 VectorCopy(subdividedMesh->verts[j * subdividedMesh->width + i + 1].xyz, w->p[1]); 637 VectorCopy(subdividedMesh->verts[(j+1) * subdividedMesh->width + i].xyz, w->p[2]); 638 w->numpoints = 3; 639 l += FilterMapDrawSurfIntoTree_r( w, ds, tree->headnode ); 640 w = AllocWinding(3); 641 VectorCopy(subdividedMesh->verts[j * subdividedMesh->width + i + 1].xyz, w->p[0]); 642 VectorCopy(subdividedMesh->verts[(j+1) * subdividedMesh->width + i + 1].xyz, w->p[1]); 643 VectorCopy(subdividedMesh->verts[(j+1) * subdividedMesh->width + i].xyz, w->p[2]); 644 w->numpoints = 3; 645 l += FilterMapDrawSurfIntoTree_r( w, ds, tree->headnode ); 646 } 647 } 648 649 // also use the old point filtering into the tree 650 for ( i = 0 ; i < subdividedMesh->width * subdividedMesh->height ; i++ ) { 651 l += FilterMapDrawSurfIntoTree( subdividedMesh->verts[i].xyz, ds, tree->headnode ); 652 } 653 654 free(subdividedMesh); 655 656 return l; 657 } 658 659 660 /* 661 ===================== 662 FilterMiscModelSurfIntoTree 663 ===================== 664 */ 665 int FilterMiscModelSurfIntoTree( mapDrawSurface_t *ds, tree_t *tree ) { 666 int i; 667 int l; 668 winding_t *w; 669 670 l = 0; 671 for (i = 0; i < ds->numIndexes-2; i++) { 672 w = AllocWinding(3); 673 VectorCopy(ds->verts[ds->indexes[i]].xyz, w->p[0]); 674 VectorCopy(ds->verts[ds->indexes[i+1]].xyz, w->p[1]); 675 VectorCopy(ds->verts[ds->indexes[i+2]].xyz, w->p[2]); 676 w->numpoints = 3; 677 l += FilterMapDrawSurfIntoTree_r( w, ds, tree->headnode ); 678 } 679 680 // also use the old point filtering into the tree 681 for ( i = 0 ; i < ds->numVerts ; i++ ) { 682 l += FilterMapDrawSurfIntoTree( ds->verts[i].xyz, ds, tree->headnode ); 683 } 684 685 return l; 686 } 687 688 /* 689 ===================== 690 FilterFlareSurfIntoTree 691 ===================== 692 */ 693 int FilterFlareSurfIntoTree( mapDrawSurface_t *ds, tree_t *tree ) { 694 return FilterMapDrawSurfIntoTree( ds->lightmapOrigin, ds, tree->headnode ); 695 } 696 697 698 //====================================================================== 699 700 int c_stripSurfaces, c_fanSurfaces; 701 702 /* 703 ================== 704 IsTriangleDegenerate 705 706 Returns qtrue if all three points are collinear or backwards 707 =================== 708 */ 709 #define COLINEAR_AREA 10 710 static qboolean IsTriangleDegenerate( drawVert_t *points, int a, int b, int c ) { 711 vec3_t v1, v2, v3; 712 float d; 713 714 VectorSubtract( points[b].xyz, points[a].xyz, v1 ); 715 VectorSubtract( points[c].xyz, points[a].xyz, v2 ); 716 CrossProduct( v1, v2, v3 ); 717 d = VectorLength( v3 ); 718 719 // assume all very small or backwards triangles will cause problems 720 if ( d < COLINEAR_AREA ) { 721 return qtrue; 722 } 723 724 return qfalse; 725 } 726 727 /* 728 =============== 729 SurfaceAsTriFan 730 731 The surface can't be represented as a single tristrip without 732 leaving a degenerate triangle (and therefore a crack), so add 733 a point in the middle and create (points-1) triangles in fan order 734 =============== 735 */ 736 static void SurfaceAsTriFan( dsurface_t *ds ) { 737 int i; 738 int colorSum[4]; 739 drawVert_t *mid, *v; 740 741 // create a new point in the center of the face 742 if ( numDrawVerts == MAX_MAP_DRAW_VERTS ) { 743 Error( "MAX_MAP_DRAW_VERTS" ); 744 } 745 mid = &drawVerts[ numDrawVerts ]; 746 numDrawVerts++; 747 748 colorSum[0] = colorSum[1] = colorSum[2] = colorSum[3] = 0; 749 750 v = drawVerts + ds->firstVert; 751 for (i = 0 ; i < ds->numVerts ; i++, v++ ) { 752 VectorAdd( mid->xyz, v->xyz, mid->xyz ); 753 mid->st[0] += v->st[0]; 754 mid->st[1] += v->st[1]; 755 mid->lightmap[0] += v->lightmap[0]; 756 mid->lightmap[1] += v->lightmap[1]; 757 758 colorSum[0] += v->color[0]; 759 colorSum[1] += v->color[1]; 760 colorSum[2] += v->color[2]; 761 colorSum[3] += v->color[3]; 762 } 763 764 mid->xyz[0] /= ds->numVerts; 765 mid->xyz[1] /= ds->numVerts; 766 mid->xyz[2] /= ds->numVerts; 767 768 mid->st[0] /= ds->numVerts; 769 mid->st[1] /= ds->numVerts; 770 771 mid->lightmap[0] /= ds->numVerts; 772 mid->lightmap[1] /= ds->numVerts; 773 774 mid->color[0] = colorSum[0] / ds->numVerts; 775 mid->color[1] = colorSum[1] / ds->numVerts; 776 mid->color[2] = colorSum[2] / ds->numVerts; 777 mid->color[3] = colorSum[3] / ds->numVerts; 778 779 VectorCopy((drawVerts+ds->firstVert)->normal, mid->normal ); 780 781 // fill in indices in trifan order 782 if ( numDrawIndexes + ds->numVerts*3 > MAX_MAP_DRAW_INDEXES ) { 783 Error( "MAX_MAP_DRAWINDEXES" ); 784 } 785 ds->firstIndex = numDrawIndexes; 786 ds->numIndexes = ds->numVerts*3; 787 788 //FIXME 789 // should be: for ( i = 0 ; i < ds->numVerts ; i++ ) { 790 // set a break point and test this in a map 791 //for ( i = 0 ; i < ds->numVerts*3 ; i++ ) { 792 for ( i = 0 ; i < ds->numVerts ; i++ ) { 793 drawIndexes[numDrawIndexes++] = ds->numVerts; 794 drawIndexes[numDrawIndexes++] = i; 795 drawIndexes[numDrawIndexes++] = (i+1) % ds->numVerts; 796 } 797 798 ds->numVerts++; 799 } 800 801 802 /* 803 ================ 804 SurfaceAsTristrip 805 806 Try to create indices that make (points-2) triangles in tristrip order 807 ================ 808 */ 809 #define MAX_INDICES 1024 810 static void SurfaceAsTristrip( dsurface_t *ds ) { 811 int i; 812 int rotate; 813 int numIndices; 814 int ni; 815 int a, b, c; 816 int indices[MAX_INDICES]; 817 818 // determine the triangle strip order 819 numIndices = ( ds->numVerts - 2 ) * 3; 820 if ( numIndices > MAX_INDICES ) { 821 Error( "MAX_INDICES exceeded for surface" ); 822 } 823 824 // try all possible orderings of the points looking 825 // for a strip order that isn't degenerate 826 for ( rotate = 0 ; rotate < ds->numVerts ; rotate++ ) { 827 for ( ni = 0, i = 0 ; i < ds->numVerts - 2 - i ; i++ ) { 828 a = ( ds->numVerts - 1 - i + rotate ) % ds->numVerts; 829 b = ( i + rotate ) % ds->numVerts; 830 c = ( ds->numVerts - 2 - i + rotate ) % ds->numVerts; 831 832 if ( IsTriangleDegenerate( drawVerts + ds->firstVert, a, b, c ) ) { 833 break; 834 } 835 indices[ni++] = a; 836 indices[ni++] = b; 837 indices[ni++] = c; 838 839 if ( i + 1 != ds->numVerts - 1 - i ) { 840 a = ( ds->numVerts - 2 - i + rotate ) % ds->numVerts; 841 b = ( i + rotate ) % ds->numVerts; 842 c = ( i + 1 + rotate ) % ds->numVerts; 843 844 if ( IsTriangleDegenerate( drawVerts + ds->firstVert, a, b, c ) ) { 845 break; 846 } 847 indices[ni++] = a; 848 indices[ni++] = b; 849 indices[ni++] = c; 850 } 851 } 852 if ( ni == numIndices ) { 853 break; // got it done without degenerate triangles 854 } 855 } 856 857 // if any triangle in the strip is degenerate, 858 // render from a centered fan point instead 859 if ( ni < numIndices ) { 860 c_fanSurfaces++; 861 SurfaceAsTriFan( ds ); 862 return; 863 } 864 865 // a normal tristrip 866 c_stripSurfaces++; 867 868 if ( numDrawIndexes + ni > MAX_MAP_DRAW_INDEXES ) { 869 Error( "MAX_MAP_DRAW_INDEXES" ); 870 } 871 ds->firstIndex = numDrawIndexes; 872 ds->numIndexes = ni; 873 874 memcpy( drawIndexes + numDrawIndexes, indices, ni * sizeof(int) ); 875 numDrawIndexes += ni; 876 } 877 878 /* 879 =============== 880 EmitPlanarSurf 881 =============== 882 */ 883 void EmitPlanarSurf( mapDrawSurface_t *ds ) { 884 int j; 885 dsurface_t *out; 886 drawVert_t *outv; 887 888 if ( numDrawSurfaces == MAX_MAP_DRAW_SURFS ) { 889 Error( "MAX_MAP_DRAW_SURFS" ); 890 } 891 out = &drawSurfaces[ numDrawSurfaces ]; 892 numDrawSurfaces++; 893 894 out->surfaceType = MST_PLANAR; 895 out->shaderNum = EmitShader( ds->shaderInfo->shader ); 896 out->firstVert = numDrawVerts; 897 out->numVerts = ds->numVerts; 898 out->fogNum = ds->fogNum; 899 out->lightmapNum = ds->lightmapNum; 900 out->lightmapX = ds->lightmapX; 901 out->lightmapY = ds->lightmapY; 902 out->lightmapWidth = ds->lightmapWidth; 903 out->lightmapHeight = ds->lightmapHeight; 904 905 VectorCopy( ds->lightmapOrigin, out->lightmapOrigin ); 906 VectorCopy( ds->lightmapVecs[0], out->lightmapVecs[0] ); 907 VectorCopy( ds->lightmapVecs[1], out->lightmapVecs[1] ); 908 VectorCopy( ds->lightmapVecs[2], out->lightmapVecs[2] ); 909 910 for ( j = 0 ; j < ds->numVerts ; j++ ) { 911 if ( numDrawVerts == MAX_MAP_DRAW_VERTS ) { 912 Error( "MAX_MAP_DRAW_VERTS" ); 913 } 914 outv = &drawVerts[ numDrawVerts ]; 915 numDrawVerts++; 916 memcpy( outv, &ds->verts[ j ], sizeof( *outv ) ); 917 outv->color[0] = 255; 918 outv->color[1] = 255; 919 outv->color[2] = 255; 920 outv->color[3] = 255; 921 } 922 923 // create the indexes 924 SurfaceAsTristrip( out ); 925 } 926 927 928 /* 929 =============== 930 EmitPatchSurf 931 =============== 932 */ 933 void EmitPatchSurf( mapDrawSurface_t *ds ) { 934 int j; 935 dsurface_t *out; 936 drawVert_t *outv; 937 938 if ( numDrawSurfaces == MAX_MAP_DRAW_SURFS ) { 939 Error( "MAX_MAP_DRAW_SURFS" ); 940 } 941 out = &drawSurfaces[ numDrawSurfaces ]; 942 numDrawSurfaces++; 943 944 out->surfaceType = MST_PATCH; 945 out->shaderNum = EmitShader( ds->shaderInfo->shader ); 946 out->firstVert = numDrawVerts; 947 out->numVerts = ds->numVerts; 948 out->firstIndex = numDrawIndexes; 949 out->numIndexes = ds->numIndexes; 950 out->patchWidth = ds->patchWidth; 951 out->patchHeight = ds->patchHeight; 952 out->fogNum = ds->fogNum; 953 out->lightmapNum = ds->lightmapNum; 954 out->lightmapX = ds->lightmapX; 955 out->lightmapY = ds->lightmapY; 956 out->lightmapWidth = ds->lightmapWidth; 957 out->lightmapHeight = ds->lightmapHeight; 958 959 VectorCopy( ds->lightmapOrigin, out->lightmapOrigin ); 960 VectorCopy( ds->lightmapVecs[0], out->lightmapVecs[0] ); 961 VectorCopy( ds->lightmapVecs[1], out->lightmapVecs[1] ); 962 VectorCopy( ds->lightmapVecs[2], out->lightmapVecs[2] ); 963 964 for ( j = 0 ; j < ds->numVerts ; j++ ) { 965 if ( numDrawVerts == MAX_MAP_DRAW_VERTS ) { 966 Error( "MAX_MAP_DRAW_VERTS" ); 967 } 968 outv = &drawVerts[ numDrawVerts ]; 969 numDrawVerts++; 970 memcpy( outv, &ds->verts[ j ], sizeof( *outv ) ); 971 outv->color[0] = 255; 972 outv->color[1] = 255; 973 outv->color[2] = 255; 974 outv->color[3] = 255; 975 } 976 977 for ( j = 0 ; j < ds->numIndexes ; j++ ) { 978 if ( numDrawIndexes == MAX_MAP_DRAW_INDEXES ) { 979 Error( "MAX_MAP_DRAW_INDEXES" ); 980 } 981 drawIndexes[ numDrawIndexes ] = ds->indexes[ j ]; 982 numDrawIndexes++; 983 } 984 } 985 986 /* 987 =============== 988 EmitFlareSurf 989 =============== 990 */ 991 void EmitFlareSurf( mapDrawSurface_t *ds ) { 992 dsurface_t *out; 993 994 if ( numDrawSurfaces == MAX_MAP_DRAW_SURFS ) { 995 Error( "MAX_MAP_DRAW_SURFS" ); 996 } 997 out = &drawSurfaces[ numDrawSurfaces ]; 998 numDrawSurfaces++; 999 1000 out->surfaceType = MST_FLARE; 1001 out->shaderNum = EmitShader( ds->shaderInfo->shader ); 1002 out->fogNum = ds->fogNum; 1003 1004 VectorCopy( ds->lightmapOrigin, out->lightmapOrigin ); 1005 VectorCopy( ds->lightmapVecs[0], out->lightmapVecs[0] ); // color 1006 VectorCopy( ds->lightmapVecs[2], out->lightmapVecs[2] ); 1007 } 1008 1009 1010 /* 1011 =============== 1012 EmitModelSurf 1013 =============== 1014 */ 1015 void EmitModelSurf( mapDrawSurface_t *ds ) { 1016 int j; 1017 dsurface_t *out; 1018 drawVert_t *outv; 1019 1020 if ( numDrawSurfaces == MAX_MAP_DRAW_SURFS ) { 1021 Error( "MAX_MAP_DRAW_SURFS" ); 1022 } 1023 out = &drawSurfaces[ numDrawSurfaces ]; 1024 numDrawSurfaces++; 1025 1026 out->surfaceType = MST_TRIANGLE_SOUP; 1027 out->shaderNum = EmitShader( ds->shaderInfo->shader ); 1028 out->firstVert = numDrawVerts; 1029 out->numVerts = ds->numVerts; 1030 out->firstIndex = numDrawIndexes; 1031 out->numIndexes = ds->numIndexes; 1032 out->patchWidth = ds->patchWidth; 1033 out->patchHeight = ds->patchHeight; 1034 out->fogNum = ds->fogNum; 1035 out->lightmapNum = ds->lightmapNum; 1036 out->lightmapX = ds->lightmapX; 1037 out->lightmapY = ds->lightmapY; 1038 out->lightmapWidth = ds->lightmapWidth; 1039 out->lightmapHeight = ds->lightmapHeight; 1040 1041 VectorCopy( ds->lightmapOrigin, out->lightmapOrigin ); 1042 VectorCopy( ds->lightmapVecs[0], out->lightmapVecs[0] ); 1043 VectorCopy( ds->lightmapVecs[1], out->lightmapVecs[1] ); 1044 VectorCopy( ds->lightmapVecs[2], out->lightmapVecs[2] ); 1045 1046 for ( j = 0 ; j < ds->numVerts ; j++ ) { 1047 if ( numDrawVerts == MAX_MAP_DRAW_VERTS ) { 1048 Error( "MAX_MAP_DRAW_VERTS" ); 1049 } 1050 outv = &drawVerts[ numDrawVerts ]; 1051 numDrawVerts++; 1052 memcpy( outv, &ds->verts[ j ], sizeof( *outv ) ); 1053 outv->color[0] = 255; 1054 outv->color[1] = 255; 1055 outv->color[2] = 255; 1056 } 1057 1058 for ( j = 0 ; j < ds->numIndexes ; j++ ) { 1059 if ( numDrawIndexes == MAX_MAP_DRAW_INDEXES ) { 1060 Error( "MAX_MAP_DRAW_INDEXES" ); 1061 } 1062 drawIndexes[ numDrawIndexes ] = ds->indexes[ j ]; 1063 numDrawIndexes++; 1064 } 1065 } 1066 1067 //====================================================================== 1068 1069 /* 1070 ================== 1071 CreateFlareSurface 1072 1073 Light flares from surface lights become 1074 ================== 1075 */ 1076 void CreateFlareSurface( mapDrawSurface_t *faceDs ) { 1077 mapDrawSurface_t *ds; 1078 int i; 1079 1080 ds = AllocDrawSurf(); 1081 1082 if ( faceDs->shaderInfo->flareShader[0] ) { 1083 ds->shaderInfo = ShaderInfoForShader( faceDs->shaderInfo->flareShader ); 1084 } else { 1085 ds->shaderInfo = ShaderInfoForShader( "flareshader" ); 1086 } 1087 ds->flareSurface = qtrue; 1088 VectorCopy( faceDs->lightmapVecs[2], ds->lightmapVecs[2] ); 1089 1090 // find midpoint 1091 VectorClear( ds->lightmapOrigin ); 1092 for ( i = 0 ; i < faceDs->numVerts ; i++ ) { 1093 VectorAdd( ds->lightmapOrigin, faceDs->verts[i].xyz, ds->lightmapOrigin ); 1094 } 1095 VectorScale( ds->lightmapOrigin, 1.0/faceDs->numVerts, ds->lightmapOrigin ); 1096 1097 VectorMA( ds->lightmapOrigin, 2, ds->lightmapVecs[2], ds->lightmapOrigin ); 1098 1099 VectorCopy( faceDs->shaderInfo->color, ds->lightmapVecs[0] ); 1100 1101 // FIXME: fog 1102 } 1103 1104 /* 1105 ===================== 1106 FilterDrawsurfsIntoTree 1107 1108 Upon completion, all drawsurfs that actually generate a reference 1109 will have been emited to the bspfile arrays, and the references 1110 will have valid final indexes 1111 ===================== 1112 */ 1113 void FilterDrawsurfsIntoTree( entity_t *e, tree_t *tree ) { 1114 int i; 1115 mapDrawSurface_t *ds; 1116 int refs; 1117 int c_surfs, c_refs; 1118 1119 qprintf( "----- FilterDrawsurfsIntoTree -----\n"); 1120 1121 c_surfs = 0; 1122 c_refs = 0; 1123 for ( i = e->firstDrawSurf ; i < numMapDrawSurfs ; i++ ) { 1124 ds = &mapDrawSurfs[i]; 1125 1126 if ( !ds->numVerts && !ds->flareSurface ) { 1127 continue; 1128 } 1129 if ( ds->miscModel ) { 1130 refs = FilterMiscModelSurfIntoTree( ds, tree ); 1131 EmitModelSurf( ds ); 1132 } else if ( ds->patch ) { 1133 refs = FilterPatchSurfIntoTree( ds, tree ); 1134 EmitPatchSurf( ds ); 1135 } else if ( ds->flareSurface ) { 1136 refs = FilterFlareSurfIntoTree( ds, tree ); 1137 EmitFlareSurf( ds ); 1138 } else { 1139 refs = FilterFaceIntoTree( ds, tree ); 1140 // if ( ds->shaderInfo->value >= 1000 ) { // ds->shaderInfo->flareShader[0] ) { 1141 if ( ds->shaderInfo->flareShader[0] ) { 1142 CreateFlareSurface( ds ); 1143 } 1144 EmitPlanarSurf( ds ); 1145 } 1146 if ( refs > 0 ) { 1147 c_surfs++; 1148 c_refs += refs; 1149 } 1150 } 1151 qprintf( "%5i emited drawsurfs\n", c_surfs ); 1152 qprintf( "%5i references\n", c_refs ); 1153 qprintf( "%5i stripfaces\n", c_stripSurfaces ); 1154 qprintf( "%5i fanfaces\n", c_fanSurfaces ); 1155 } 1156 1157 1158