/* ================= FindFloatPlane changed to allow a number of test points to be supplied that must be within an epsilon distance of the plane ================= */ int FindFloatPlane( vec3_t normal, vec_t dist, int numPoints, vec3_t *points ) { int i, j, hash, h; plane_t *p; vec_t d; SnapPlane( normal, &dist ); hash = (PLANE_HASHES - 1) & (int)fabs( dist ); for( i = -1; i <= 1; i++ ) { h = (hash + i) & (PLANE_HASHES - 1); for( p = planehash[ h ]; p != NULL; p = p->hash_chain ) { if( !PlaneEqual( p, normal, dist )) continue; // test supplied points against this plane for( j = 0; j < numPoints; j++ ) { d = DotProduct( points[j], normal ) - dist; if( fabs( d ) > distanceEpsilon ) break; } if( j >= numPoints ) return p - mapplanes; } } // none found, so create a new one return CreateNewFloatPlane( normal, dist ); }
int FindFloatPlane( vec3_t innormal, vec_t dist, int numPoints, vec3_t *points ) // NOTE: this has a side effect on the normal. Good or bad? #ifdef USE_HASHING { int i, j, hash, h; int pidx; plane_t *p; vec_t d; vec3_t normal; VectorCopy(innormal, normal); #if Q3MAP2_EXPERIMENTAL_SNAP_PLANE_FIX SnapPlaneImproved(normal, &dist, numPoints, (const vec3_t *) points); #else SnapPlane( normal, &dist ); #endif /* hash the plane */ hash = (PLANE_HASHES - 1) & (int) fabs( dist ); /* search the border bins as well */ for( i = -1; i <= 1; i++ ) { h = (hash + i) & (PLANE_HASHES - 1); for( pidx = planehash[ h ] - 1; pidx != -1; pidx = mapplanes[pidx].hash_chain - 1 ) { p = &mapplanes[pidx]; /* do standard plane compare */ if( !PlaneEqual( p, normal, dist ) ) continue; /* ydnar: uncomment the following line for old-style plane finding */ //% return p - mapplanes; /* ydnar: test supplied points against this plane */ for( j = 0; j < numPoints; j++ ) { // NOTE: When dist approaches 2^16, the resolution of 32 bit floating // point number is greatly decreased. The distanceEpsilon cannot be // very small when world coordinates extend to 2^16. Making the // dot product here in 64 bit land will not really help the situation // because the error will already be carried in dist. d = DotProduct( points[ j ], p->normal ) - p->dist; d = fabs(d); if (d != 0.0 && d >= distanceEpsilon) break; // Point is too far from plane. } /* found a matching plane */ if( j >= numPoints ) return p - mapplanes; } } /* none found, so create a new one */ return CreateNewFloatPlane( normal, dist ); }
int FindFloatPlane (vec3_t normal, vec_t dist) { int i; plane_t *p; SnapPlane (normal, &dist); for (i=0, p=mapplanes ; i<nummapplanes ; i++, p++) { if (PlaneEqual (p, normal, dist)) return i; } return CreateNewFloatPlane (normal, dist); }
int FindFloatPlane( vec3_t normal, vec_t dist, int numPoints, vec3_t *points ) #ifdef USE_HASHING { int i, j, hash, h; plane_t *p; vec_t d; /* hash the plane */ SnapPlane( normal, &dist ); hash = ( PLANE_HASHES - 1 ) & (int) fabs( dist ); /* search the border bins as well */ for ( i = -1; i <= 1; i++ ) { h = ( hash + i ) & ( PLANE_HASHES - 1 ); for ( p = planehash[ h ]; p != NULL; p = p->hash_chain ) { /* do standard plane compare */ if ( !PlaneEqual( p, normal, dist ) ) { continue; } /* ydnar: uncomment the following line for old-style plane finding */ //% return p - mapplanes; /* ydnar: test supplied points against this plane */ for ( j = 0; j < numPoints; j++ ) { d = DotProduct( points[ j ], normal ) - dist; if ( fabs( d ) > distanceEpsilon ) { break; } } /* found a matching plane */ if ( j >= numPoints ) { return p - mapplanes; } } } /* none found, so create a new one */ return CreateNewFloatPlane( normal, dist ); }
/* * FindFloatPlane */ int FindFloatPlane(vec3_t normal, vec_t dist) { int i; const map_plane_t *p; int hash; SnapPlane(normal, &dist); hash = (int) fabs(dist) / 8; hash &= (PLANE_HASHES - 1); // search the border bins as well for (i = -1; i <= 1; i++) { const int h = (hash + i) & (PLANE_HASHES - 1); for (p = plane_hash[h]; p; p = p->hash_chain) { if (PlaneEqual(p, normal, dist)) return p - map_planes; } } return CreateNewFloatPlane(normal, dist); }
/* * @brief */ int32_t FindPlane(vec3_t normal, dvec_t dist) { int32_t i; SnapPlane(normal, &dist); const uint16_t hash = ((uint32_t) fabsl(dist)) & (PLANE_HASHES - 1); // search the border bins as well for (i = -1; i <= 1; i++) { const uint16_t h = (hash + i) & (PLANE_HASHES - 1); const map_plane_t *p = plane_hash[h]; while (p) { if (PlaneEqual(p, normal, dist)) { return p - map_planes; } p = p->hash_chain; } } return CreateNewFloatPlane(normal, dist); }
uint16_t FindOrCreateFloatPlane (vec3_t normal, vec_t dist) { int i; plane_t* p; int hash; SnapPlane(normal, &dist); hash = GetPlaneHashValueForDistance(dist); /* search the border bins as well */ for (i = -1; i <= 1; i++) { const int h = (hash + i) & (PLANE_HASHES - 1); for (p = planehash[h]; p; p = p->hash_chain) { if (PlaneEqual(p, normal, dist)) { const intptr_t index = p - mapplanes; return (int16_t)index; } } } return CreateNewFloatPlane(normal, dist); }
/* ================= AddBrushBevels adds any additional planes necessary to allow the brush being built to be expanded against axial bounding boxes 2003-01-20: added mr.Elusive fixes ================= */ void AddBrushBevels( void ) { int axis, dir; int i, j, k, l, order = 0; side_t sidetemp; side_t *s, *s2; winding_t *w, *w2; vec3_t normal; float dist; vec3_t vec, vec2; float d, minBack; // add the axial planes for( axis = 0; axis < 3; axis++ ) { for( dir = -1; dir <= 1; dir += 2, order++ ) { // see if the plane is allready present for( i = 0, s = buildBrush->sides; i < buildBrush->numsides; i++, s++ ) { if( mapplanes[s->planenum].normal[axis] == dir ) break; } if( i == buildBrush->numsides ) { // add a new side if( buildBrush->numsides == MAX_BUILD_SIDES ) Sys_Break( "Entity %i, Brush %i MAX_BUILD_SIDES\n", buildBrush->entityNum, buildBrush->brushNum ); Mem_Set( s, 0, sizeof( *s )); buildBrush->numsides++; VectorClear (normal); normal[axis] = dir; if( dir == 1 ) { // adding bevel plane snapping for fewer bsp planes if( bevelSnap > 0 ) dist = floor( buildBrush->maxs[axis] / bevelSnap ) * bevelSnap; else dist = buildBrush->maxs[axis]; } else { // adding bevel plane snapping for fewer bsp planes if( bevelSnap > 0 ) dist = -ceil( buildBrush->mins[axis] / bevelSnap ) * bevelSnap; else dist = -buildBrush->mins[axis]; } s->planenum = FindFloatPlane( normal, dist, 0, NULL ); s->contentFlags = buildBrush->sides[0].contentFlags; s->bevel = true; c_boxbevels++; } // if the plane is not in it canonical order, swap it if( i != order ) { sidetemp = buildBrush->sides[order]; buildBrush->sides[order] = buildBrush->sides[i]; buildBrush->sides[i] = sidetemp; } } } // add the edge bevels if( buildBrush->numsides == 6 ) return; // pure axial // test the non-axial plane edges for( i = 6; i < buildBrush->numsides; i++ ) { s = buildBrush->sides + i; w = s->winding; if( !w ) continue; for( j = 0; j < w->numpoints; j++ ) { k = (j+1)%w->numpoints; VectorSubtract( w->p[j], w->p[k], vec ); if( VectorNormalizeLength( vec ) < 0.5f ) continue; SnapNormal( vec ); for( k = 0; k < 3; k++ ) { if( vec[k] == -1.0f || vec[k] == 1.0f || (vec[k] == 0.0f && vec[(k+1)%3] == 0.0f)) break; // axial } if( k != 3 ) continue; // only test non-axial edges // try the six possible slanted axials from this edge for( axis = 0; axis < 3; axis++ ) { for( dir = -1; dir <= 1; dir += 2 ) { // construct a plane VectorClear( vec2 ); vec2[axis] = dir; CrossProduct( vec, vec2, normal ); if( VectorNormalizeLength( normal ) < 0.5f ) continue; dist = DotProduct( w->p[j], normal ); // if all the points on all the sides are // behind this plane, it is a proper edge bevel for( k = 0; k < buildBrush->numsides; k++ ) { // if this plane has allready been used, skip it if( PlaneEqual( &mapplanes[buildBrush->sides[k].planenum], normal, dist )) break; w2 = buildBrush->sides[k].winding; if( !w2 ) continue; minBack = 0.0f; for( l = 0; l < w2->numpoints; l++ ) { d = DotProduct( w2->p[l], normal ) - dist; if( d > 0.1f ) break; // point in front if( d < minBack ) minBack = d; } // if some point was at the front if( l != w2->numpoints ) break; // if no points at the back then the winding is on the bevel plane if( minBack > -0.1f ) break; } if( k != buildBrush->numsides ) continue; // wasn't part of the outer hull // add this plane if( buildBrush->numsides == MAX_BUILD_SIDES ) Sys_Break( "Entity %i, Brush %i MAX_BUILD_SIDES\n", buildBrush->entityNum, buildBrush->brushNum ); s2 = &buildBrush->sides[buildBrush->numsides]; buildBrush->numsides++; Mem_Set( s2, 0, sizeof( *s2 ) ); s2->planenum = FindFloatPlane( normal, dist, 1, &w->p[j] ); s2->contentFlags = buildBrush->sides[0].contentFlags; s2->bevel = true; c_edgebevels++; } } } } }
/* ================= AddBrushBevels Adds any additional planes necessary to allow the brush to be expanded against axial bounding boxes ================= */ void AddBrushBevels (mapbrush_t *b) { int axis, dir; int i, j, k, l, order; side_t sidetemp; brush_texture_t tdtemp; side_t *s, *s2; vec3_t normal; float dist; winding_t *w, *w2; vec3_t vec, vec2; float d; // // add the axial planes // order = 0; for (axis=0 ; axis <3 ; axis++) { for (dir=-1 ; dir <= 1 ; dir+=2, order++) { // see if the plane is allready present for (i=0, s=b->original_sides ; i<b->numsides ; i++,s++) { if (mapplanes[s->planenum].normal[axis] == dir) break; } if (i == b->numsides) { // add a new side if (nummapbrushsides == MAX_MAP_BRUSHSIDES) Error ("MAX_MAP_BRUSHSIDES"); nummapbrushsides++; b->numsides++; VectorClear (normal); normal[axis] = dir; if (dir == 1) dist = b->maxs[axis]; else dist = -b->mins[axis]; s->planenum = FindFloatPlane (normal, dist); s->texinfo = b->original_sides[0].texinfo; s->contents = b->original_sides[0].contents; s->bevel = true; c_boxbevels++; } // if the plane is not in it canonical order, swap it if (i != order) { sidetemp = b->original_sides[order]; b->original_sides[order] = b->original_sides[i]; b->original_sides[i] = sidetemp; j = b->original_sides - brushsides; tdtemp = side_brushtextures[j+order]; side_brushtextures[j+order] = side_brushtextures[j+i]; side_brushtextures[j+i] = tdtemp; } } } // // add the edge bevels // if (b->numsides == 6) return; // pure axial // test the non-axial plane edges for (i=6 ; i<b->numsides ; i++) { s = b->original_sides + i; w = s->winding; if (!w) continue; for (j=0 ; j<w->numpoints ; j++) { k = (j+1)%w->numpoints; VectorSubtract (w->p[j], w->p[k], vec); if (VectorNormalize (vec, vec) < 0.5) continue; SnapVector (vec); for (k=0 ; k<3 ; k++) if ( vec[k] == -1 || vec[k] == 1) break; // axial if (k != 3) continue; // only test non-axial edges // try the six possible slanted axials from this edge for (axis=0 ; axis <3 ; axis++) { for (dir=-1 ; dir <= 1 ; dir+=2) { // construct a plane VectorClear (vec2); vec2[axis] = dir; CrossProduct (vec, vec2, normal); if (VectorNormalize (normal, normal) < 0.5) continue; dist = DotProduct (w->p[j], normal); // if all the points on all the sides are // behind this plane, it is a proper edge bevel for (k=0 ; k<b->numsides ; k++) { // if this plane has allready been used, skip it if (PlaneEqual (&mapplanes[b->original_sides[k].planenum] , normal, dist) ) break; w2 = b->original_sides[k].winding; if (!w2) continue; for (l=0 ; l<w2->numpoints ; l++) { d = DotProduct (w2->p[l], normal) - dist; if (d > 0.1) break; // point in front } if (l != w2->numpoints) break; } if (k != b->numsides) continue; // wasn't part of the outer hull // add this plane if (nummapbrushsides == MAX_MAP_BRUSHSIDES) Error ("MAX_MAP_BRUSHSIDES"); nummapbrushsides++; s2 = &b->original_sides[b->numsides]; s2->planenum = FindFloatPlane (normal, dist); s2->texinfo = b->original_sides[0].texinfo; s2->contents = b->original_sides[0].contents; s2->bevel = true; c_edgebevels++; b->numsides++; } } } } }
/* * @brief Adds any additional planes necessary to allow the brush to be expanded * against axial bounding boxes */ static void AddBrushBevels(map_brush_t * b) { int32_t axis, dir; int32_t i, j, k, l, order; side_t sidetemp; map_brush_texture_t tdtemp; side_t *s, *s2; vec3_t normal; vec_t dist; winding_t *w, *w2; vec3_t vec, vec2; vec_t d; // add the axial planes order = 0; for (axis = 0; axis < 3; axis++) { for (dir = -1; dir <= 1; dir += 2, order++) { // see if the plane is already present for (i = 0, s = b->original_sides; i < b->num_sides; i++, s++) { if (map_planes[s->plane_num].normal[axis] == dir) break; } if (i == b->num_sides) { // add a new side if (num_map_brush_sides == MAX_BSP_BRUSH_SIDES) Com_Error(ERR_FATAL, "MAX_BSP_BRUSH_SIDES\n"); num_map_brush_sides++; b->num_sides++; VectorClear(normal); normal[axis] = dir; if (dir == 1) dist = b->maxs[axis]; else dist = -b->mins[axis]; s->plane_num = FindPlane(normal, dist); s->texinfo = b->original_sides[0].texinfo; s->contents = b->original_sides[0].contents; s->bevel = true; c_box_bevels++; } // if the plane is not in it canonical order, swap it if (i != order) { sidetemp = b->original_sides[order]; b->original_sides[order] = b->original_sides[i]; b->original_sides[i] = sidetemp; j = b->original_sides - map_brush_sides; tdtemp = map_brush_textures[j + order]; map_brush_textures[j + order] = map_brush_textures[j + i]; map_brush_textures[j + i] = tdtemp; } } } // add the edge bevels if (b->num_sides == 6) return; // pure axial // test the non-axial plane edges for (i = 6; i < b->num_sides; i++) { s = b->original_sides + i; w = s->winding; if (!w) continue; for (j = 0; j < w->num_points; j++) { k = (j + 1) % w->num_points; VectorSubtract(w->points[j], w->points[k], vec); if (VectorNormalize(vec) < 0.5) { continue; } SnapNormal(vec); for (k = 0; k < 3; k++) { if (vec[k] == -1.0 || vec[k] == 1.0 || (vec[k] == 0.0 && vec[(k + 1) % 3] == 0.0)) { break; // axial } } if (k != 3) { continue; // only test non-axial edges } // try the six possible slanted axials from this edge for (axis = 0; axis < 3; axis++) { for (dir = -1; dir <= 1; dir += 2) { // construct a plane VectorClear(vec2); vec2[axis] = dir; CrossProduct(vec, vec2, normal); if (VectorNormalize(normal) < 0.5) continue; dist = DotProduct(w->points[j], normal); // if all the points on all the sides are // behind this plane, it is a proper edge bevel for (k = 0; k < b->num_sides; k++) { vec_t minBack; // if this plane has already been used, skip it if (PlaneEqual(&map_planes[b->original_sides[k].plane_num], normal, dist)) break; w2 = b->original_sides[k].winding; if (!w2) continue; minBack = 0.0f; for (l = 0; l < w2->num_points; l++) { d = DotProduct(w2->points[l], normal) - dist; if (d > 0.1) break; // point in front if (d < minBack) minBack = d; } // if some point was at the front if (l != w2->num_points) break; // if no points at the back then the winding is on the // bevel plane if (minBack > -0.1f) break; } if (k != b->num_sides) continue; // wasn't part of the outer hull // add this plane if (num_map_brush_sides == MAX_BSP_BRUSH_SIDES) Com_Error(ERR_FATAL, "MAX_BSP_BRUSH_SIDES\n"); s2 = &b->original_sides[b->num_sides++]; s2->plane_num = FindPlane(normal, dist); s2->texinfo = b->original_sides[0].texinfo; s2->contents = b->original_sides[0].contents; s2->bevel = true; num_map_brush_sides++; c_edge_bevels++; } } } } }
/** * @brief Adds any additional planes necessary to allow the brush to be expanded * against axial bounding boxes */ static void AddBrushBevels (mapbrush_t* b) { int axis, dir; int i, l, order; vec3_t normal; /* add the axial planes */ order = 0; for (axis = 0; axis < 3; axis++) { for (dir = -1; dir <= 1; dir += 2, order++) { side_t* s; /* see if the plane is already present */ for (i = 0, s = b->original_sides; i < b->numsides; i++, s++) { if (mapplanes[s->planenum].normal[axis] == dir) break; } if (i == b->numsides) { /* add a new side */ float dist; if (nummapbrushsides == MAX_MAP_BRUSHSIDES) Sys_Error("MAX_MAP_BRUSHSIDES (%i)", nummapbrushsides); nummapbrushsides++; b->numsides++; VectorClear(normal); normal[axis] = dir; if (dir == 1) dist = b->mbBox.maxs[axis]; else dist = -b->mbBox.mins[axis]; s->planenum = FindOrCreateFloatPlane(normal, dist); s->texinfo = b->original_sides[0].texinfo; s->contentFlags = b->original_sides[0].contentFlags; s->bevel = true; c_boxbevels++; } /* if the plane is not in it canonical order, swap it */ if (i != order) { const ptrdiff_t index = b->original_sides - brushsides; side_t sidetemp = b->original_sides[order]; brush_texture_t tdtemp = side_brushtextures[index + order]; b->original_sides[order] = b->original_sides[i]; b->original_sides[i] = sidetemp; side_brushtextures[index + order] = side_brushtextures[index + i]; side_brushtextures[index + i] = tdtemp; } } } /* add the edge bevels */ if (b->numsides == 6) return; /* pure axial */ /* test the non-axial plane edges */ for (i = 6; i < b->numsides; i++) { side_t* s = b->original_sides + i; winding_t* w = s->winding; if (!w) continue; for (int j = 0; j < w->numpoints; j++) { int k = (j + 1) % w->numpoints; vec3_t vec; VectorSubtract(w->p[j], w->p[k], vec); if (VectorNormalize(vec) < 0.5) continue; SnapVector(vec); for (k = 0; k < 3; k++) if (vec[k] == -1 || vec[k] == 1 || (vec[k] == 0.0f && vec[(k + 1) % 3] == 0.0f)) break; /* axial */ if (k != 3) continue; /* only test non-axial edges */ /* try the six possible slanted axials from this edge */ for (axis = 0; axis < 3; axis++) { for (dir = -1; dir <= 1; dir += 2) { /* construct a plane */ vec3_t vec2 = {0, 0, 0}; float dist; side_t* s2; vec2[axis] = dir; CrossProduct(vec, vec2, normal); if (VectorNormalize(normal) < 0.5) continue; dist = DotProduct(w->p[j], normal); /* if all the points on all the sides are * behind this plane, it is a proper edge bevel */ for (k = 0; k < b->numsides; k++) { winding_t* w2; float minBack; /* @note: This leads to different results on different archs * due to float rounding/precision errors - use the -ffloat-store * feature of gcc to 'fix' this */ /* if this plane has already been used, skip it */ if (PlaneEqual(&mapplanes[b->original_sides[k].planenum], normal, dist)) break; w2 = b->original_sides[k].winding; if (!w2) continue; minBack = 0.0f; for (l = 0; l < w2->numpoints; l++) { const float d = DotProduct(w2->p[l], normal) - dist; if (d > 0.1) break; /* point in front */ if (d < minBack) minBack = d; } /* if some point was at the front */ if (l != w2->numpoints) break; /* if no points at the back then the winding is on the bevel plane */ if (minBack > -0.1f) break; } if (k != b->numsides) continue; /* wasn't part of the outer hull */ /* add this plane */ if (nummapbrushsides == MAX_MAP_BRUSHSIDES) Sys_Error("MAX_MAP_BRUSHSIDES (%i)", nummapbrushsides); nummapbrushsides++; s2 = &b->original_sides[b->numsides]; s2->planenum = FindOrCreateFloatPlane(normal, dist); s2->texinfo = b->original_sides[0].texinfo; s2->contentFlags = b->original_sides[0].contentFlags; s2->bevel = true; c_edgebevels++; b->numsides++; } } } } }