static void CL_RunMapParticles (void) { mapParticle_t *mp; ptl_t *ptl; int i; for (i = 0, mp = mapParticles; i < cl.numMapParticles; i++, mp++) if (mp->nextTime && cl.time >= mp->nextTime) { /* spawn a new particle */ ptl = CL_ParticleSpawn(mp->ptl, mp->levelflags, mp->origin); if (!ptl) { Com_Printf(S_COLOR_YELLOW "Could not spawn particle '%s'\n", mp->ptl); mp->nextTime = 0; continue; } /* init the particle */ CL_ParseMapParticle(ptl, mp->info, false); CL_ParticleFunction(ptl, ptl->ctrl->init); CL_ParseMapParticle(ptl, mp->info, true); /* prepare next spawning */ if (Vector2NotEmpty(mp->wait)) mp->nextTime += mp->wait[0] + mp->wait[1] * frand(); else mp->nextTime = 0; } }
/** * @brief Export all the faces for one particular lightmap (day or night) * @param path The path to write the files into * @param name The name of the map to export the lightmap for * @param day @c true to export the day lightmap data, @c false to export the night lightmap data */ static void ExportLightmap (const char* path, const char* name, bool day) { const int lightmapIndex = day ? 1 : 0; const byte* bspLightBytes = curTile->lightdata[lightmapIndex]; const byte quant = *bspLightBytes; const int scale = 1 << quant; for (int i = 0; i < curTile->numfaces; i++) { const dBspSurface_t* face = &curTile->faces[i]; const byte* lightmap = bspLightBytes + face->lightofs[lightmapIndex]; vec2_t texSize; CalcTextureSize(face, texSize, scale); /* write a tga image out */ if (Vector2NotEmpty(texSize)) { char filename[MAX_QPATH]; Com_sprintf(filename, sizeof(filename), "%s/%s_lightmap_%04d%c.tga", path, name, i, day ? 'd' : 'n'); Com_Printf("Writing %s (%.0fx%.0f)\n", filename, texSize[0], texSize[1]); WriteTGA24(filename, lightmap, texSize[0], texSize[1], 0); Com_sprintf(filename, sizeof(filename), "%s/%s_direction_%04d%c.tga", path, name, i, day ? 'd' : 'n'); Com_Printf("Writing %s (%.0fx%.0f)\n", filename, texSize[0], texSize[1]); WriteTGA24(filename, lightmap, texSize[0], texSize[1], 3); } } }
/** @note Defaults should match those of ufo2map, or lighting will be inconsistent between world and models */ static void SP_worldspawn (const localEntityParse_t* entData) { /* maximum level */ cl.mapMaxLevel = entData->maxLevel; if (GAME_IsMultiplayer()) { if (cl_teamnum->integer > entData->maxMultiplayerTeams || cl_teamnum->integer <= TEAM_CIVILIAN) { Com_Printf("The selected team is not usable. " "The map doesn't support %i teams but only %i teams\n", cl_teamnum->integer, entData->maxMultiplayerTeams); Cvar_SetValue("cl_teamnum", TEAM_DEFAULT); Com_Printf("Set teamnum to %i\n", cl_teamnum->integer); } } /** @todo - make sun position/color vary based on local time at location? */ const int dayLightmap = CL_GetConfigStringInteger(CS_LIGHTMAP); /** @note Some vectors have exra elements to comply with mathlib and/or OpenGL conventions, but handled as shorter ones */ vec3_t sunAngles; vec4_t sunColor; vec_t sunIntensity; if (dayLightmap) { /* set defaults for daylight */ Vector4Set(refdef.ambientColor, 0.26, 0.26, 0.26, 1.0); sunIntensity = 280; VectorSet(sunAngles, -75, 100, 0); Vector4Set(sunColor, 0.90, 0.75, 0.65, 1.0); /* override defaults with data from worldspawn entity, if any */ if (VectorNotEmpty(entData->ambientDayColor)) VectorCopy(entData->ambientDayColor, refdef.ambientColor); if (entData->dayLight) sunIntensity = entData->dayLight; if (Vector2NotEmpty(entData->daySunAngles)) Vector2Copy(entData->daySunAngles, sunAngles); if (VectorNotEmpty(entData->daySunColor)) VectorCopy(entData->daySunColor, sunColor); Vector4Set(refdef.sunSpecularColor, 1.0, 1.0, 0.9, 1); } else { /* set defaults for night light */ Vector4Set(refdef.ambientColor, 0.16, 0.16, 0.17, 1.0); sunIntensity = 15; VectorSet(sunAngles, -80, 220, 0); Vector4Set(sunColor, 0.25, 0.25, 0.35, 1.0); /* override defaults with data from worldspawn entity, if any */ if (VectorNotEmpty(entData->ambientNightColor)) VectorCopy(entData->ambientNightColor, refdef.ambientColor); if (entData->nightLight) sunIntensity = entData->nightLight; if (Vector2NotEmpty(entData->nightSunAngles)) Vector2Copy(entData->nightSunAngles, sunAngles); if (VectorNotEmpty(entData->nightSunColor)) VectorCopy(entData->nightSunColor, sunColor); Vector4Set(refdef.sunSpecularColor, 0.5, 0.5, 0.7, 1); } ColorNormalize(sunColor, sunColor); VectorScale(sunColor, sunIntensity/255.0, sunColor); Vector4Copy(sunColor, refdef.sunDiffuseColor); /* clamp ambient for models */ Vector4Copy(refdef.ambientColor, refdef.modelAmbientColor); for (int i = 0; i < 3; i++) if (refdef.modelAmbientColor[i] < MIN_AMBIENT_COMPONENT) refdef.modelAmbientColor[i] = MIN_AMBIENT_COMPONENT; /* scale it into a reasonable range, the clamp above ensures this will work */ while (VectorSum(refdef.modelAmbientColor) < MIN_AMBIENT_SUM) VectorScale(refdef.modelAmbientColor, 1.25, refdef.modelAmbientColor); AngleVectors(sunAngles, refdef.sunVector, nullptr, nullptr); refdef.sunVector[3] = 0.0; /* to use as directional light source in OpenGL */ /** @todo Parse fog from worldspawn config */ refdef.weather = WEATHER_NONE; refdef.fogColor[3] = 1.0; VectorSet(refdef.fogColor, 0.75, 0.75, 0.75); }