/* ================ R_LoadLightGrid ================ */ void R_LoadLightGrid( lump_t *l ) { int i, j; vec3_t maxs; world_t *w; float *wMins, *wMaxs; w = &s_worldData; w->lightGridInverseSize[0] = 1.0 / w->lightGridSize[0]; w->lightGridInverseSize[1] = 1.0 / w->lightGridSize[1]; w->lightGridInverseSize[2] = 1.0 / w->lightGridSize[2]; wMins = w->bmodels[0].bounds[0]; wMaxs = w->bmodels[0].bounds[1]; for ( i = 0 ; i < 3 ; i++ ) { w->lightGridOrigin[i] = w->lightGridSize[i] * ceil( wMins[i] / w->lightGridSize[i] ); maxs[i] = w->lightGridSize[i] * floor( wMaxs[i] / w->lightGridSize[i] ); w->lightGridBounds[i] = (maxs[i] - w->lightGridOrigin[i])/w->lightGridSize[i] + 1; } int numGridDataElements = l->filelen / sizeof(*w->lightGridData); w->lightGridData = (mgrid_t *)ri.Hunk_Alloc( l->filelen, qfalse ); memcpy( w->lightGridData, (void *)(fileBase + l->fileofs), l->filelen ); // deal with overbright bits for ( i = 0 ; i < numGridDataElements ; i++ ) { for(j=0; j<MAXLIGHTMAPS; j++) { R_ColorShiftLightingBytes(w->lightGridData[i].ambientLight[j]); R_ColorShiftLightingBytes(w->lightGridData[i].directLight[j]); } } }
/* =============== ParseTriSurf =============== */ static void ParseTriSurf( dsurface_t *ds, mapVert_t *verts, msurface_t *surf, int *indexes ) { srfTriangles_t *tri; int i, j, k; int numVerts, numIndexes; // get fog volume surf->fogIndex = LittleLong( ds->fogNum ) + 1; // get shader surf->shader = ShaderForShaderNum( ds->shaderNum, lightmapsVertex, ds->lightmapStyles, ds->vertexStyles ); if ( r_singleShader->integer && !surf->shader->isSky ) { surf->shader = tr.defaultShader; } numVerts = LittleLong( ds->numVerts ); numIndexes = LittleLong( ds->numIndexes ); tri = (srfTriangles_t *) ri.Hunk_Alloc( sizeof( *tri ) + numVerts * sizeof( tri->verts[0] ) + numIndexes * sizeof( tri->indexes[0] ), qtrue ); tri->surfaceType = SF_TRIANGLES; tri->numVerts = numVerts; tri->numIndexes = numIndexes; tri->verts = (drawVert_t *)(tri + 1); tri->indexes = (int *)(tri->verts + tri->numVerts ); surf->data = (surfaceType_t *)tri; // copy vertexes verts += LittleLong( ds->firstVert ); ClearBounds( tri->bounds[0], tri->bounds[1] ); for ( i = 0 ; i < numVerts ; i++ ) { for ( j = 0 ; j < 3 ; j++ ) { tri->verts[i].xyz[j] = LittleFloat( verts[i].xyz[j] ); tri->verts[i].normal[j] = LittleFloat( verts[i].normal[j] ); } AddPointToBounds( tri->verts[i].xyz, tri->bounds[0], tri->bounds[1] ); for ( j = 0 ; j < 2 ; j++ ) { tri->verts[i].st[j] = LittleFloat( verts[i].st[j] ); for(k=0; k<MAXLIGHTMAPS; k++) { tri->verts[i].lightmap[k][j] = LittleFloat( verts[i].lightmap[k][j] ); } } for(k=0; k<MAXLIGHTMAPS; k++) { R_ColorShiftLightingBytes( verts[i].color[k], tri->verts[i].color[k] ); } } // copy indexes indexes += LittleLong( ds->firstIndex ); for ( i = 0 ; i < numIndexes ; i++ ) { tri->indexes[i] = LittleLong( indexes[i] ); if ( tri->indexes[i] < 0 || tri->indexes[i] >= numVerts ) { ri.Error( ERR_DROP, "Bad index in triangle surface" ); } } }
/* =============== ParseMesh =============== */ static void ParseMesh ( dsurface_t *ds, mapVert_t *verts, msurface_t *surf) { srfGridMesh_t *grid; int i, j, k; int width, height, numPoints; MAC_STATIC drawVert_t points[MAX_PATCH_SIZE*MAX_PATCH_SIZE]; int lightmapNum[MAXLIGHTMAPS]; vec3_t bounds[2]; vec3_t tmpVec; static surfaceType_t skipData = SF_SKIP; for(i=0; i<MAXLIGHTMAPS; i++) { lightmapNum[i] = LittleLong( ds->lightmapNum[i] ); } // get fog volume surf->fogIndex = LittleLong( ds->fogNum ) + 1; // get shader value surf->shader = ShaderForShaderNum( ds->shaderNum, lightmapNum, ds->lightmapStyles, ds->vertexStyles ); if ( r_singleShader->integer && !surf->shader->isSky ) { surf->shader = tr.defaultShader; } // we may have a nodraw surface, because they might still need to // be around for movement clipping if ( s_worldData.shaders[ LittleLong( ds->shaderNum ) ].surfaceFlags & SURF_NODRAW ) { surf->data = &skipData; return; } width = LittleLong( ds->patchWidth ); height = LittleLong( ds->patchHeight ); verts += LittleLong( ds->firstVert ); numPoints = width * height; for ( i = 0 ; i < numPoints ; i++ ) { for ( j = 0 ; j < 3 ; j++ ) { points[i].xyz[j] = LittleFloat( verts[i].xyz[j] ); points[i].normal[j] = LittleFloat( verts[i].normal[j] ); } for ( j = 0 ; j < 2 ; j++ ) { points[i].st[j] = LittleFloat( verts[i].st[j] ); for(k=0; k<MAXLIGHTMAPS; k++) { points[i].lightmap[k][j] = LittleFloat( verts[i].lightmap[k][j] ); } } for(k=0; k<MAXLIGHTMAPS; k++) { R_ColorShiftLightingBytes( verts[i].color[k], points[i].color[k] ); } } // pre-tesseleate grid = R_SubdividePatchToGrid( width, height, points ); surf->data = (surfaceType_t *)grid; // copy the level of detail origin, which is the center // of the group of all curves that must subdivide the same // to avoid cracking for ( i = 0 ; i < 3 ; i++ ) { bounds[0][i] = LittleFloat( ds->lightmapVecs[0][i] ); bounds[1][i] = LittleFloat( ds->lightmapVecs[1][i] ); } VectorAdd( bounds[0], bounds[1], bounds[1] ); VectorScale( bounds[1], 0.5f, grid->lodOrigin ); VectorSubtract( bounds[0], grid->lodOrigin, tmpVec ); grid->lodRadius = VectorLength( tmpVec ); }
/* =============== ParseFace =============== */ static void ParseFace( dsurface_t *ds, mapVert_t *verts, msurface_t *surf, int *indexes, byte *&pFaceDataBuffer) { int i, j, k; srfSurfaceFace_t *cv; int numPoints, numIndexes; int lightmapNum[MAXLIGHTMAPS]; int sfaceSize, ofsIndexes; for(i=0; i<MAXLIGHTMAPS; i++) { lightmapNum[i] = LittleLong( ds->lightmapNum[i] ); } // get fog volume surf->fogIndex = LittleLong( ds->fogNum ) + 1; // get shader value surf->shader = ShaderForShaderNum( ds->shaderNum, lightmapNum, ds->lightmapStyles, ds->vertexStyles ); if ( r_singleShader->integer && !surf->shader->isSky ) { surf->shader = tr.defaultShader; } numPoints = LittleLong( ds->numVerts ); if (numPoints > MAX_FACE_POINTS) { ri.Printf( PRINT_DEVELOPER, "MAX_FACE_POINTS exceeded: %i\n", numPoints); } numIndexes = LittleLong( ds->numIndexes ); // create the srfSurfaceFace_t sfaceSize = ( int ) &((srfSurfaceFace_t *)0)->points[numPoints]; ofsIndexes = sfaceSize; sfaceSize += sizeof( int ) * numIndexes; cv = (srfSurfaceFace_t *) pFaceDataBuffer;//ri.Hunk_Alloc( sfaceSize ); pFaceDataBuffer += sfaceSize; // :-) cv->surfaceType = SF_FACE; cv->numPoints = numPoints; cv->numIndices = numIndexes; cv->ofsIndices = ofsIndexes; verts += LittleLong( ds->firstVert ); for ( i = 0 ; i < numPoints ; i++ ) { for ( j = 0 ; j < 3 ; j++ ) { cv->points[i][j] = LittleFloat( verts[i].xyz[j] ); } for ( j = 0 ; j < 2 ; j++ ) { cv->points[i][3+j] = LittleFloat( verts[i].st[j] ); for(k=0; k<MAXLIGHTMAPS; k++) { cv->points[i][VERTEX_LM+j+(k*2)] = LittleFloat( verts[i].lightmap[k][j] ); } } for(k=0; k<MAXLIGHTMAPS; k++) { R_ColorShiftLightingBytes( verts[i].color[k], (byte *)&cv->points[i][VERTEX_COLOR+k] ); } } indexes += LittleLong( ds->firstIndex ); for ( i = 0 ; i < numIndexes ; i++ ) { ((int *)((byte *)cv + cv->ofsIndices ))[i] = LittleLong( indexes[ i ] ); } // take the plane information from the lightmap vector for ( i = 0 ; i < 3 ; i++ ) { cv->plane.normal[i] = LittleFloat( ds->lightmapVecs[2][i] ); } cv->plane.dist = DotProduct( cv->points[0], cv->plane.normal ); SetPlaneSignbits( &cv->plane ); cv->plane.type = PlaneTypeForNormal( cv->plane.normal ); surf->data = (surfaceType_t *)cv; }
static void R_LoadLightmaps( lump_t *l, const char *psMapName ) { byte *buf, *buf_p; int len; MAC_STATIC byte image[LIGHTMAP_SIZE*LIGHTMAP_SIZE*4]; int i, j; float maxIntensity = 0; double sumIntensity = 0; len = l->filelen; if ( !len ) { return; } buf = fileBase + l->fileofs; // we are about to upload textures R_SyncRenderThread(); // create all the lightmaps tr.numLightmaps = len / (LIGHTMAP_SIZE * LIGHTMAP_SIZE * 3); // if we are in r_vertexLight mode, we don't need the lightmaps at all if ( r_vertexLight->integer ) { return; } char sMapName[MAX_QPATH]; COM_StripExtension(psMapName,sMapName); // will already by MAX_QPATH legal, so no length check for ( i = 0 ; i < tr.numLightmaps ; i++ ) { // expand the 24 bit on-disk to 32 bit buf_p = buf + i * LIGHTMAP_SIZE*LIGHTMAP_SIZE * 3; if ( r_lightmap->integer == 2 ) { // color code by intensity as development tool (FIXME: check range) for ( j = 0; j < LIGHTMAP_SIZE * LIGHTMAP_SIZE; j++ ) { float r = buf_p[j*3+0]; float g = buf_p[j*3+1]; float b = buf_p[j*3+2]; float intensity; float out[3]; intensity = 0.33f * r + 0.685 * g + 0.063f * b; if ( intensity > 255 ) intensity = 1.0f; else intensity /= 255.0f; if ( intensity > maxIntensity ) maxIntensity = intensity; HSVtoRGB( intensity, 1.00, 0.50, out ); image[j*4+0] = out[0] * 255; image[j*4+1] = out[1] * 255; image[j*4+2] = out[2] * 255; image[j*4+3] = 255; sumIntensity += intensity; } } else { for ( j = 0 ; j < LIGHTMAP_SIZE*LIGHTMAP_SIZE ; j++ ) { R_ColorShiftLightingBytes( &buf_p[j*3], &image[j*4] ); image[j*4+3] = 255; } } tr.lightmaps[i] = R_CreateImage( va("*%s/lightmap%d",sMapName,i), image, LIGHTMAP_SIZE, LIGHTMAP_SIZE, qfalse, qfalse, r_ext_compressed_lightmaps->integer, GL_CLAMP); } if ( r_lightmap->integer == 2 ) { ri.Printf( PRINT_ALL, "Brightest lightmap value: %d\n", ( int ) ( maxIntensity * 255 ) ); } }
void R_RMGInit(void) { char newSky[MAX_QPATH]; char newFog[MAX_QPATH]; shader_t *fog; fog_t *gfog; mgrid_t *grid; char temp[MAX_QPATH]; int i; unsigned short *pos; ri.Cvar_VariableStringBuffer("RMG_sky", newSky, MAX_QPATH); // Get sunlight - this should set up all the sunlight data R_FindShader( newSky, lightmapsNone, stylesDefault, qfalse ); // Remap sky R_RemapShader("textures/tools/_sky", newSky, NULL); // Fill in the lightgrid with sunlight if(tr.world->lightGridData) { grid = tr.world->lightGridData; grid->ambientLight[0][0] = (byte)Com_Clampi(0, 255, tr.sunAmbient[0] * 255.0f); grid->ambientLight[0][1] = (byte)Com_Clampi(0, 255, tr.sunAmbient[1] * 255.0f); grid->ambientLight[0][2] = (byte)Com_Clampi(0, 255, tr.sunAmbient[2] * 255.0f); R_ColorShiftLightingBytes(grid->ambientLight[0], grid->ambientLight[0]); grid->directLight[0][0] = (byte)Com_Clampi(0, 255, tr.sunLight[0]); grid->directLight[0][1] = (byte)Com_Clampi(0, 255, tr.sunLight[1]); grid->directLight[0][2] = (byte)Com_Clampi(0, 255, tr.sunLight[2]); R_ColorShiftLightingBytes(grid->directLight[0], grid->directLight[0]); NormalToLatLong(tr.sunDirection, grid->latLong); pos = tr.world->lightGridArray; for(i=0;i<tr.world->numGridArrayElements;i++) { *pos = 0; pos++; } } // Override the global fog with the defined one if(tr.world->globalFog != -1) { ri.Cvar_VariableStringBuffer("RMG_fog", newFog, MAX_QPATH); fog = R_FindShader( newFog, lightmapsNone, stylesDefault, qfalse); if (fog != tr.defaultShader) { gfog = tr.world->fogs + tr.world->globalFog; gfog->parms = *fog->fogParms; if (gfog->parms.depthForOpaque) { gfog->tcScale = 1.0f / ( gfog->parms.depthForOpaque * 8.0f ); tr.distanceCull = gfog->parms.depthForOpaque; tr.distanceCullSquared = tr.distanceCull * tr.distanceCull; ri.Cvar_Set("RMG_distancecull", va("%f", tr.distanceCull)); } else { gfog->tcScale = 1.0f; } gfog->colorInt = ColorBytes4 ( gfog->parms.color[0], gfog->parms.color[1], gfog->parms.color[2], 1.0f ); } } ri.Cvar_VariableStringBuffer("RMG_weather", temp, MAX_QPATH); // Set up any weather effects switch(atol(temp)) { case 0: break; case 1: RE_WorldEffectCommand("rain init 1000"); RE_WorldEffectCommand("rain outside"); break; case 2: RE_WorldEffectCommand("snow init 1000 outside"); RE_WorldEffectCommand("snow outside"); break; } }
/* =============== ParseTriSurf =============== */ static void ParseTriSurf( dsurface_t *ds, mapVert_t *verts, msurface_t *surf, int *indexes, world_t &worldData, int index ) { srfTriangles_t *tri; int i, j, k; int numVerts, numIndexes; // get fog volume surf->fogIndex = LittleLong( ds->fogNum ) + 1; if (index && !surf->fogIndex && tr.world && tr.world->globalFog != -1) { surf->fogIndex = worldData.globalFog; } // get shader surf->shader = ShaderForShaderNum( ds->shaderNum, lightmapsVertex, ds->lightmapStyles, ds->vertexStyles, worldData ); if ( r_singleShader->integer && !surf->shader->sky ) { surf->shader = tr.defaultShader; } numVerts = LittleLong( ds->numVerts ); numIndexes = LittleLong( ds->numIndexes ); if ( numVerts >= SHADER_MAX_VERTEXES ) { Com_Error(ERR_DROP, "ParseTriSurf: verts > MAX (%d > %d) on misc_model %s", numVerts, SHADER_MAX_VERTEXES, surf->shader->name ); } if ( numIndexes >= SHADER_MAX_INDEXES ) { Com_Error(ERR_DROP, "ParseTriSurf: indices > MAX (%d > %d) on misc_model %s", numIndexes, SHADER_MAX_INDEXES, surf->shader->name ); } tri = (srfTriangles_t *) R_Malloc( sizeof( *tri ) + numVerts * sizeof( tri->verts[0] ) + numIndexes * sizeof( tri->indexes[0] ), TAG_HUNKMISCMODELS, qfalse ); tri->dlightBits = 0; //JIC tri->surfaceType = SF_TRIANGLES; tri->numVerts = numVerts; tri->numIndexes = numIndexes; tri->verts = (drawVert_t *)(tri + 1); tri->indexes = (int *)(tri->verts + tri->numVerts ); surf->data = (surfaceType_t *)tri; // copy vertexes verts += LittleLong( ds->firstVert ); ClearBounds( tri->bounds[0], tri->bounds[1] ); for ( i = 0 ; i < numVerts ; i++ ) { for ( j = 0 ; j < 3 ; j++ ) { tri->verts[i].xyz[j] = LittleFloat( verts[i].xyz[j] ); tri->verts[i].normal[j] = LittleFloat( verts[i].normal[j] ); } AddPointToBounds( tri->verts[i].xyz, tri->bounds[0], tri->bounds[1] ); for ( j = 0 ; j < 2 ; j++ ) { tri->verts[i].st[j] = LittleFloat( verts[i].st[j] ); for(k=0;k<MAXLIGHTMAPS;k++) { tri->verts[i].lightmap[k][j] = LittleFloat( verts[i].lightmap[k][j] ); } } for(k=0;k<MAXLIGHTMAPS;k++) { R_ColorShiftLightingBytes( verts[i].color[k], tri->verts[i].color[k] ); } } // copy indexes indexes += LittleLong( ds->firstIndex ); for ( i = 0 ; i < numIndexes ; i++ ) { tri->indexes[i] = LittleLong( indexes[i] ); if ( tri->indexes[i] < 0 || tri->indexes[i] >= numVerts ) { Com_Error( ERR_DROP, "Bad index in triangle surface" ); } } }
static void R_LoadLightmaps( lump_t *l, const char *psMapName, world_t &worldData ) { byte *buf, *buf_p; int len; byte image[LIGHTMAP_SIZE*LIGHTMAP_SIZE*4]; int i, j; float maxIntensity = 0; double sumIntensity = 0; int count; if (&worldData == &s_worldData) { tr.numLightmaps = 0; } len = l->filelen; if ( !len ) { return; } buf = fileBase + l->fileofs; // we are about to upload textures R_IssuePendingRenderCommands(); // // create all the lightmaps worldData.startLightMapIndex = tr.numLightmaps; count = len / (LIGHTMAP_SIZE * LIGHTMAP_SIZE * 3); tr.numLightmaps += count; // if we are in r_vertexLight mode, we don't need the lightmaps at all if ( r_vertexLight->integer ) { return; } char sMapName[MAX_QPATH]; COM_StripExtension(psMapName,sMapName, sizeof(sMapName)); for ( i = 0 ; i < count ; i++ ) { // expand the 24 bit on-disk to 32 bit buf_p = buf + i * LIGHTMAP_SIZE*LIGHTMAP_SIZE * 3; if ( r_lightmap->integer == 2 ) { // color code by intensity as development tool (FIXME: check range) for ( j = 0; j < LIGHTMAP_SIZE * LIGHTMAP_SIZE; j++ ) { float r = buf_p[j*3+0]; float g = buf_p[j*3+1]; float b = buf_p[j*3+2]; float intensity; float out[3] = {0.0f, 0.0f, 0.0f}; intensity = 0.33f * r + 0.685f * g + 0.063f * b; if ( intensity > 255 ) intensity = 1.0f; else intensity /= 255.0f; if ( intensity > maxIntensity ) maxIntensity = intensity; HSVtoRGB( intensity, 1.00, 0.50, out ); image[j*4+0] = out[0] * 255; image[j*4+1] = out[1] * 255; image[j*4+2] = out[2] * 255; image[j*4+3] = 255; sumIntensity += intensity; } } else { for ( j = 0 ; j < LIGHTMAP_SIZE * LIGHTMAP_SIZE; j++ ) { R_ColorShiftLightingBytes( &buf_p[j*3], &image[j*4] ); image[j*4+3] = 255; } } tr.lightmaps[worldData.startLightMapIndex+i] = R_CreateImage( va("$%s/lightmap%d", sMapName, worldData.startLightMapIndex+i), image, LIGHTMAP_SIZE, LIGHTMAP_SIZE, GL_RGBA, qfalse, qfalse, (qboolean)(r_ext_compressed_lightmaps->integer != 0), GL_CLAMP); } if ( r_lightmap->integer == 2 ) { ri.Printf( PRINT_ALL, "Brightest lightmap value: %d\n", ( int ) ( maxIntensity * 255 ) ); } }