/** * @brief Chops the patch by a global grid */ static void SubdividePatch(patch_t* patch) { winding_t* w, *o1, *o2; vec3_t mins, maxs; vec3_t split; vec_t dist; int i; patch_t* newp; w = patch->winding; WindingBounds(w, mins, maxs); VectorClear(split); for (i = 0; i < 3; i++) { if (floor((mins[i] + 1) / PATCH_SUBDIVIDE) < floor((maxs[i] - 1) / PATCH_SUBDIVIDE)) { split[i] = 1.0; break; } } /* no splitting needed */ if (i == 3) return; /* split the winding */ dist = PATCH_SUBDIVIDE * (1 + floor((mins[i] + 1) / PATCH_SUBDIVIDE)); ClipWindingEpsilon(w, split, dist, ON_EPSILON, &o1, &o2); /* create a new patch */ newp = Mem_AllocType(patch_t); newp->next = patch->next; patch->next = newp; patch->winding = o1; newp->winding = o2; FinishSubdividePatch(patch, newp); SubdividePatch(patch); SubdividePatch(newp); }
/** * @brief Iterate all of the head face patches, subdividing them as necessary. */ void SubdividePatches (void) { int i; for (i = 0; i < MAX_MAP_FACES; i++) { patch_t* p = face_patches[i]; if (p) /* break it up */ SubdividePatch(p); } }
/* ============= SubdividePatches ============= */ void SubdividePatches (void) { int i, num; num = num_patches; // because the list will grow for (i=0 ; i<num ; i++) { patch_t *patch = patches + i; SubdividePatch( patch ); } qprintf ("%i patches after subdivision\n", num_patches); }
/* * @brief Iterate all of the head face patches, subdividing them as necessary. */ void SubdividePatches(void) { int32_t i; for (i = 0; i < MAX_BSP_FACES; i++) { const d_bsp_face_t *f = &d_bsp.faces[i]; patch_t *p = face_patches[i]; if (p && !IsSky(f)) // break it up SubdividePatch(p); } }
/* ============= SubdividePatch ============= */ void SubdividePatch (patch_t *patch) { winding_t *w, *o1, *o2; vec3_t total; vec3_t split; vec_t dist; vec_t widest = -1; int i, j, widest_axis = -1; int subdivide_it = 0; vec_t v; patch_t *newp; w = patch->winding; VectorSubtract (patch->maxs, patch->mins, total); for (i=0 ; i<3 ; i++) { if ( total[i] > widest ) { widest_axis = i; widest = total[i]; } if ( total[i] > patch->chop || (patch->face_maxs[i] == patch->maxs[i] || patch->face_mins[i] == patch->mins[i] ) && total[i] > minchop ) { subdivide_it = 1; } } if ( subdivide_it ) { // // split the winding // VectorCopy (vec3_origin, split); split[widest_axis] = 1; dist = (patch->mins[widest_axis] + patch->maxs[widest_axis])*0.5f; ClipWinding (w, split, dist, &o1, &o2); // // create a new patch // if (num_patches == MAX_PATCHES) Error ("MAX_PATCHES"); newp = &patches[num_patches]; newp->next = patch->next; patch->next = newp; patch->winding = o1; newp->winding = o2; VectorCopy( patch->face_mins, newp->face_mins ); VectorCopy( patch->face_maxs, newp->face_maxs ); VectorCopy( patch->baselight, newp->baselight ); VectorCopy( patch->directlight, newp->directlight ); VectorCopy( patch->totallight, newp->totallight ); VectorCopy( patch->reflectivity, newp->reflectivity ); newp->plane = patch->plane; newp->sky = patch->sky; newp->chop = patch->chop; newp->faceNumber = patch->faceNumber; num_patches++; patch->area = WindingArea (patch->winding); newp->area = WindingArea (newp->winding); WindingCenter (patch->winding, patch->origin); WindingCenter (newp->winding, newp->origin); #ifdef PHONG_NORMAL_PATCHES // This seems to be a bad idea for some reason. Leave it turned off for now. // Set (Copy or Calculate) the synthetic normal for these new patches VectorAdd (patch->origin, patch->plane->normal, patch->origin); VectorAdd (newp->origin, newp->plane->normal, newp->origin); GetPhongNormal( patch->faceNumber, patch->origin, patch->normal ); GetPhongNormal( newp->faceNumber, newp->origin, newp->normal ); VectorSubtract( patch->origin, patch->plane->normal, patch->origin); VectorSubtract( newp->origin, newp->plane->normal, newp->origin); #else VectorCopy( patch->plane->normal, patch->normal ); VectorCopy( newp->plane->normal, newp->normal ); #endif VectorAdd( patch->origin, patch->normal, patch->origin ); VectorAdd( newp->origin, newp->normal, newp->origin ); WindingBounds(patch->winding, patch->mins, patch->maxs); WindingBounds(newp->winding, newp->mins, newp->maxs); // Subdivide patch even more if on the edge of the face; this is a hack! VectorSubtract (patch->maxs, patch->mins, total); if ( total[0] < patch->chop && total[1] < patch->chop && total[2] < patch->chop ) for ( i=0; i<3; i++ ) if ( (patch->face_maxs[i] == patch->maxs[i] || patch->face_mins[i] == patch->mins[i] ) && total[i] > minchop ) { patch->chop = max( minchop, patch->chop / 2 ); break; } SubdividePatch (patch); // Subdivide patch even more if on the edge of the face; this is a hack! VectorSubtract (newp->maxs, newp->mins, total); if ( total[0] < newp->chop && total[1] < newp->chop && total[2] < newp->chop ) for ( i=0; i<3; i++ ) if ( (newp->face_maxs[i] == newp->maxs[i] || newp->face_mins[i] == newp->mins[i] ) && total[i] > minchop ) { newp->chop = max( minchop, newp->chop / 2 ); break; } SubdividePatch (newp); } }
/* ============= SubdividePatch Chops the patch only if its local bounds exceed the max size ============= */ void SubdividePatch( patch_t *patch ){ winding_t *w, *o1, *o2; vec3_t mins, maxs, total; vec3_t split; vec_t dist; int i, j; vec_t v; patch_t *newp; w = patch->winding; mins[0] = mins[1] = mins[2] = 99999; maxs[0] = maxs[1] = maxs[2] = -99999; for ( i = 0 ; i < w->numpoints ; i++ ) { for ( j = 0 ; j < 3 ; j++ ) { v = w->p[i][j]; if ( v < mins[j] ) { mins[j] = v; } if ( v > maxs[j] ) { maxs[j] = v; } } } VectorSubtract( maxs, mins, total ); for ( i = 0 ; i < 3 ; i++ ) if ( total[i] > ( subdiv + 1 ) ) { break; } if ( i == 3 ) { // no splitting needed return; } // // split the winding // VectorCopy( vec3_origin, split ); split[i] = 1; dist = ( mins[i] + maxs[i] ) * 0.5; ClipWindingEpsilon( w, split, dist, ON_EPSILON, &o1, &o2 ); // // create a new patch // if ( num_patches == MAX_PATCHES ) { Error( "MAX_PATCHES" ); } newp = &patches[num_patches]; num_patches++; newp->next = patch->next; patch->next = newp; patch->winding = o1; newp->winding = o2; FinishSplit( patch, newp ); SubdividePatch( patch ); SubdividePatch( newp ); }