@@ -848,6 +848,55 @@ static void SphereFromBounds( vec3_t mins, vec3_t maxs, vec3_t origin, float* ra
848848 *radius = VectorLength ( temp );
849849}
850850
851+ static std::string VertexToString ( srfVert_t* vertex ) {
852+ return Str::Format ( " xyz: %f %f %f normal: %f %f %f uv: %f %f lightmap: %f %f" , vertex->xyz [0 ], vertex->xyz [1 ], vertex->xyz [2 ],
853+ vertex->normal [0 ], vertex->normal [1 ], vertex->normal [2 ], vertex->st [0 ], vertex->st [1 ],
854+ vertex->lightmap [0 ], vertex->lightmap [1 ] );
855+ }
856+
857+ void ValidateVertex ( srfVert_t* vertex, int vertexID, shader_t * shader ) {
858+ for ( int i = 0 ; i < 3 ; i++ ) {
859+ /* NetRadiant only allows vertices in range [-65535, 65536],
860+ but some vertices still end up outside of that range, e.g: station15 sun */
861+ if ( !Math::IsFinite ( vertex->xyz [i] ) || vertex->xyz [i] < -1e9 || vertex->xyz [i] > 1e9 ) {
862+ Log::Warn ( " BSP: Bad position in vertex %i: %s, %s; setting to 0.0f" , vertexID,
863+ VertexToString ( vertex ), shader->name );
864+ vertex->xyz [i] = 0 .0f ;
865+ }
866+
867+ if ( !Math::IsFinite ( vertex->normal [i] ) ) {
868+ Log::Warn ( " BSP: Bad vertex normal %i: %s, %s; setting to 0.0f" , vertexID,
869+ VertexToString ( vertex ), shader->name );
870+ vertex->normal [i] = 0 .0f ;
871+
872+ VectorNormalize ( vertex->normal );
873+ }
874+ }
875+
876+ for ( int i = 0 ; i < 2 ; i++ ) {
877+ if ( !Math::IsFinite ( vertex->st [i] ) ) {
878+ Log::Warn ( " BSP: Bad uv in vertex %i: %s, %s; setting to 0.0f" , vertexID,
879+ VertexToString ( vertex ), shader->name );
880+ vertex->st [i] = 0 .0f ;
881+ }
882+
883+ // q3map2 sometimes produces garbage lightmap uv's on patch meshes and on surfaces that don't seem to use lightmaps
884+ if ( !Math::IsFinite ( vertex->lightmap [i] ) || vertex->lightmap [i] < -1 .0f || vertex->lightmap [i] > 1 .0f ) {
885+ /* Bad lightmap uv's on surfaces that don't use lightmapping seems to be very common in q3map2,
886+ so don't spam the log with them. We still need to fix such values though */
887+ for ( const shaderStage_t* pStage = shader->stages ; pStage < shader->lastStage ; pStage++ ) {
888+ if ( pStage->colorRenderer == &Render_lightMapping ) {
889+ Log::Warn ( " BSP: Bad lightmap in vertex %i: %s, %s; setting to 0.0f" , vertexID,
890+ VertexToString ( vertex ), shader->name );
891+ break ;
892+ }
893+ }
894+
895+ vertex->lightmap [i] = 0 .0f ;
896+ }
897+ }
898+ }
899+
851900static void ParseTriangleSurface ( dsurface_t * ds, drawVert_t* verts, bspSurface_t* surf, int * indexes ) {
852901 int realLightmapNum = LittleLong ( ds->lightmapNum );
853902
@@ -902,21 +951,25 @@ static void ParseTriangleSurface( dsurface_t* ds, drawVert_t* verts, bspSurface_
902951 cv->verts [ i ].normal [ j ] = LittleFloat ( verts[ i ].normal [ j ] );
903952 }
904953
905- AddPointToBounds ( cv->verts [ i ].xyz , cv->bounds [ 0 ], cv->bounds [ 1 ] );
906-
907954 components[ i ].minVertex = i;
908955
909956 for ( int j = 0 ; j < 2 ; j++ ) {
910957 cv->verts [ i ].st [ j ] = LittleFloat ( verts[ i ].st [ j ] );
911958 cv->verts [ i ].lightmap [ j ] = LittleFloat ( verts[ i ].lightmap [ j ] );
912-
913- components[ i ].stBounds [ 0 ][ j ] = cv->verts [ i ].st [ j ];
914- components[ i ].stBounds [ 1 ][ j ] = cv->verts [ i ].st [ j ];
915959 }
916960
917961 cv->verts [ i ].lightmap [ 0 ] = LittleFloat ( verts[ i ].lightmap [ 0 ] );
918962 cv->verts [ i ].lightmap [ 1 ] = LittleFloat ( verts[ i ].lightmap [ 1 ] );
919963
964+ ValidateVertex ( &cv->verts [i], ds->firstVert + i, surf->shader );
965+
966+ AddPointToBounds ( cv->verts [ i ].xyz , cv->bounds [ 0 ], cv->bounds [ 1 ] );
967+
968+ for ( int j = 0 ; j < 2 ; j++ ) {
969+ components[ i ].stBounds [ 0 ][ j ] = cv->verts [ i ].st [ j ];
970+ components[ i ].stBounds [ 1 ][ j ] = cv->verts [ i ].st [ j ];
971+ }
972+
920973 cv->verts [ i ].lightColor = Color::Adapt ( verts[ i ].color );
921974
922975 if ( tr.overbrightBits < tr.mapOverBrightBits ) {
@@ -1065,7 +1118,6 @@ static void ParseTriSurf( dsurface_t* ds, drawVert_t* verts, bspSurface_t* surf,
10651118static void ParseMesh ( dsurface_t *ds, drawVert_t *verts, bspSurface_t *surf )
10661119{
10671120 srfGridMesh_t *grid;
1068- int i, j;
10691121 int width, height, numPoints;
10701122 static srfVert_t points[ MAX_PATCH_SIZE * MAX_PATCH_SIZE ];
10711123 vec3_t bounds[ 2 ];
@@ -1128,26 +1180,30 @@ static void ParseMesh( dsurface_t *ds, drawVert_t *verts, bspSurface_t *surf )
11281180 stBounds[ 1 ][ 0 ] = -99999 .0f ;
11291181 stBounds[ 1 ][ 1 ] = -99999 .0f ;
11301182
1131- for ( i = 0 ; i < numPoints; i++ )
1183+ for ( int i = 0 ; i < numPoints; i++ )
11321184 {
1133- for ( j = 0 ; j < 3 ; j++ )
1185+ for ( int j = 0 ; j < 3 ; j++ )
11341186 {
11351187 points[ i ].xyz [ j ] = LittleFloat ( verts[ i ].xyz [ j ] );
11361188 points[ i ].normal [ j ] = LittleFloat ( verts[ i ].normal [ j ] );
11371189 }
11381190
1139- for ( j = 0 ; j < 2 ; j++ )
1191+ for ( int j = 0 ; j < 2 ; j++ )
11401192 {
11411193 points[ i ].st [ j ] = LittleFloat ( verts[ i ].st [ j ] );
11421194 points[ i ].lightmap [ j ] = LittleFloat ( verts[ i ].lightmap [ j ] );
1143-
1144- stBounds[ 0 ][ j ] = std::min ( stBounds[ 0 ][ j ], points[ i ].st [ j ] );
1145- stBounds[ 1 ][ j ] = std::max ( stBounds[ 1 ][ j ], points[ i ].st [ j ] );
11461195 }
11471196
11481197 points[ i ].lightmap [ 0 ] = LittleFloat ( verts[ i ].lightmap [ 0 ] );
11491198 points[ i ].lightmap [ 1 ] = LittleFloat ( verts[ i ].lightmap [ 1 ] );
11501199
1200+ ValidateVertex ( &points[i], ds->firstVert + i, surf->shader );
1201+
1202+ for ( int j = 0 ; j < 2 ; j++ ) {
1203+ stBounds[ 0 ][ j ] = std::min ( stBounds[ 0 ][ j ], points[ i ].st [ j ] );
1204+ stBounds[ 1 ][ j ] = std::max ( stBounds[ 1 ][ j ], points[ i ].st [ j ] );
1205+ }
1206+
11511207 points[ i ].lightColor = Color::Adapt ( verts[ i ].color );
11521208
11531209 if ( tr.overbrightBits < tr.mapOverBrightBits )
@@ -1157,14 +1213,14 @@ static void ParseMesh( dsurface_t *ds, drawVert_t *verts, bspSurface_t *surf )
11571213 }
11581214
11591215 // center texture coords
1160- for ( j = 0 ; j < 2 ; j++ ) {
1216+ for ( int j = 0 ; j < 2 ; j++ ) {
11611217 tcOffset[ j ] = 0 .5f * (stBounds[ 1 ][ j ] + stBounds[ 0 ][ j ]);
11621218 tcOffset[ j ] = rintf ( tcOffset[ j ] );
11631219 }
11641220
1165- for ( i = 0 ; i < numPoints; i++ )
1221+ for ( int i = 0 ; i < numPoints; i++ )
11661222 {
1167- for ( j = 0 ; j < 2 ; j++ )
1223+ for ( int j = 0 ; j < 2 ; j++ )
11681224 {
11691225 points[ i ].st [ j ] -= tcOffset[ j ];
11701226 }
@@ -1177,7 +1233,7 @@ static void ParseMesh( dsurface_t *ds, drawVert_t *verts, bspSurface_t *surf )
11771233 // copy the level of detail origin, which is the center
11781234 // of the group of all curves that must subdivide the same
11791235 // to avoid cracking
1180- for ( i = 0 ; i < 3 ; i++ )
1236+ for ( int i = 0 ; i < 3 ; i++ )
11811237 {
11821238 bounds[ 0 ][ i ] = LittleFloat ( ds->lightmapVecs [ 0 ][ i ] );
11831239 bounds[ 1 ][ i ] = LittleFloat ( ds->lightmapVecs [ 1 ][ i ] );
0 commit comments