From: Garux Date: Tue, 1 Aug 2017 10:34:48 +0000 (+0300) Subject: Q3map2: X-Git-Url: https://git.rm.cloudns.org/?a=commitdiff_plain;h=f73cc19a6166fc04269f953c980175779f81b9b0;p=xonotic%2Fnetradiant.git Q3map2: * -clipdepth F, def 2, _clipdepth * fixed model autoclip (64u thick brushes/no collision at all in some cases) * pyramidal etc zillion (20!) of autoclip modes * removed stuctural caulk in models, was broken anyway Radiant: misc... * hollow: produces not intersecting brushes --- diff --git a/Makefile b/Makefile index e2d56e38..4eb69efa 100644 --- a/Makefile +++ b/Makefile @@ -5,7 +5,7 @@ MAKEFILE_CONF ?= Makefile.conf # user customizable stuf # you may override this in Makefile.conf or the environment BUILD ?= debug -# or: release, or: extradebug, or: profile +# or: release, or: extradebug, or: profile, or: debug OS ?= $(shell uname) # or: Linux, Win32, Darwin LDFLAGS ?= diff --git a/radiant/csg.cpp b/radiant/csg.cpp index 5676401e..aab9caa5 100644 --- a/radiant/csg.cpp +++ b/radiant/csg.cpp @@ -29,10 +29,25 @@ #include "brushmanip.h" #include "brushnode.h" #include "grid.h" +/* +void Face_makeBrush( Face& face, const Brush& brush, brush_vector_t& out, float offset ){ + if ( face.contributes() ) { + out.push_back( new Brush( brush ) ); + Face* newFace = out.back()->addFace( face ); + if ( newFace != 0 ) { + newFace->flipWinding(); + newFace->getPlane().offset( offset ); + newFace->planeChanged(); + } + } +} +*/ void Face_makeBrush( Face& face, const Brush& brush, brush_vector_t& out, float offset ){ if ( face.contributes() ) { out.push_back( new Brush( brush ) ); + //face.getPlane().offset( -offset ); + //face.planeChanged(); Face* newFace = out.back()->addFace( face ); if ( newFace != 0 ) { newFace->flipWinding(); diff --git a/tools/quake3/q3map2/bsp.c b/tools/quake3/q3map2/bsp.c index 2edf9f5d..1cef5a48 100644 --- a/tools/quake3/q3map2/bsp.c +++ b/tools/quake3/q3map2/bsp.c @@ -955,9 +955,10 @@ int BSPMain( int argc, char **argv ){ Sys_Printf( "Debug model clip enabled\n" ); debugClip = qtrue; } - else if ( !strcmp( argv[ i ], "-snapmodelclip" ) ) { - Sys_Printf( "Snapping model clip enabled\n" ); - snapModelClip = qtrue; + else if ( !strcmp( argv[ i ], "-clipdepth" ) ) { + clipDepthGlobal = atof( argv[ i + 1 ] ); + i++; + Sys_Printf( "Model autoclip thickness set to %.3f\n", clipDepthGlobal ); } else if ( !strcmp( argv[ i ], "-sRGBtex" ) ) { texturesRGB = qtrue; diff --git a/tools/quake3/q3map2/map.c b/tools/quake3/q3map2/map.c index e0d1fdda..7014ec44 100644 --- a/tools/quake3/q3map2/map.c +++ b/tools/quake3/q3map2/map.c @@ -69,7 +69,7 @@ qboolean PlaneEqual( plane_t *p, vec3_t normal, vec_t dist ){ /* compare */ // We check equality of each component since we're using '<', not '<=' - // (the epsilons may be zero). We want to use '<' intead of '<=' to be + // (the epsilons may be zero). We want to use '<' instead of '<=' to be // consistent with the true meaning of "epsilon", and also because other // parts of the code uses this inequality. if ( ( p->dist == dist || fabs( p->dist - dist ) < de ) && @@ -164,6 +164,44 @@ qboolean SnapNormal( vec3_t normal ){ // normalized). The original SnapNormal() didn't snap such vectors - it // only snapped vectors that were near a perfect axis. + //adjusting vectors, that were near a perfect axis, with bigger epsilon + //they cause precision errors + + /* + if ( ( normal[0] != 0.0 || normal[1] != 0.0 ) && fabs(normal[0]) < 0.00025 && fabs(normal[1]) < 0.00025){ + normal[0] = normal[1] = 0.0; + adjusted = qtrue; + } + else if ( ( normal[0] != 0.0 || normal[2] != 0.0 ) && fabs(normal[0]) < 0.00025 && fabs(normal[2]) < 0.00025){ + normal[0] = normal[2] = 0.0; + adjusted = qtrue; + } + else if ( ( normal[2] != 0.0 || normal[1] != 0.0 ) && fabs(normal[2]) < 0.00025 && fabs(normal[1]) < 0.00025){ + normal[2] = normal[1] = 0.0; + adjusted = qtrue; + } + */ + + /* + for ( i=0; i<30; i++ ) + { + double x, y, z, length; + x=(double) 1.0; + y=(double) ( 0.00001 * i ); + z=(double) 0.0; + + Sys_Printf("(%6.18f %6.18f %6.18f)inNormal\n", x,y,z ); + + length = sqrt( ( x * x ) + ( y * y ) + ( z * z ) ); + Sys_Printf("(%6.18f)length\n", length); + x = (vec_t) ( x / length ); + y = (vec_t) ( y / length ); + z = (vec_t) ( z / length ); + Sys_Printf("(%6.18f %6.18f %6.18f)outNormal\n\n", x,y,z ); + } + Error("vectorNormalize test completed"); + */ + for ( i = 0; i < 3; i++ ) { if ( normal[i] != 0.0 && -normalEpsilon < normal[i] && normal[i] < normalEpsilon ) { @@ -326,12 +364,7 @@ int FindFloatPlane( vec3_t innormal, vec_t dist, int numPoints, vec3_t *points ) VectorCopy( innormal, normal ); #if Q3MAP2_EXPERIMENTAL_SNAP_PLANE_FIX - if ( !doingModelClip ) { - SnapPlaneImproved( normal, &dist, numPoints, (const vec3_t *) points ); - } - if ( doingModelClip && snapModelClip ) { - SnapPlane( normal, &dist ); - } + SnapPlaneImproved( normal, &dist, numPoints, (const vec3_t *) points ); #else SnapPlane( normal, &dist ); #endif diff --git a/tools/quake3/q3map2/model.c b/tools/quake3/q3map2/model.c index 7127591e..e8e00d33 100644 --- a/tools/quake3/q3map2/model.c +++ b/tools/quake3/q3map2/model.c @@ -210,8 +210,8 @@ picoModel_t *LoadModel( const char *name, int frame ){ adds a picomodel into the bsp */ -void InsertModel( const char *name, int skin, int frame, m4x4_t transform, remap_t *remap, shaderInfo_t *celShader, int eNum, int castShadows, int recvShadows, int spawnFlags, float lightmapScale, int lightmapSampleSize, float shadeAngle ){ - int i, j, s, numSurfaces; +void InsertModel( const char *name, int skin, int frame, m4x4_t transform, remap_t *remap, shaderInfo_t *celShader, int eNum, int castShadows, int recvShadows, int spawnFlags, float lightmapScale, int lightmapSampleSize, float shadeAngle, float clipDepth ){ + int i, j, s, k, numSurfaces; m4x4_t identity, nTransform; picoModel_t *model; picoShader_t *shader; @@ -226,12 +226,18 @@ void InsertModel( const char *name, int skin, int frame, m4x4_t transform, remap picoIndex_t *indexes; remap_t *rm, *glob; skinfile_t *sf, *sf2; - double normalEpsilon_save; - double distanceEpsilon_save; char skinfilename[ MAX_QPATH ]; char *skinfilecontent; int skinfilesize; char *skinfileptr, *skinfilenextptr; + int ok=0, notok=0, spf = ( spawnFlags & 8088 ); + float limDepth=0; + + + if ( clipDepth < 0 ){ + limDepth = -clipDepth; + clipDepth = 2.0; + } /* get model */ @@ -418,15 +424,7 @@ void InsertModel( const char *name, int skin, int frame, m4x4_t transform, remap if ( ( si != NULL && si->forceMeta ) || ( spawnFlags & 4 ) ) { /* 3rd bit */ ds->type = SURFACE_FORCED_META; } -/* else - { - //fix not requested lightmapping of models :E - // else force vertexlit - // ApplySurfaceParm( "pointlight", &si->contentFlags, &si->surfaceFlags, &si->compileFlags ); - // si->compileFlags |= C_VERTEXLIT; - //ds->type == SURFACE_TRIANGLES; - } -*/ + /* fix the surface's normals (jal: conditioned by shader info) */ if ( !( spawnFlags & 64 ) && ( shadeAngle == 0.0f || ds->type != SURFACE_FORCED_META ) ) { PicoFixSurfaceNormals( surface ); @@ -524,23 +522,99 @@ void InsertModel( const char *name, int skin, int frame, m4x4_t transform, remap ds->celShader = celShader; /* ydnar: giant hack land: generate clipping brushes for model triangles */ - if ( si->clipModel || ( spawnFlags & 2 ) ) { /* 2nd bit */ - vec3_t points[ 4 ], backs[ 3 ]; - vec4_t plane, reverse, pa, pb, pc; - + if ( ( si->clipModel && !( spf ) ) || //default CLIPMODEL + ( ( spawnFlags & 8090 ) == 2 ) || //default CLIPMODEL + ( spf == 8 ) || //EXTRUDE_FACE_NORMALS + ( spf == 16 ) || //EXTRUDE_TERRAIN + ( spf == 128 ) || //EXTRUDE_VERTEX_NORMALS + ( spf == 256 ) || //PYRAMIDAL_CLIP + ( spf == 512 ) || //EXTRUDE_DOWNWARDS + ( spf == 1024 ) || //EXTRUDE_UPWARDS + ( spf == 4096 ) || //default CLIPMODEL + AXIAL_BACKPLANE + ( spf == 264 ) || //EXTRUDE_FACE_NORMALS+PYRAMIDAL_CLIP (extrude 45) + ( spf == 2064 ) || //EXTRUDE_TERRAIN+MAX_EXTRUDE + ( spf == 4112 ) || //EXTRUDE_TERRAIN+AXIAL_BACKPLANE + ( spf == 384 ) || //EXTRUDE_VERTEX_NORMALS + PYRAMIDAL_CLIP - vertex normals + don't check for sides, sticking outwards + ( spf == 4352 ) || //PYRAMIDAL_CLIP+AXIAL_BACKPLANE + ( spf == 1536 ) || //EXTRUDE_DOWNWARDS+EXTRUDE_UPWARDS + ( spf == 2560 ) || //EXTRUDE_DOWNWARDS+MAX_EXTRUDE + ( spf == 4608 ) || //EXTRUDE_DOWNWARDS+AXIAL_BACKPLANE + ( spf == 3584 ) || //EXTRUDE_DOWNWARDS+EXTRUDE_UPWARDS+MAX_EXTRUDE + ( spf == 5632 ) || //EXTRUDE_DOWNWARDS+EXTRUDE_UPWARDS+AXIAL_BACKPLANE + ( spf == 3072 ) || //EXTRUDE_UPWARDS+MAX_EXTRUDE + ( spf == 5120 ) ){ //EXTRUDE_UPWARDS+AXIAL_BACKPLANE + vec3_t points[ 4 ], backs[ 3 ], cnt, bestNormal, nrm, Vnorm[3], Enorm[3]; + vec4_t plane, reverse, p[3]; + double normalEpsilon_save; + qboolean snpd; + vec3_t min = { 999999, 999999, 999999 }, max = { -999999, -999999, -999999 }; + vec3_t avgDirection = { 0, 0, 0 }; + int axis; + #define nonax_clip_dbg 1 /* temp hack */ if ( !si->clipModel && !( si->compileFlags & C_SOLID ) ) { continue; } + //wont snap these in normal way, or will explode + normalEpsilon_save = normalEpsilon; + //normalEpsilon = 0.000001; + + + //MAX_EXTRUDE or EXTRUDE_TERRAIN + if ( ( spawnFlags & 2048 ) || ( spawnFlags & 16 ) ){ + + for ( i = 0; i < ds->numIndexes; i += 3 ) + { + for ( j = 0; j < 3; j++ ) + { + dv = &ds->verts[ ds->indexes[ i + j ] ]; + VectorCopy( dv->xyz, points[ j ] ); + } + if ( PlaneFromPoints( plane, points[ 0 ], points[ 1 ], points[ 2 ] ) ){ + if ( spawnFlags & 16 ) VectorAdd( avgDirection, plane, avgDirection ); //calculate average mesh facing direction + + //get min/max + for ( k = 2; k > -1; k-- ){ + if ( plane[k] > 0 ){ + for ( j = 0; j < 3; j++ ){ if ( points[j][k] < min[k] ) min[k] = points[j][k]; } + } + else if ( plane[k] < 0 ){ + for ( j = 0; j < 3; j++ ){ if ( points[j][k] > max[k] ) max[k] = points[j][k]; } + } + //if EXTRUDE_DOWNWARDS or EXTRUDE_UPWARDS + if ( ( spawnFlags & 512 ) || ( spawnFlags & 1024 ) ){ + break; + } + } + } + } + //unify avg direction + if ( spawnFlags & 16 ){ + for ( j = 0; j < 3; j++ ){ + if ( fabs(avgDirection[j]) > fabs(avgDirection[(j+1)%3]) ){ + avgDirection[(j+1)%3] = 0.0; + axis = j; + } + else { + avgDirection[j] = 0.0; + } + } + if ( VectorNormalize( avgDirection, avgDirection ) == 0 ){ + axis = 2; + VectorSet( avgDirection, 0, 0, 1 ); + } + } + } + /* walk triangle list */ for ( i = 0; i < ds->numIndexes; i += 3 ) { /* overflow hack */ AUTOEXPAND_BY_REALLOC( mapplanes, ( nummapplanes + 64 ) << 1, allocatedmapplanes, 1024 ); - /* make points and back points */ + /* make points */ for ( j = 0; j < 3; j++ ) { /* get vertex */ @@ -550,105 +624,667 @@ void InsertModel( const char *name, int skin, int frame, m4x4_t transform, remap VectorCopy( dv->xyz, points[ j ] ); } - VectorCopy( points[0], points[3] ); // for cyclic usage - /* make plane for triangle */ - // div0: add some extra spawnflags: - // 0: snap normals to axial planes for extrusion - // 8: extrude with the original normals - // 16: extrude only with up/down normals (ideal for terrain) - // 24: extrude by distance zero (may need engine changes) if ( PlaneFromPoints( plane, points[ 0 ], points[ 1 ], points[ 2 ] ) ) { - vec3_t bestNormal; - float backPlaneDistance = 2; - if ( spawnFlags & 8 ) { // use a DOWN normal - if ( spawnFlags & 16 ) { - // 24: normal as is, and zero width (broken) - VectorCopy( plane, bestNormal ); + /* build a brush */ + buildBrush = AllocBrush( 48 ); + buildBrush->entityNum = mapEntityNum; + buildBrush->original = buildBrush; + buildBrush->contentShader = si; + buildBrush->compileFlags = si->compileFlags; + buildBrush->contentFlags = si->contentFlags; + buildBrush->detail = qtrue; + + //snap points before using them for further calculations + //precision suffers a lot, when two of normal values are under .00025 (often no collision, knocking up effect in ioq3) + //also broken drawsurfs in case of normal brushes + snpd = qfalse; + for ( j=0; j<3; j++ ) + { + if ( fabs(plane[j]) < 0.00025 && fabs(plane[(j+1)%3]) < 0.00025 && ( plane[j] != 0.0 || plane[(j+1)%3] != 0.0 ) ){ + VectorAdd( points[ 0 ], points[ 1 ], cnt ); + VectorAdd( cnt, points[ 2 ], cnt ); + VectorScale( cnt, 0.3333333333333f, cnt ); + points[0][(j+2)%3]=points[1][(j+2)%3]=points[2][(j+2)%3]=cnt[(j+2)%3]; + snpd = qtrue; + break; } - else + } + + //snap pairs of points to prevent bad side planes + for ( j=0; j<3; j++ ) + { + VectorSubtract( points[j], points[(j+1)%3], nrm ); + VectorNormalize( nrm, nrm ); + for ( k=0; k<3; k++ ) { - // 8: normal as is - VectorCopy( plane, bestNormal ); + if ( nrm[k] != 0.0 && fabs(nrm[k]) < 0.00025 ){ + //Sys_Printf( "b4(%6.6f %6.6f %6.6f)(%6.6f %6.6f %6.6f)\n", points[j][0], points[j][1], points[j][2], points[(j+1)%3][0], points[(j+1)%3][1], points[(j+1)%3][2] ); + points[j][k]=points[(j+1)%3][k] = ( points[j][k] + points[(j+1)%3][k] ) / 2.0; + //Sys_Printf( "sn(%6.6f %6.6f %6.6f)(%6.6f %6.6f %6.6f)\n", points[j][0], points[j][1], points[j][2], points[(j+1)%3][0], points[(j+1)%3][1], points[(j+1)%3][2] ); + snpd = qtrue; + } } } - else + + if ( snpd ) { + PlaneFromPoints( plane, points[ 0 ], points[ 1 ], points[ 2 ] ); + snpd = qfalse; + } + + //vector-is-close-to-be-on-axis check again, happens after previous code sometimes + for ( j=0; j<3; j++ ) { - if ( spawnFlags & 16 ) { - // 16: UP/DOWN normal - VectorSet( bestNormal, 0, 0, ( plane[2] >= 0 ? 1 : -1 ) ); + if ( fabs(plane[j]) < 0.00025 && fabs(plane[(j+1)%3]) < 0.00025 && ( plane[j] != 0.0 || plane[(j+1)%3] != 0.0 ) ){ + VectorAdd( points[ 0 ], points[ 1 ], cnt ); + VectorAdd( cnt, points[ 2 ], cnt ); + VectorScale( cnt, 0.3333333333333f, cnt ); + points[0][(j+2)%3]=points[1][(j+2)%3]=points[2][(j+2)%3]=cnt[(j+2)%3]; + PlaneFromPoints( plane, points[ 0 ], points[ 1 ], points[ 2 ] ); + break; } - else + } + + //snap single snappable normal components + for ( j=0; j<3; j++ ) + { + if ( plane[j] != 0.0 && fabs(plane[j]) < 0.00005 ){ + plane[j]=0.0; + snpd = qtrue; + } + } + + //adjust plane dist + if ( snpd ) { + VectorAdd( points[ 0 ], points[ 1 ], cnt ); + VectorAdd( cnt, points[ 2 ], cnt ); + VectorScale( cnt, 0.3333333333333f, cnt ); + VectorNormalize( plane, plane ); + plane[3] = DotProduct( plane, cnt ); + + //project points to resulting plane to keep intersections precision + for ( j=0; j<3; j++ ) + { + //Sys_Printf( "b4 %i (%6.7f %6.7f %6.7f)\n", j, points[j][0], points[j][1], points[j][2] ); + VectorMA( points[j], plane[3] - DotProduct( plane, points[j]), plane, points[j] ); + //Sys_Printf( "sn %i (%6.7f %6.7f %6.7f)\n", j, points[j][0], points[j][1], points[j][2] ); + } + //Sys_Printf( "sn pln (%6.7f %6.7f %6.7f %6.7f)\n", plane[0], plane[1], plane[2], plane[3] ); + //PlaneFromPoints( plane, points[ 0 ], points[ 1 ], points[ 2 ] ); + //Sys_Printf( "pts pln (%6.7f %6.7f %6.7f %6.7f)\n", plane[0], plane[1], plane[2], plane[3] ); + } + + + if ( spf == 4352 ){ //PYRAMIDAL_CLIP+AXIAL_BACKPLANE + + for ( j=0; j<3; j++ ) { - // 0: axial normal - if ( fabs( plane[0] ) > fabs( plane[1] ) ) { // x>y - if ( fabs( plane[1] ) > fabs( plane[2] ) ) { // x>y, y>z - VectorSet( bestNormal, ( plane[0] >= 0 ? 1 : -1 ), 0, 0 ); + if ( fabs(plane[j]) < 0.05 && fabs(plane[(j+1)%3]) < 0.05 ){ //no way, close to lay on two axises + goto default_CLIPMODEL; + } + } + + // best axial normal + VectorCopy( plane, bestNormal ); + for ( j = 0; j < 3; j++ ){ + if ( fabs(bestNormal[j]) > fabs(bestNormal[(j+1)%3]) ){ + bestNormal[(j+1)%3] = 0.0; + axis = j; + } + else { + bestNormal[j] = 0.0; + } + } + VectorNormalize( bestNormal, bestNormal ); + + + float bestdist, currdist, bestangle, currangle, mindist = 999999; + + for ( j = 0; j < 3; j++ ){//planes + bestdist = 999999; + bestangle = 1; + for ( k = 0; k < 3; k++ ){//axises + VectorSubtract( points[ (j+1)%3 ], points[ j ], nrm ); + if ( k == axis ){ + CrossProduct( bestNormal, nrm, reverse ); } - else // x>y, z>=y - if ( fabs( plane[0] ) > fabs( plane[2] ) ) { // x>z, z>=y - VectorSet( bestNormal, ( plane[0] >= 0 ? 1 : -1 ), 0, 0 ); + else{ + VectorClear( Vnorm[0] ); + if ( (k+1)%3 == axis ){ + if ( nrm[ (k+2)%3 ] == 0 ) continue; + Vnorm[0][ (k+2)%3 ] = nrm[ (k+2)%3 ]; + } + else{ + if ( nrm[ (k+1)%3 ] == 0 ) continue; + Vnorm[0][ (k+1)%3 ] = nrm[ (k+1)%3 ]; + } + CrossProduct( bestNormal, Vnorm[0], Enorm[0] ); + CrossProduct( Enorm[0], nrm, reverse ); } - else{ // z>=x, x>y - VectorSet( bestNormal, 0, 0, ( plane[2] >= 0 ? 1 : -1 ) ); + VectorNormalize( reverse, reverse ); + reverse[3] = DotProduct( points[ j ], reverse ); + //check facing, thickness + currdist = reverse[3] - DotProduct( reverse, points[ (j+2)%3 ] ); + currangle = DotProduct( reverse, plane ); + if ( ( ( currdist > 0.1 ) && ( currdist < bestdist ) && ( currangle < 0 ) ) || + ( ( currangle >= 0 ) && ( currangle <= bestangle ) ) ){ + bestangle = currangle; + if ( currangle < 0 ) bestdist = currdist; + VectorCopy( reverse, p[j] ); + p[j][3] = reverse[3]; + } + } + //if ( bestdist == 999999 && bestangle == 1 ) Sys_Printf("default_CLIPMODEL\n"); + if ( bestdist == 999999 && bestangle == 1 ) goto default_CLIPMODEL; + if ( bestdist < mindist ) mindist = bestdist; + } + if ( (limDepth != 0.0) && (mindist > limDepth) ) goto default_CLIPMODEL; + + +#if nonax_clip_dbg + for ( j = 0; j < 3; j++ ) + { + for ( k = 0; k < 3; k++ ) + { + if ( fabs(p[j][k]) < 0.00025 && p[j][k] != 0.0 ){ + Sys_Printf( "nonax nrm %6.17f %6.17f %6.17f\n", p[j][0], p[j][1], p[j][2] ); } } - else // y>=x - if ( fabs( plane[1] ) > fabs( plane[2] ) ) { // y>z, y>=x - VectorSet( bestNormal, 0, ( plane[1] >= 0 ? 1 : -1 ), 0 ); + } +#endif + /* set up brush sides */ + buildBrush->numsides = 4; + buildBrush->sides[ 0 ].shaderInfo = si; + for ( j = 1; j < buildBrush->numsides; j++ ) { + if ( debugClip ) { + buildBrush->sides[ 0 ].shaderInfo = ShaderInfoForShader( "debugclip2" ); + buildBrush->sides[ j ].shaderInfo = ShaderInfoForShader( "debugclip" ); + } + else { + buildBrush->sides[ j ].shaderInfo = NULL; // don't emit these faces as draw surfaces, should make smaller BSPs; hope this works } - else{ // z>=y, y>=x + } + VectorCopy( points[0], points[3] ); // for cyclic usage + + buildBrush->sides[ 0 ].planenum = FindFloatPlane( plane, plane[ 3 ], 3, points ); + buildBrush->sides[ 1 ].planenum = FindFloatPlane( p[0], p[0][ 3 ], 2, &points[ 0 ] ); // p[0] contains points[0] and points[1] + buildBrush->sides[ 2 ].planenum = FindFloatPlane( p[1], p[1][ 3 ], 2, &points[ 1 ] ); // p[1] contains points[1] and points[2] + buildBrush->sides[ 3 ].planenum = FindFloatPlane( p[2], p[2][ 3 ], 2, &points[ 2 ] ); // p[2] contains points[2] and points[0] (copied to points[3] + } + + + else if ( ( spf == 16 ) || //EXTRUDE_TERRAIN + ( spf == 512 ) || //EXTRUDE_DOWNWARDS + ( spf == 1024 ) || //EXTRUDE_UPWARDS + ( spf == 4096 ) || //default CLIPMODEL + AXIAL_BACKPLANE + ( spf == 2064 ) || //EXTRUDE_TERRAIN+MAX_EXTRUDE + ( spf == 4112 ) || //EXTRUDE_TERRAIN+AXIAL_BACKPLANE + ( spf == 1536 ) || //EXTRUDE_DOWNWARDS+EXTRUDE_UPWARDS + ( spf == 2560 ) || //EXTRUDE_DOWNWARDS+MAX_EXTRUDE + ( spf == 4608 ) || //EXTRUDE_DOWNWARDS+AXIAL_BACKPLANE + ( spf == 3584 ) || //EXTRUDE_DOWNWARDS+EXTRUDE_UPWARDS+MAX_EXTRUDE + ( spf == 5632 ) || //EXTRUDE_DOWNWARDS+EXTRUDE_UPWARDS+AXIAL_BACKPLANE + ( spf == 3072 ) || //EXTRUDE_UPWARDS+MAX_EXTRUDE + ( spf == 5120 ) ){ //EXTRUDE_UPWARDS+AXIAL_BACKPLANE + + if ( spawnFlags & 16 ){ //autodirection + VectorCopy( avgDirection, bestNormal ); + } + else{ + axis = 2; + if ( ( spawnFlags & 1536 ) == 1536 ){ //up+down VectorSet( bestNormal, 0, 0, ( plane[2] >= 0 ? 1 : -1 ) ); } + else if ( spawnFlags & 512 ){ //down + VectorSet( bestNormal, 0, 0, 1 ); + + } + else if ( spawnFlags & 1024 ){ //up + VectorSet( bestNormal, 0, 0, -1 ); + } + else{ // best axial normal + VectorCopy( plane, bestNormal ); + for ( j = 0; j < 3; j++ ){ + if ( fabs(bestNormal[j]) > fabs(bestNormal[(j+1)%3]) ){ + bestNormal[(j+1)%3] = 0.0; + axis = j; + } + else { + bestNormal[j] = 0.0; + } + } + VectorNormalize( bestNormal, bestNormal ); + } + } + + if ( DotProduct( plane, bestNormal ) < 0.05 ){ + goto default_CLIPMODEL; + } + + + /* make side planes */ + for ( j = 0; j < 3; j++ ) + { + VectorSubtract( points[(j+1)%3], points[ j ], nrm ); + CrossProduct( bestNormal, nrm, p[ j ] ); + VectorNormalize( p[ j ], p[ j ] ); + p[j][3] = DotProduct( points[j], p[j] ); + } + + /* make back plane */ + if ( spawnFlags & 2048 ){ //max extrude + VectorScale( bestNormal, -1.0f, reverse ); + if ( bestNormal[axis] > 0 ){ + reverse[3] = -min[axis] + clipDepth; + } + else{ + reverse[3] = max[axis] + clipDepth; + } + } + else if ( spawnFlags & 4096 ){ //axial backplane + VectorScale( bestNormal, -1.0f, reverse ); + reverse[3] = points[0][axis]; + if ( bestNormal[axis] > 0 ){ + for ( j = 1; j < 3; j++ ){ + if ( points[j][axis] < reverse[3] ){ + reverse[3] = points[j][axis]; + } + } + reverse[3] = -reverse[3] + clipDepth; + } + else{ + for ( j = 1; j < 3; j++ ){ + if ( points[j][axis] > reverse[3] ){ + reverse[3] = points[j][axis]; + } + } + reverse[3] += clipDepth; + } + if (limDepth != 0.0){ + VectorCopy( points[0], cnt ); + if ( bestNormal[axis] > 0 ){ + for ( j = 1; j < 3; j++ ){ + if ( points[j][axis] > cnt[axis] ){ + VectorCopy( points[j], cnt ); + } + } + } + else { + for ( j = 1; j < 3; j++ ){ + if ( points[j][axis] < cnt[axis] ){ + VectorCopy( points[j], cnt ); + } + } + } + VectorMA( cnt, reverse[3] - DotProduct( reverse, cnt ), reverse, cnt ); + if ( ( plane[3] - DotProduct( plane, cnt ) ) > limDepth ){ + VectorScale( plane, -1.0f, reverse ); + reverse[ 3 ] = -plane[ 3 ]; + reverse[3] += clipDepth; + } + } + } + else{ //normal backplane + VectorScale( plane, -1.0f, reverse ); + reverse[ 3 ] = -plane[ 3 ]; + reverse[3] += clipDepth; + } +#if nonax_clip_dbg + for ( j = 0; j < 3; j++ ) + { + for ( k = 0; k < 3; k++ ) + { + if ( fabs(p[j][k]) < 0.00025 && p[j][k] != 0.0 ){ + Sys_Printf( "nonax nrm %6.17f %6.17f %6.17f\n", p[j][0], p[j][1], p[j][2] ); + } + } } +#endif + /* set up brush sides */ + buildBrush->numsides = 5; + buildBrush->sides[ 0 ].shaderInfo = si; + for ( j = 1; j < buildBrush->numsides; j++ ) { + if ( debugClip ) { + buildBrush->sides[ 0 ].shaderInfo = ShaderInfoForShader( "debugclip2" ); + buildBrush->sides[ j ].shaderInfo = ShaderInfoForShader( "debugclip" ); + } + else { + buildBrush->sides[ j ].shaderInfo = NULL; // don't emit these faces as draw surfaces, should make smaller BSPs; hope this works + } + } + VectorCopy( points[0], points[3] ); // for cyclic usage + + buildBrush->sides[ 0 ].planenum = FindFloatPlane( plane, plane[ 3 ], 3, points ); + buildBrush->sides[ 1 ].planenum = FindFloatPlane( p[0], p[0][ 3 ], 2, &points[ 0 ] ); // p[0] contains points[0] and points[1] + buildBrush->sides[ 2 ].planenum = FindFloatPlane( p[1], p[1][ 3 ], 2, &points[ 1 ] ); // p[1] contains points[1] and points[2] + buildBrush->sides[ 3 ].planenum = FindFloatPlane( p[2], p[2][ 3 ], 2, &points[ 2 ] ); // p[2] contains points[2] and points[0] (copied to points[3] + buildBrush->sides[ 4 ].planenum = FindFloatPlane( reverse, reverse[ 3 ], 0, NULL ); } - /* build a brush */ - buildBrush = AllocBrush( 48 ); - buildBrush->entityNum = mapEntityNum; - buildBrush->original = buildBrush; - buildBrush->contentShader = si; - buildBrush->compileFlags = si->compileFlags; - buildBrush->contentFlags = si->contentFlags; - normalEpsilon_save = normalEpsilon; - distanceEpsilon_save = distanceEpsilon; - if ( si->compileFlags & C_STRUCTURAL ) { // allow forced structural brushes here - buildBrush->detail = qfalse; - // only allow EXACT matches when snapping for these (this is mostly for caulk brushes inside a model) - if ( normalEpsilon > 0 ) { - normalEpsilon = 0; + else if ( spf == 264 ){ //EXTRUDE_FACE_NORMALS+PYRAMIDAL_CLIP (extrude 45) + + //45 degrees normals for side planes + for ( j = 0; j < 3; j++ ) + { + VectorSubtract( points[(j+1)%3], points[ j ], nrm ); + CrossProduct( plane, nrm, Enorm[ j ] ); + VectorNormalize( Enorm[ j ], Enorm[ j ] ); + VectorAdd( plane, Enorm[ j ], Enorm[ j ] ); + VectorNormalize( Enorm[ j ], Enorm[ j ] ); + /* make side planes */ + CrossProduct( Enorm[ j ], nrm, p[ j ] ); + VectorNormalize( p[ j ], p[ j ] ); + p[j][3] = DotProduct( points[j], p[j] ); + //snap nearly axial side planes + snpd = qfalse; + for ( k = 0; k < 3; k++ ) + { + if ( fabs(p[j][k]) < 0.00025 && p[j][k] != 0.0 ){ + p[j][k] = 0.0; + snpd = qtrue; + } + } + if ( snpd ){ + VectorNormalize( p[j], p[j] ); + VectorAdd( points[j], points[(j+1)%3], cnt ); + VectorScale( cnt, 0.5f, cnt ); + p[j][3] = DotProduct( cnt, p[j] ); + } } - if ( distanceEpsilon > 0 ) { - distanceEpsilon = 0; + + /* make back plane */ + VectorScale( plane, -1.0f, reverse ); + reverse[ 3 ] = -plane[ 3 ]; + reverse[3] += clipDepth; + + /* set up brush sides */ + buildBrush->numsides = 5; + buildBrush->sides[ 0 ].shaderInfo = si; + for ( j = 1; j < buildBrush->numsides; j++ ) { + if ( debugClip ) { + buildBrush->sides[ 0 ].shaderInfo = ShaderInfoForShader( "debugclip2" ); + buildBrush->sides[ j ].shaderInfo = ShaderInfoForShader( "debugclip" ); + } + else { + buildBrush->sides[ j ].shaderInfo = NULL; // don't emit these faces as draw surfaces, should make smaller BSPs; hope this works + } } + VectorCopy( points[0], points[3] ); // for cyclic usage + + buildBrush->sides[ 0 ].planenum = FindFloatPlane( plane, plane[ 3 ], 3, points ); + buildBrush->sides[ 1 ].planenum = FindFloatPlane( p[0], p[0][ 3 ], 2, &points[ 0 ] ); // p[0] contains points[0] and points[1] + buildBrush->sides[ 2 ].planenum = FindFloatPlane( p[1], p[1][ 3 ], 2, &points[ 1 ] ); // p[1] contains points[1] and points[2] + buildBrush->sides[ 3 ].planenum = FindFloatPlane( p[2], p[2][ 3 ], 2, &points[ 2 ] ); // p[2] contains points[2] and points[0] (copied to points[3] + buildBrush->sides[ 4 ].planenum = FindFloatPlane( reverse, reverse[ 3 ], 0, NULL ); } - else{ - buildBrush->detail = qtrue; + + + else if ( ( spf == 128 ) || //EXTRUDE_VERTEX_NORMALS + ( spf == 384 ) ){ //EXTRUDE_VERTEX_NORMALS + PYRAMIDAL_CLIP - vertex normals + don't check for sides, sticking outwards + /* get vertex normals */ + for ( j = 0; j < 3; j++ ) + { + /* get vertex */ + dv = &ds->verts[ ds->indexes[ i + j ] ]; + /* copy normal */ + VectorCopy( dv->normal, Vnorm[ j ] ); + } + + //avg normals for side planes + for ( j = 0; j < 3; j++ ) + { + VectorAdd( Vnorm[ j ], Vnorm[ (j+1)%3 ], Enorm[ j ] ); + VectorNormalize( Enorm[ j ], Enorm[ j ] ); + //check fuer bad ones + VectorSubtract( points[(j+1)%3], points[ j ], cnt ); + CrossProduct( plane, cnt, nrm ); + VectorNormalize( nrm, nrm ); + //check for negative or outside direction + if ( DotProduct( Enorm[ j ], plane ) > 0.1 ){ + if ( ( DotProduct( Enorm[ j ], nrm ) > -0.2 ) || ( spawnFlags & 256 ) ){ + //ok++; + continue; + } + } + //notok++; + //Sys_Printf( "faulty Enormal %i/%i\n", notok, ok ); + //use 45 normal + VectorAdd( plane, nrm, Enorm[ j ] ); + VectorNormalize( Enorm[ j ], Enorm[ j ] ); + } + + /* make side planes */ + for ( j = 0; j < 3; j++ ) + { + VectorSubtract( points[(j+1)%3], points[ j ], nrm ); + CrossProduct( Enorm[ j ], nrm, p[ j ] ); + VectorNormalize( p[ j ], p[ j ] ); + p[j][3] = DotProduct( points[j], p[j] ); + //snap nearly axial side planes + snpd = qfalse; + for ( k = 0; k < 3; k++ ) + { + if ( fabs(p[j][k]) < 0.00025 && p[j][k] != 0.0 ){ + //Sys_Printf( "init plane %6.8f %6.8f %6.8f %6.8f\n", p[j][0], p[j][1], p[j][2], p[j][3]); + p[j][k] = 0.0; + snpd = qtrue; + } + } + if ( snpd ){ + VectorNormalize( p[j], p[j] ); + //Sys_Printf( "nrm plane %6.8f %6.8f %6.8f %6.8f\n", p[j][0], p[j][1], p[j][2], p[j][3]); + VectorAdd( points[j], points[(j+1)%3], cnt ); + VectorScale( cnt, 0.5f, cnt ); + p[j][3] = DotProduct( cnt, p[j] ); + //Sys_Printf( "dst plane %6.8f %6.8f %6.8f %6.8f\n", p[j][0], p[j][1], p[j][2], p[j][3]); + } + } + + /* make back plane */ + VectorScale( plane, -1.0f, reverse ); + reverse[ 3 ] = -plane[ 3 ]; + reverse[3] += clipDepth; + + /* set up brush sides */ + buildBrush->numsides = 5; + buildBrush->sides[ 0 ].shaderInfo = si; + for ( j = 1; j < buildBrush->numsides; j++ ) { + if ( debugClip ) { + buildBrush->sides[ 0 ].shaderInfo = ShaderInfoForShader( "debugclip2" ); + buildBrush->sides[ j ].shaderInfo = ShaderInfoForShader( "debugclip" ); + } + else { + buildBrush->sides[ j ].shaderInfo = NULL; // don't emit these faces as draw surfaces, should make smaller BSPs; hope this works + } + } + VectorCopy( points[0], points[3] ); // for cyclic usage + + buildBrush->sides[ 0 ].planenum = FindFloatPlane( plane, plane[ 3 ], 3, points ); + buildBrush->sides[ 1 ].planenum = FindFloatPlane( p[0], p[0][ 3 ], 2, &points[ 0 ] ); // p[0] contains points[0] and points[1] + buildBrush->sides[ 2 ].planenum = FindFloatPlane( p[1], p[1][ 3 ], 2, &points[ 1 ] ); // p[1] contains points[1] and points[2] + buildBrush->sides[ 3 ].planenum = FindFloatPlane( p[2], p[2][ 3 ], 2, &points[ 2 ] ); // p[2] contains points[2] and points[0] (copied to points[3] + buildBrush->sides[ 4 ].planenum = FindFloatPlane( reverse, reverse[ 3 ], 0, NULL ); } - /* regenerate back points */ - for ( j = 0; j < 3; j++ ) - { - /* get vertex */ - dv = &ds->verts[ ds->indexes[ i + j ] ]; - // shift by some units - VectorMA( dv->xyz, -64.0f, bestNormal, backs[j] ); // 64 prevents roundoff errors a bit + else if ( spf == 8 ){ //EXTRUDE_FACE_NORMALS + + /* make side planes */ + for ( j = 0; j < 3; j++ ) + { + VectorSubtract( points[(j+1)%3], points[ j ], nrm ); + CrossProduct( plane, nrm, p[ j ] ); + VectorNormalize( p[ j ], p[ j ] ); + p[j][3] = DotProduct( points[j], p[j] ); + //snap nearly axial side planes + snpd = qfalse; + for ( k = 0; k < 3; k++ ) + { + if ( fabs(p[j][k]) < 0.00025 && p[j][k] != 0.0 ){ + //Sys_Printf( "init plane %6.8f %6.8f %6.8f %6.8f\n", p[j][0], p[j][1], p[j][2], p[j][3]); + p[j][k] = 0.0; + snpd = qtrue; + } + } + if ( snpd ){ + VectorNormalize( p[j], p[j] ); + //Sys_Printf( "nrm plane %6.8f %6.8f %6.8f %6.8f\n", p[j][0], p[j][1], p[j][2], p[j][3]); + VectorAdd( points[j], points[(j+1)%3], cnt ); + VectorScale( cnt, 0.5f, cnt ); + p[j][3] = DotProduct( cnt, p[j] ); + //Sys_Printf( "dst plane %6.8f %6.8f %6.8f %6.8f\n", p[j][0], p[j][1], p[j][2], p[j][3]); + } + } + + /* make back plane */ + VectorScale( plane, -1.0f, reverse ); + reverse[ 3 ] = -plane[ 3 ]; + reverse[3] += clipDepth; +#if nonax_clip_dbg + for ( j = 0; j < 3; j++ ) + { + for ( k = 0; k < 3; k++ ) + { + if ( fabs(p[j][k]) < 0.00005 && p[j][k] != 0.0 ){ + Sys_Printf( "nonax nrm %6.17f %6.17f %6.17f\n", p[j][0], p[j][1], p[j][2] ); + Sys_Printf( "frm src nrm %6.17f %6.17f %6.17f\n", plane[0], plane[1], plane[2]); + } + } + } +#endif + /* set up brush sides */ + buildBrush->numsides = 5; + buildBrush->sides[ 0 ].shaderInfo = si; + for ( j = 1; j < buildBrush->numsides; j++ ) { + if ( debugClip ) { + buildBrush->sides[ 0 ].shaderInfo = ShaderInfoForShader( "debugclip2" ); + buildBrush->sides[ j ].shaderInfo = ShaderInfoForShader( "debugclip" ); + } + else { + buildBrush->sides[ j ].shaderInfo = NULL; // don't emit these faces as draw surfaces, should make smaller BSPs; hope this works + } + } + VectorCopy( points[0], points[3] ); // for cyclic usage + + buildBrush->sides[ 0 ].planenum = FindFloatPlane( plane, plane[ 3 ], 3, points ); + buildBrush->sides[ 1 ].planenum = FindFloatPlane( p[0], p[0][ 3 ], 2, &points[ 0 ] ); // p[0] contains points[0] and points[1] + buildBrush->sides[ 2 ].planenum = FindFloatPlane( p[1], p[1][ 3 ], 2, &points[ 1 ] ); // p[1] contains points[1] and points[2] + buildBrush->sides[ 3 ].planenum = FindFloatPlane( p[2], p[2][ 3 ], 2, &points[ 2 ] ); // p[2] contains points[2] and points[0] (copied to points[3] + buildBrush->sides[ 4 ].planenum = FindFloatPlane( reverse, reverse[ 3 ], 0, NULL ); } - /* make back plane */ - VectorScale( plane, -1.0f, reverse ); - reverse[ 3 ] = -plane[ 3 ]; - if ( ( spawnFlags & 24 ) != 24 ) { - reverse[3] += DotProduct( bestNormal, plane ) * backPlaneDistance; + + else if ( spf == 256 ){ //PYRAMIDAL_CLIP + + /* calculate center */ + VectorAdd( points[ 0 ], points[ 1 ], cnt ); + VectorAdd( cnt, points[ 2 ], cnt ); + VectorScale( cnt, 0.3333333333333f, cnt ); + + /* make back pyramid point */ + VectorMA( cnt, -clipDepth, plane, cnt ); + + /* make 3 more planes */ + if( PlaneFromPoints( p[0], points[ 2 ], points[ 1 ], cnt ) && + PlaneFromPoints( p[1], points[ 1 ], points[ 0 ], cnt ) && + PlaneFromPoints( p[2], points[ 0 ], points[ 2 ], cnt ) ) { + + //check for dangerous planes + while( (( p[0][0] != 0.0 || p[0][1] != 0.0 ) && fabs(p[0][0]) < 0.00025 && fabs(p[0][1]) < 0.00025) || + (( p[0][0] != 0.0 || p[0][2] != 0.0 ) && fabs(p[0][0]) < 0.00025 && fabs(p[0][2]) < 0.00025) || + (( p[0][2] != 0.0 || p[0][1] != 0.0 ) && fabs(p[0][2]) < 0.00025 && fabs(p[0][1]) < 0.00025) || + (( p[1][0] != 0.0 || p[1][1] != 0.0 ) && fabs(p[1][0]) < 0.00025 && fabs(p[1][1]) < 0.00025) || + (( p[1][0] != 0.0 || p[1][2] != 0.0 ) && fabs(p[1][0]) < 0.00025 && fabs(p[1][2]) < 0.00025) || + (( p[1][2] != 0.0 || p[1][1] != 0.0 ) && fabs(p[1][2]) < 0.00025 && fabs(p[1][1]) < 0.00025) || + (( p[2][0] != 0.0 || p[2][1] != 0.0 ) && fabs(p[2][0]) < 0.00025 && fabs(p[2][1]) < 0.00025) || + (( p[2][0] != 0.0 || p[2][2] != 0.0 ) && fabs(p[2][0]) < 0.00025 && fabs(p[2][2]) < 0.00025) || + (( p[2][2] != 0.0 || p[2][1] != 0.0 ) && fabs(p[2][2]) < 0.00025 && fabs(p[2][1]) < 0.00025) ) { + VectorMA( cnt, -0.1f, plane, cnt ); + // Sys_Printf( "shifting pyramid point\n" ); + PlaneFromPoints( p[0], points[ 2 ], points[ 1 ], cnt ); + PlaneFromPoints( p[1], points[ 1 ], points[ 0 ], cnt ); + PlaneFromPoints( p[2], points[ 0 ], points[ 2 ], cnt ); + } +#if nonax_clip_dbg + for ( j = 0; j < 3; j++ ) + { + for ( k = 0; k < 3; k++ ) + { + if ( fabs(p[j][k]) < 0.00005 && p[j][k] != 0.0 ){ + Sys_Printf( "nonax nrm %6.17f %6.17f %6.17f\n (%6.8f %6.8f %6.8f)\n (%6.8f %6.8f %6.8f)\n (%6.8f %6.8f %6.8f)\n", p[j][0], p[j][1], p[j][2], points[j][0], points[j][1], points[j][2], points[(j+1)%3][0], points[(j+1)%3][1], points[(j+1)%3][2], cnt[0], cnt[1], cnt[2] ); + } + } + } +#endif + /* set up brush sides */ + buildBrush->numsides = 4; + buildBrush->sides[ 0 ].shaderInfo = si; + for ( j = 1; j < buildBrush->numsides; j++ ) { + if ( debugClip ) { + buildBrush->sides[ 0 ].shaderInfo = ShaderInfoForShader( "debugclip2" ); + buildBrush->sides[ j ].shaderInfo = ShaderInfoForShader( "debugclip" ); + } + else { + buildBrush->sides[ j ].shaderInfo = NULL; // don't emit these faces as draw surfaces, should make smaller BSPs; hope this works + } + } + VectorCopy( points[0], points[3] ); // for cyclic usage + + buildBrush->sides[ 0 ].planenum = FindFloatPlane( plane, plane[ 3 ], 3, points ); + buildBrush->sides[ 1 ].planenum = FindFloatPlane( p[0], p[0][ 3 ], 2, &points[ 1 ] ); // p[0] contains points[1] and points[2] + buildBrush->sides[ 2 ].planenum = FindFloatPlane( p[1], p[1][ 3 ], 2, &points[ 0 ] ); // p[1] contains points[0] and points[1] + buildBrush->sides[ 3 ].planenum = FindFloatPlane( p[2], p[2][ 3 ], 2, &points[ 2 ] ); // p[2] contains points[2] and points[0] (copied to points[3] + } + else + { + Sys_Printf( "WARNING: triangle (%6.0f %6.0f %6.0f) (%6.0f %6.0f %6.0f) (%6.0f %6.0f %6.0f) of %s was not autoclipped\n", points[0][0], points[0][1], points[0][2], points[1][0], points[1][1], points[1][2], points[2][0], points[2][1], points[2][2], name ); + free( buildBrush ); + continue; + } } - // that's at least sqrt(1/3) backPlaneDistance, unless in DOWN mode; in DOWN mode, we are screwed anyway if we encounter a plane that's perpendicular to the xy plane) - if ( PlaneFromPoints( pa, points[ 2 ], points[ 1 ], backs[ 1 ] ) && - PlaneFromPoints( pb, points[ 1 ], points[ 0 ], backs[ 0 ] ) && - PlaneFromPoints( pc, points[ 0 ], points[ 2 ], backs[ 2 ] ) ) { + + else if ( ( si->clipModel && !( spf ) ) || ( ( spawnFlags & 8090 ) == 2 ) ){ //default CLIPMODEL + + default_CLIPMODEL: + // axial normal + VectorCopy( plane, bestNormal ); + for ( j = 0; j < 3; j++ ){ + if ( fabs(bestNormal[j]) > fabs(bestNormal[(j+1)%3]) ){ + bestNormal[(j+1)%3] = 0.0; + } + else { + bestNormal[j] = 0.0; + } + } + VectorNormalize( bestNormal, bestNormal ); + + /* make side planes */ + for ( j = 0; j < 3; j++ ) + { + VectorSubtract( points[(j+1)%3], points[ j ], nrm ); + CrossProduct( bestNormal, nrm, p[ j ] ); + VectorNormalize( p[ j ], p[ j ] ); + p[j][3] = DotProduct( points[j], p[j] ); + } + + /* make back plane */ + VectorScale( plane, -1.0f, reverse ); + reverse[ 3 ] = -plane[ 3 ]; + reverse[3] += DotProduct( bestNormal, plane ) * clipDepth; +#if nonax_clip_dbg + for ( j = 0; j < 3; j++ ) + { + for ( k = 0; k < 3; k++ ) + { + if ( fabs(p[j][k]) < 0.00025 && p[j][k] != 0.0 ){ + Sys_Printf( "nonax nrm %6.17f %6.17f %6.17f\n", p[j][0], p[j][1], p[j][2] ); + } + } + } +#endif /* set up brush sides */ buildBrush->numsides = 5; buildBrush->sides[ 0 ].shaderInfo = si; @@ -661,21 +1297,15 @@ void InsertModel( const char *name, int skin, int frame, m4x4_t transform, remap buildBrush->sides[ j ].shaderInfo = NULL; // don't emit these faces as draw surfaces, should make smaller BSPs; hope this works } } + VectorCopy( points[0], points[3] ); // for cyclic usage buildBrush->sides[ 0 ].planenum = FindFloatPlane( plane, plane[ 3 ], 3, points ); - buildBrush->sides[ 1 ].planenum = FindFloatPlane( pa, pa[ 3 ], 2, &points[ 1 ] ); // pa contains points[1] and points[2] - buildBrush->sides[ 2 ].planenum = FindFloatPlane( pb, pb[ 3 ], 2, &points[ 0 ] ); // pb contains points[0] and points[1] - buildBrush->sides[ 3 ].planenum = FindFloatPlane( pc, pc[ 3 ], 2, &points[ 2 ] ); // pc contains points[2] and points[0] (copied to points[3] - buildBrush->sides[ 4 ].planenum = FindFloatPlane( reverse, reverse[ 3 ], 3, backs ); - } - else - { - free( buildBrush ); - continue; + buildBrush->sides[ 1 ].planenum = FindFloatPlane( p[0], p[0][ 3 ], 2, &points[ 0 ] ); // p[0] contains points[0] and points[1] + buildBrush->sides[ 2 ].planenum = FindFloatPlane( p[1], p[1][ 3 ], 2, &points[ 1 ] ); // p[1] contains points[1] and points[2] + buildBrush->sides[ 3 ].planenum = FindFloatPlane( p[2], p[2][ 3 ], 2, &points[ 2 ] ); // p[2] contains points[2] and points[0] (copied to points[3] + buildBrush->sides[ 4 ].planenum = FindFloatPlane( reverse, reverse[ 3 ], 0, NULL ); } - normalEpsilon = normalEpsilon_save; - distanceEpsilon = distanceEpsilon_save; /* add to entity */ if ( CreateBrushWindings( buildBrush ) ) { @@ -686,10 +1316,15 @@ void InsertModel( const char *name, int skin, int frame, m4x4_t transform, remap entities[ mapEntityNum ].numBrushes++; } else{ + Sys_Printf( "WARNING: triangle (%6.0f %6.0f %6.0f) (%6.0f %6.0f %6.0f) (%6.0f %6.0f %6.0f) of %s was not autoclipped\n", points[0][0], points[0][1], points[0][2], points[1][0], points[1][1], points[1][2], points[2][0], points[2][1], points[2][2], name ); free( buildBrush ); } } } + normalEpsilon = normalEpsilon_save; + } + else if ( spawnFlags & 8090 ){ + Sys_Printf( "WARNING: nonexistent clipping mode selected\n" ); } } } @@ -708,7 +1343,7 @@ void AddTriangleModels( entity_t *e ){ const char *target, *model, *value; char shader[ MAX_QPATH ]; shaderInfo_t *celShader; - float temp, baseLightmapScale, lightmapScale; + float temp, baseLightmapScale, lightmapScale, clipDepth; float shadeAngle; int lightmapSampleSize; vec3_t origin, scale, angles; @@ -721,7 +1356,6 @@ void AddTriangleModels( entity_t *e ){ /* note it */ Sys_FPrintf( SYS_VRB, "--- AddTriangleModels ---\n" ); - doingModelClip = qtrue; /* get current brush entity targetname */ if ( e == entities ) { @@ -960,8 +1594,15 @@ void AddTriangleModels( entity_t *e ){ skin = IntForKey( e2, "skin" ); } + clipDepth = clipDepthGlobal; + if ( strcmp( "", ValueForKey( e2, "_clipdepth" ) ) ) { + clipDepth = FloatForKey( e2, "_clipdepth" ); + Sys_Printf( "misc_model has autoclip depth of %.3f\n", clipDepth ); + } + + /* insert the model */ - InsertModel( model, skin, frame, transform, remap, celShader, mapEntityNum, castShadows, recvShadows, spawnFlags, lightmapScale, lightmapSampleSize, shadeAngle ); + InsertModel( model, skin, frame, transform, remap, celShader, mapEntityNum, castShadows, recvShadows, spawnFlags, lightmapScale, lightmapSampleSize, shadeAngle, clipDepth ); /* free shader remappings */ while ( remap != NULL ) @@ -972,5 +1613,4 @@ void AddTriangleModels( entity_t *e ){ } } - doingModelClip = qfalse; } diff --git a/tools/quake3/q3map2/q3map2.h b/tools/quake3/q3map2/q3map2.h index c819d38b..6d2189ce 100644 --- a/tools/quake3/q3map2/q3map2.h +++ b/tools/quake3/q3map2/q3map2.h @@ -1675,7 +1675,7 @@ void PicoPrintFunc( int level, const char *str ); void PicoLoadFileFunc( const char *name, byte **buffer, int *bufSize ); picoModel_t *FindModel( const char *name, int frame ); picoModel_t *LoadModel( const char *name, int frame ); -void InsertModel( const char *name, int skin, int frame, m4x4_t transform, remap_t *remap, shaderInfo_t *celShader, int eNum, int castShadows, int recvShadows, int spawnFlags, float lightmapScale, int lightmapSampleSize, float shadeAngle ); +void InsertModel( const char *name, int skin, int frame, m4x4_t transform, remap_t *remap, shaderInfo_t *celShader, int eNum, int castShadows, int recvShadows, int spawnFlags, float lightmapScale, int lightmapSampleSize, float shadeAngle, float clipDepth ); void AddTriangleModels( entity_t *e ); @@ -2001,8 +2001,6 @@ Q_EXTERN float jitters[ MAX_JITTERS ]; /*can't code*/ Q_EXTERN qboolean doingBSP Q_ASSIGN( qfalse ); -Q_EXTERN qboolean doingModelClip Q_ASSIGN( qfalse ); -Q_EXTERN qboolean snapModelClip Q_ASSIGN( qfalse ); /* commandline arguments */ Q_EXTERN qboolean nocmdline Q_ASSIGN( qfalse ); @@ -2045,6 +2043,7 @@ Q_EXTERN qboolean debugSurfaces Q_ASSIGN( qfalse ); Q_EXTERN qboolean debugInset Q_ASSIGN( qfalse ); Q_EXTERN qboolean debugPortals Q_ASSIGN( qfalse ); Q_EXTERN qboolean debugClip Q_ASSIGN( qfalse ); /* debug model autoclipping */ +Q_EXTERN float clipDepthGlobal Q_ASSIGN( 2.0f ); Q_EXTERN qboolean lightmapTriangleCheck Q_ASSIGN( qfalse ); Q_EXTERN qboolean lightmapExtraVisClusterNudge Q_ASSIGN( qfalse ); Q_EXTERN qboolean lightmapFill Q_ASSIGN( qfalse ); diff --git a/tools/quake3/q3map2/surface.c b/tools/quake3/q3map2/surface.c index 2bc185cd..65a651c4 100644 --- a/tools/quake3/q3map2/surface.c +++ b/tools/quake3/q3map2/surface.c @@ -3278,7 +3278,7 @@ int AddSurfaceModelsToTriangle_r( mapDrawSurface_t *ds, surfaceModel_t *model, b } /* insert the model */ - InsertModel( (char *) model->model, 0, 0, transform, NULL, ds->celShader, ds->entityNum, ds->castShadows, ds->recvShadows, 0, ds->lightmapScale, 0, 0 ); + InsertModel( (char *) model->model, 0, 0, transform, NULL, ds->celShader, ds->entityNum, ds->castShadows, ds->recvShadows, 0, ds->lightmapScale, 0, 0, clipDepthGlobal ); /* return to sender */ return 1; diff --git a/tools/quake3/q3map2/surface_foliage.c b/tools/quake3/q3map2/surface_foliage.c index 042c547a..fc3ce072 100644 --- a/tools/quake3/q3map2/surface_foliage.c +++ b/tools/quake3/q3map2/surface_foliage.c @@ -281,7 +281,7 @@ void Foliage( mapDrawSurface_t *src ){ m4x4_scale_for_vec3( transform, scale ); /* add the model to the bsp */ - InsertModel( foliage->model, 0, 0, transform, NULL, NULL, src->entityNum, src->castShadows, src->recvShadows, 0, src->lightmapScale, 0, 0 ); + InsertModel( foliage->model, 0, 0, transform, NULL, NULL, src->entityNum, src->castShadows, src->recvShadows, 0, src->lightmapScale, 0, 0, clipDepthGlobal ); /* walk each new surface */ for ( i = oldNumMapDrawSurfs; i < numMapDrawSurfs; i++ )