/** * @brief Chop up faces that are larger than we want in the surface cache */ static void SubdivideFace (node_t* node, face_t* f) { if (f->merged) return; /* special (non-surface cached) faces don't need subdivision */ const dBspTexinfo_t* tex = &curTile->texinfo[f->texinfo]; if (tex->surfaceFlags & SURF_WARP) return; for (int axis = 0; axis < 2; axis++) { while (1) { const winding_t* w = f->w; winding_t* frontw, *backw; float mins = 999999; float maxs = -999999; vec3_t temp; vec_t v; VectorCopy(tex->vecs[axis], temp); for (int i = 0; i < w->numpoints; i++) { v = DotProduct(w->p[i], temp); if (v < mins) mins = v; if (v > maxs) maxs = v; } /* no bsp subdivide for this winding? */ if (maxs - mins <= config.subdivideSize) break; /* split it */ c_subdivide++; v = VectorNormalize(temp); vec_t dist = (mins + config.subdivideSize - 16) / v; ClipWindingEpsilon(w, temp, dist, ON_EPSILON, &frontw, &backw); if (!frontw || !backw) Sys_Error("SubdivideFace: didn't split the polygon (texture: '%s')", tex->texture); f->split[0] = NewFaceFromFace(f); f->split[0]->w = frontw; f->split[0]->next = node->faces; node->faces = f->split[0]; f->split[1] = NewFaceFromFace(f); f->split[1]->w = backw; f->split[1]->next = node->faces; node->faces = f->split[1]; SubdivideFace(node, f->split[0]); SubdivideFace(node, f->split[1]); return; } } }
/* ================== CopyFacesToNode Do a final merge attempt, then subdivide the faces to surface cache size if needed. These are final faces that will be drawable in the game. Copies of these faces are further chopped up into the leafs, but they will reference these originals. ================== */ void CopyFacesToNode (node_t *node, surface_t *surf) { face_t **prevptr, *f, *newf; // merge as much as possible MergePlaneFaces (surf); // subdivide large faces prevptr = &surf->faces; while (1) { f = *prevptr; if (!f) break; SubdivideFace (f, prevptr); f = *prevptr; prevptr = &f->next; } // copy the faces to the node, and consider them the originals node->surfaces = NULL; node->faces = NULL; for (f=surf->faces ; f ; f=f->next) { if (f->contents != CONTENTS_SOLID) { newf = AllocFace (); *newf = *f; f->original = newf; newf->next = node->faces; node->faces = newf; c_nodefaces++; } } }
static void SubdivideNodeFaces (node_t* node) { face_t* f; for (f = node->faces; f; f = f->next) SubdivideFace(node, f); }
// actually, this has no users. void SubdivideFaces (surface_t *surfhead) { surface_t *surf; face_t *f , **prevptr; qprintf ("--- SubdivideFaces ---\n"); subdivides = 0; for (surf = surfhead ; surf ; surf = surf->next) { prevptr = &surf->faces; while (1) { f = *prevptr; if (!f) break; SubdivideFace (f, prevptr); f = *prevptr; prevptr = &f->next; } } qprintf ("%i faces added by subdivision\n", subdivides); }
/* ================== LinkNodeFaces Returns a duplicated list of all faces on surface ================== */ static face_t * LinkNodeFaces(surface_t *surface) { face_t *f, *newf, **prevptr; face_t *list = NULL; // subdivide large faces prevptr = &surface->faces; f = *prevptr; while (f) { SubdivideFace(f, prevptr); prevptr = &(*prevptr)->next; f = *prevptr; } // copy for (f = surface->faces; f; f = f->next) { nodefaces++; newf = AllocMem(FACE, 1, true); *newf = *f; f->original = newf; newf->next = list; list = newf; } return list; }
void LS_Surface::Subdivide() { subdivisionLevel++; // Linear subdivision of edges LS_EdgeList::iterator edge_itr = edges.begin(); int numEdges = edges.size(); int numVertices = vertices.size(); //TimeHandle t = TimeBegin(); for( int i = 0; i < numEdges; i++, edge_itr++ ) { // Only subdivide old edges (ones not attached to a new vertex) if ( (*edge_itr)->vertices[0]->creationLevel != subdivisionLevel && (*edge_itr)->vertices[1]->creationLevel != subdivisionLevel ) SubdivideEdge( *edge_itr ); } //printf("Subdivide Edge Time = %lf\n", TimeSlice(t)); // Create the new faces / Connect the new vertices LS_FaceList::iterator face_itr = faces.begin(); int orinumfaces = faces.size(); //t = TimeBegin(); for( int i = 0; i < orinumfaces; i++, face_itr++ ) { // Connect the new vertices into faces SubdivideFace( *face_itr ); } //printf("Subdivide Face Time = %lf\n", TimeSlice(t)); // Reposition new vertices LS_VertexList::iterator vertex_itr = vertices.begin(); //t = TimeBegin(); for( int i = 0; i < vertices.size(); i++, vertex_itr++ ) { RepositionVertex( *vertex_itr ); } //printf("Reposition Time = %lf\n", TimeSlice(t)); vertex_itr = vertices.begin(); //t = TimeBegin(); for( int i = 0; i < vertices.size(); i++, vertex_itr++ ) (*vertex_itr)->pos = (*vertex_itr)->newPos; //printf("Other Time = %lf\n", TimeSlice(t)); //UpdateNormals(); }