void CreateMapFogs( void ){ int i; entity_t *entity; brush_t *brush; fog_t *fog; vec3_t invFogDir; const char *globalFog; /* skip? */ if ( nofog ) { return; } /* note it */ Sys_FPrintf( SYS_VRB, "--- CreateMapFogs ---\n" ); /* walk entities */ for ( i = 0; i < numEntities; i++ ) { /* get entity */ entity = &entities[ i ]; /* walk entity brushes */ for ( brush = entity->brushes; brush != NULL; brush = brush->next ) { /* ignore non-fog brushes */ if ( brush->contentShader->fogParms == qfalse ) { continue; } /* test limit */ if ( numMapFogs >= MAX_MAP_FOGS ) { Error( "Exceeded MAX_MAP_FOGS (%d)", MAX_MAP_FOGS ); } /* set up fog */ fog = &mapFogs[ numMapFogs++ ]; fog->si = brush->contentShader; fog->brush = brush; fog->visibleSide = -1; /* if shader specifies an explicit direction, then find a matching brush side with an opposed normal */ if ( VectorLength( fog->si->fogDir ) ) { /* flip it */ VectorScale( fog->si->fogDir, -1.0f, invFogDir ); /* find the brush side */ for ( i = 0; i < brush->numsides; i++ ) { if ( VectorCompare( invFogDir, mapplanes[ brush->sides[ i ].planenum ].normal ) ) { fog->visibleSide = i; //% Sys_Printf( "Brush num: %d Side num: %d\n", fog->brushNum, fog->visibleSide ); break; } } } } } /* ydnar: global fog */ globalFog = ValueForKey( &entities[ 0 ], "_fog" ); if ( globalFog[ 0 ] == '\0' ) { globalFog = ValueForKey( &entities[ 0 ], "fog" ); } if ( globalFog[ 0 ] != '\0' ) { /* test limit */ if ( numMapFogs >= MAX_MAP_FOGS ) { Error( "Exceeded MAX_MAP_FOGS (%d) trying to add global fog", MAX_MAP_FOGS ); } /* note it */ Sys_FPrintf( SYS_VRB, "Map has global fog shader %s\n", globalFog ); /* set up fog */ fog = &mapFogs[ numMapFogs++ ]; fog->si = ShaderInfoForShaderNull( globalFog ); if ( fog->si == NULL ) { Error( "Invalid shader \"%s\" referenced trying to add global fog", globalFog ); } fog->brush = NULL; fog->visibleSide = -1; /* set as default fog */ defaultFogNum = numMapFogs - 1; /* mark all worldspawn brushes as fogged */ for ( brush = entities[ 0 ].brushes; brush != NULL; brush = brush->next ) ApplySurfaceParm( "fog", &brush->contentFlags, NULL, &brush->compileFlags ); } /* emit some stats */ Sys_FPrintf( SYS_VRB, "%9d fogs\n", numMapFogs ); }
void SetupTraceNodes(void) { /* note it */ Sys_FPrintf(SYS_VRB, "--- SetupTraceNodes ---\n"); /* find nodraw bit */ noDrawContentFlags = noDrawSurfaceFlags = noDrawCompileFlags = 0; ApplySurfaceParm("nodraw", &noDrawContentFlags, &noDrawSurfaceFlags, &noDrawCompileFlags); /* create the baseline raytracing tree from the bsp tree */ headNodeNum = SetupTraceNodes_r(0); /* create outside node for skybox surfaces */ skyboxNodeNum = AllocTraceNode(); /* populate the tree with triangles from the world and shadow casting entities */ PopulateTraceNodes(); /* create the raytracing bsp */ #if 1 // Tr3B: this requires ridiculous much memory if(loMem == qfalse) { SubdivideTraceNode_r(headNodeNum, 0); SubdivideTraceNode_r(skyboxNodeNum, 0); } #endif /* create triangles from the trace windings */ TriangulateTraceNode_r(headNodeNum); TriangulateTraceNode_r(skyboxNodeNum); /* emit some stats */ //% Sys_FPrintf( SYS_VRB, "%9d original triangles\n", numOriginalTriangles ); Sys_FPrintf(SYS_VRB, "%9d trace windings (%.2fMB)\n", numTraceWindings, (float)(numTraceWindings * sizeof(*traceWindings)) / (1024.0f * 1024.0f)); Sys_FPrintf(SYS_VRB, "%9d trace triangles (%.2fMB)\n", numTraceTriangles, (float)(numTraceTriangles * sizeof(*traceTriangles)) / (1024.0f * 1024.0f)); Sys_FPrintf(SYS_VRB, "%9d trace nodes (%.2fMB)\n", numTraceNodes, (float)(numTraceNodes * sizeof(*traceNodes)) / (1024.0f * 1024.0f)); Sys_FPrintf(SYS_VRB, "%9d leaf nodes (%.2fMB)\n", numTraceLeafNodes, (float)(numTraceLeafNodes * sizeof(*traceNodes)) / (1024.0f * 1024.0f)); //% Sys_FPrintf( SYS_VRB, "%9d average triangles per leaf node\n", numTraceTriangles / numTraceLeafNodes ); Sys_FPrintf(SYS_VRB, "%9d average windings per leaf node\n", numTraceWindings / (numTraceLeafNodes + 1)); Sys_FPrintf(SYS_VRB, "%9d max trace depth\n", maxTraceDepth); /* free trace windings */ free(traceWindings); numTraceWindings = 0; maxTraceWindings = 0; deadWinding = -1; /* debug code: write out trace triangles to an alias obj file */ #if 0 { int i, j; FILE *file; char filename[1024]; traceWinding_t *tw; /* open the file */ strcpy(filename, source); StripExtension(filename); strcat(filename, ".lin"); Sys_Printf("Opening light trace file %s...\n", filename); file = fopen(filename, "w"); if(file == NULL) Error("Error opening %s for writing", filename); /* walk node list */ for(i = 0; i < numTraceWindings; i++) { tw = &traceWindings[i]; for(j = 0; j < tw->numVerts + 1; j++) fprintf(file, "%f %f %f\n", tw->v[j % tw->numVerts].xyz[0], tw->v[j % tw->numVerts].xyz[1], tw->v[j % tw->numVerts].xyz[2]); } /* close it */ fclose(file); } #endif }
void RadLight( int num ) { int lightmapNum; float scale, subdivide; int contentFlags, surfaceFlags, compileFlags; bspDrawSurface_t *ds; surfaceInfo_t *info; rawLightmap_t *lm; shaderInfo_t *si; clipWork_t cw; /* get drawsurface, lightmap, and shader info */ ds = &bspDrawSurfaces[ num ]; info = &surfaceInfos[ num ]; lm = info->lm; si = info->si; scale = si->bounceScale; /* find nodraw bit */ contentFlags = surfaceFlags = compileFlags = 0; ApplySurfaceParm( "nodraw", &contentFlags, &surfaceFlags, &compileFlags ); /* early outs? */ if( scale <= 0.0f || (si->compileFlags & C_SKY) || si->autosprite || (bspShaders[ ds->shaderNum ].contentFlags & contentFlags) || (bspShaders[ ds->shaderNum ].surfaceFlags & surfaceFlags) || (si->compileFlags & compileFlags) ) return; /* determine how much we need to chop up the surface */ if( si->lightSubdivide ) subdivide = si->lightSubdivide; else subdivide = diffuseSubdivide; /* inc counts */ numDiffuseSurfaces++; /* iterate through styles (this could be more efficient, yes) */ for( lightmapNum = 0; lightmapNum < MAX_LIGHTMAPS; lightmapNum++ ) { /* switch on type */ if( ds->lightmapStyles[ lightmapNum ] != LS_NONE && ds->lightmapStyles[ lightmapNum ] != LS_UNUSED ) { switch( ds->surfaceType ) { case MST_PLANAR: case MST_TRIANGLE_SOUP: RadLightForTriangles( num, lightmapNum, lm, si, scale, subdivide, &cw ); break; case MST_PATCH: RadLightForPatch( num, lightmapNum, lm, si, scale, subdivide, &cw ); break; default: break; } } } }