home *** CD-ROM | disk | FTP | other *** search
/ PC PowerPlay 58 / pcpp58a.iso / extras / quake 3 source / Q3A_ToolSource.exe / Main / patch.c < prev    next >
Encoding:
C/C++ Source or Header  |  2001-01-02  |  6.0 KB  |  266 lines

  1. #include "qbsp.h"
  2.  
  3.  
  4. void PrintCtrl( vec3_t ctrl[9] ) {
  5.     int        i, j;
  6.  
  7.     for ( i = 0 ; i < 3 ; i++ ) {
  8.         for ( j = 0 ; j < 3 ; j++ ) {
  9.             _printf("(%5.2f %5.2f %5.2f) ", ctrl[i*3+j][0], ctrl[i*3+j][1], ctrl[i*3+j][2] );
  10.         }
  11.         _printf("\n");
  12.     }
  13. }
  14.  
  15. /*
  16. ================
  17. DrawSurfaceForMesh
  18. ================
  19. */
  20. mapDrawSurface_t    *DrawSurfaceForMesh( mesh_t *m ) {
  21.     mapDrawSurface_t    *ds;
  22.     int                i, j;
  23.     mesh_t            *copy;
  24.  
  25.     // to make valid normals for patches with degenerate edges,
  26.     // we need to make a copy of the mesh and put the aproximating
  27.     // points onto the curve
  28.     copy = CopyMesh( m );
  29.     PutMeshOnCurve( *copy );
  30.     MakeMeshNormals( *copy );
  31.     for ( j = 0 ; j < m->width ; j++ ) {
  32.         for ( i = 0 ; i < m->height ; i++ ) {
  33.             VectorCopy( copy->verts[i*m->width+j].normal, m->verts[i*m->width+j].normal );
  34.         }
  35.     }
  36.     FreeMesh( copy );
  37.  
  38.     ds = AllocDrawSurf();
  39.     ds->mapBrush = NULL;
  40.     ds->side = NULL;
  41.  
  42.     ds->patch = qtrue;
  43.     ds->patchWidth = m->width;
  44.     ds->patchHeight = m->height;
  45.     ds->numVerts = ds->patchWidth * ds->patchHeight;
  46.     ds->verts = malloc( ds->numVerts * sizeof( *ds->verts ) );
  47.     memcpy( ds->verts, m->verts, ds->numVerts * sizeof( *ds->verts ) );
  48.  
  49.     ds->lightmapNum = -1;
  50.     ds->fogNum = -1;
  51.  
  52.     return ds;
  53. }
  54.  
  55. /*
  56. =================
  57. ParsePatch
  58.  
  59. Creates a mapDrawSurface_t from the patch text
  60. =================
  61. */
  62. void ParsePatch( void ) {
  63.     vec_t        info[5];
  64.     int            i, j;
  65.     parseMesh_t    *pm;
  66.     char        texture[MAX_QPATH];
  67.     char        shader[MAX_QPATH];
  68.     mesh_t        m;
  69.     drawVert_t    *verts;
  70.   epair_t *ep;
  71.  
  72.     MatchToken( "{" );
  73.  
  74.     // get texture
  75.     GetToken (qtrue);
  76.     strcpy( texture, token );
  77.  
  78.     // save the shader name for retexturing
  79.     if ( numMapIndexedShaders == MAX_MAP_BRUSHSIDES ) {
  80.         Error( "MAX_MAP_BRUSHSIDES" );
  81.     }
  82.     strcpy( mapIndexedShaders[numMapIndexedShaders], texture );
  83.     numMapIndexedShaders++;
  84.  
  85.  
  86.     Parse1DMatrix( 5, info );
  87.     m.width = info[0];
  88.     m.height = info[1];
  89.     m.verts = verts = malloc( m.width * m.height * sizeof( m.verts[0] ) );
  90.  
  91.     if ( m.width < 0 || m.width > MAX_PATCH_SIZE
  92.         || m.height < 0 || m.height > MAX_PATCH_SIZE ) {
  93.         Error("ParsePatch: bad size");
  94.     }
  95.  
  96.     MatchToken( "(" );
  97.     for ( j = 0 ; j < m.width ; j++ ) {
  98.         MatchToken( "(" );
  99.         for ( i = 0 ; i < m.height ; i++ ) {
  100.             Parse1DMatrix( 5, verts[i*m.width+j].xyz );
  101.         }
  102.         MatchToken( ")" );
  103.     }
  104.     MatchToken( ")" );
  105.  
  106.   // if brush primitives format, we may have some epairs to ignore here
  107.   GetToken(qtrue);
  108.   if (g_bBrushPrimit!=BPRIMIT_OLDBRUSHES && strcmp(token,"}"))
  109.   {
  110.     // NOTE: we leak that!
  111.     ep = ParseEpair();
  112.   }
  113.   else
  114.     UnGetToken();
  115.  
  116.     MatchToken( "}" );
  117.     MatchToken( "}" );
  118.  
  119.     if ( noCurveBrushes ) {
  120.         return;
  121.     }
  122.  
  123.     // find default flags and values
  124.     pm = malloc( sizeof( *pm ) );
  125.     memset( pm, 0, sizeof( *pm ) );
  126.  
  127.     sprintf( shader, "textures/%s", texture );
  128.     pm->shaderInfo = ShaderInfoForShader( shader ); 
  129.     pm->mesh = m;
  130.  
  131.     // link to the entity
  132.     pm->next = mapent->patches;
  133.     mapent->patches = pm;
  134. }
  135.  
  136.  
  137. void GrowGroup_r( int patchNum, int patchCount, const byte *bordering, byte *group ) {
  138.     int        i;
  139.     const byte *row;
  140.  
  141.     if ( group[patchNum] ) {
  142.         return;
  143.     }
  144.     group[patchNum] = 1;
  145.     row = bordering + patchNum * patchCount;
  146.     for ( i = 0 ; i < patchCount ; i++ ) {
  147.         if ( row[i] ) {
  148.             GrowGroup_r( i, patchCount, bordering, group );
  149.         }
  150.     }
  151. }
  152.  
  153.  
  154. /*
  155. =====================
  156. PatchMapDrawSurfs
  157.  
  158. Any patches that share an edge need to choose their
  159. level of detail as a unit, otherwise the edges would
  160. pull apart.
  161. =====================
  162. */
  163. void PatchMapDrawSurfs( entity_t *e ) {
  164.     parseMesh_t            *pm;
  165.     parseMesh_t            *check, *scan;
  166.     mapDrawSurface_t    *ds;
  167.     int                    patchCount, groupCount;
  168.     int                    i, j, k, l, c1, c2;
  169.     drawVert_t            *v1, *v2;
  170.     vec3_t                bounds[2];
  171.     byte                *bordering;
  172.     parseMesh_t            *meshes[MAX_MAP_DRAW_SURFS];
  173.     qboolean            grouped[MAX_MAP_DRAW_SURFS];
  174.     byte                group[MAX_MAP_DRAW_SURFS];
  175.  
  176.     qprintf( "----- PatchMapDrawSurfs -----\n" );
  177.  
  178.     patchCount = 0;
  179.     for ( pm = e->patches ; pm ; pm = pm->next  ) {
  180.         meshes[patchCount] = pm;
  181.         patchCount++;
  182.     }
  183.  
  184.     if ( !patchCount ) {
  185.         return;
  186.     }
  187.     bordering = malloc( patchCount * patchCount );
  188.     memset( bordering, 0, patchCount * patchCount );
  189.  
  190.     // build the bordering matrix
  191.     for ( k = 0 ; k < patchCount ; k++ ) {
  192.         bordering[k*patchCount+k] = 1;
  193.  
  194.         for ( l = k+1 ; l < patchCount ; l++ ) {
  195.             check = meshes[k];
  196.             scan = meshes[l];
  197.             c1 = scan->mesh.width * scan->mesh.height;
  198.             v1 = scan->mesh.verts;
  199.  
  200.             for ( i = 0 ; i < c1 ; i++, v1++ ) {
  201.                 c2 = check->mesh.width * check->mesh.height;
  202.                 v2 = check->mesh.verts;
  203.                 for ( j = 0 ; j < c2 ; j++, v2++ ) {
  204.                     if ( fabs( v1->xyz[0] - v2->xyz[0] ) < 1.0
  205.                         && fabs( v1->xyz[1] - v2->xyz[1] ) < 1.0
  206.                         && fabs( v1->xyz[2] - v2->xyz[2] ) < 1.0 ) {
  207.                         break;
  208.                     }
  209.                 }
  210.                 if ( j != c2 ) {
  211.                     break;
  212.                 }
  213.             }
  214.             if ( i != c1 ) {
  215.                 // we have a connection
  216.                 bordering[k*patchCount+l] =
  217.                 bordering[l*patchCount+k] = 1;
  218.             } else {
  219.                 // no connection
  220.                 bordering[k*patchCount+l] =
  221.                 bordering[l*patchCount+k] = 0;
  222.             }
  223.  
  224.         }
  225.     }
  226.  
  227.     // build groups
  228.     memset( grouped, 0, sizeof(grouped) );
  229.     groupCount = 0;
  230.     for ( i = 0 ; i < patchCount ; i++ ) {
  231.         if ( !grouped[i] ) {
  232.             groupCount++;
  233.         }
  234.  
  235.         // recursively find all patches that belong in the same group
  236.         memset( group, 0, patchCount );
  237.         GrowGroup_r( i, patchCount, bordering, group );
  238.  
  239.         // bound them
  240.         ClearBounds( bounds[0], bounds[1] );
  241.         for ( j = 0 ; j < patchCount ; j++ ) {
  242.             if ( group[j] ) {
  243.                 grouped[j] = qtrue;
  244.                 scan = meshes[j];
  245.                 c1 = scan->mesh.width * scan->mesh.height;
  246.                 v1 = scan->mesh.verts;
  247.                 for ( k = 0 ; k < c1 ; k++, v1++ ) {
  248.                     AddPointToBounds( v1->xyz, bounds[0], bounds[1] );
  249.                 }
  250.             }
  251.         }
  252.  
  253.         // create drawsurf
  254.         scan = meshes[i];
  255.         scan->grouped = qtrue;
  256.         ds = DrawSurfaceForMesh( &scan->mesh );
  257.         ds->shaderInfo = scan->shaderInfo;
  258.         VectorCopy( bounds[0], ds->lightmapVecs[0] );
  259.         VectorCopy( bounds[1], ds->lightmapVecs[1] );
  260.     }
  261.  
  262.     qprintf( "%5i patches\n", patchCount );
  263.     qprintf( "%5i patch LOD groups\n", groupCount );
  264. }
  265.  
  266.