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