/****************************************************************************/ /* */ /* project : CGF (c) 1999 William van der Sterren */ /* */ /* file : cgf_sfx_fog.h "fog openGL stuff" */ /* author(s): William van der Sterren */ /* version : 0.5 */ /* */ /* date (last revision): Aug 31, 99 */ /* date (creation) : Aug 31, 99 */ /* */ /* */ /* revision history */ /* -- date ---- | -- revision ---------------------- | -- revisor -- */ /* | | */ /* */ /****************************************************************************/ #undef FOG #ifdef FOG #include // prevent problems between C and STL extern "C" { #include "cgf_sfx_fog.h" #include "../g_local.h" //#include "sabin_debug.h" #include #include /* #ifdef CGF // AI update related to fog #include "cgf_tactics_visibility.h" #endif */ } #include #include #include using namespace std; // defaults static vec_t m_FogDensity = 0.1000; static int m_FogEnabled = false; static int m_FogType = 2; // linear static int m_FogStart = 200; static int m_FogEnd = 1600; static vec_t m_FogColor[4] = {0.5, 0.5, 0.5, 1}; static char m_Settings[64]; const int kMaxViewingDistance = 8192; const int kViewingDistanceStep = 64; static vec_t m_FogViewReduction[kMaxViewingDistance / kViewingDistanceStep]; //static vec_t m_FogViewReduction[128]; // cvar for fog and video mode static cvar_t* fog = 0; static cvar_t* vid_ref = 0; // forward decls void CGF_SFX_ActivateFog(vec_t aDensity, int aType, vec3_t aColor, vec_t aBegin, vec_t anEnd ); void CGF_SFX_DeactivateFog(); qboolean CGF_SFX_FindFogPreferences(const char* aMapName, vec_t* aDensity, int* aType, vec_t* aRed, vec_t* aGreen, vec_t* aBlue, vec_t* aBegin, vec_t* aEnd ); void CGF_SFX_InitFogForDistance(int aFogMode, vec_t aFogDensity, vec_t aFogBegin, vec_t aFogEnd); void CGF_SFX_InstallFogSupport() { // reset settings m_Settings[0] = 0;//char(0); // if fog > 0, then enabled fog = gi.cvar("fog", "0", 0); vid_ref = gi.cvar("vid_ref", "", 0); // prevent issueing gl calls if no opengl present m_FogEnabled = ( (fog->value > 0) && (0 != stricmp(vid_ref->string, "soft")) ); // if not fog enabled, act upon it if (!m_FogEnabled) { if (fog->value == 0) { strcpy(m_Settings, "cvar fog is 0"); // CGF_Debug_LogMessage("fog disabled: cvar fog is 0"); } else { strcpy(m_Settings, "using software rendering"); // CGF_Debug_LogMessage("fog disabled: using software rendering"); } gi.cvar_set("fog", "0"); } } void CGF_SFX_AdjustFogForMap(const char* aMapName) { // verify fog if m_FogEnabled, and reset if required fog = gi.cvar("fog", "0", 0); vid_ref = gi.cvar("vid_ref", "", 0); if (m_FogEnabled) { if (!(m_FogEnabled = (fog->value != 0))) { #ifdef CGF CGF_Debug_LogMessage("fog disabled: fog set to 0 or video mode changed"); // change visibility info for AI CGF_Tactics_IncorporateChangedFogSettings(); #endif } } else { m_FogEnabled = ( (fog->value > 0) && (0 != stricmp(vid_ref->string, "soft")) ); if (m_FogEnabled) { #ifdef CGF CGF_Debug_LogMessage("fog enabled : fog set to 1 or video mode changed"); // change visibility info for AI CGF_Tactics_IncorporateChangedFogSettings(); #endif } } // process fog setting if (m_FogEnabled) { vec_t d; int t; vec_t s; vec_t e; vec3_t rgb; if ( (!aMapName) || (!CGF_SFX_FindFogPreferences(aMapName, &d, &t, &rgb[0], &rgb[1], &rgb[2], &s, &e)) ) { if (!CGF_SFX_FindFogPreferences("default", &d, &t, &rgb[0], &rgb[1], &rgb[2], &s, &e)) { d = m_FogDensity; t = m_FogType; VectorCopy(m_FogColor, rgb); s = m_FogStart; e = m_FogEnd; } } // convert d to value usable for gl lib d /= 100; // convert fog type // 0 == GL_EXP, 1 == GL_EXP2, 2 == GL_LINEAR if ((t < 0) || (t > 2)) t = m_FogType; if (t < 2) t = t + 0x800; else t = GL_LINEAR; if (d > 0) CGF_SFX_ActivateFog(d, t, rgb, s, e); else CGF_SFX_DeactivateFog(); } else { CGF_SFX_DeactivateFog(); } } qboolean CGF_SFX_FindFogPreferences(const char* aMapName, vec_t* aDensity, int* aType, vec_t* aRed, vec_t* aGreen, vec_t* aBlue, vec_t* aBegin, vec_t* aEnd ) { *aDensity = 0; // try to read preferences from file action\cgf\fog\.fog // format for file is: // // format: mapname density fogtype red green blue char buf_filename[256]; ostrstream filename(buf_filename, 255); cvar_t* gamedir; cvar_t* basedir; gamedir = gi.cvar ("game", "", 0); basedir = gi.cvar("basedir", ".", 0); // obtain file location filename << basedir->string << '\\' << gamedir->string << '\\' << "cgf\\fog\\" << aMapName << ".fog" << char(0); // open file, append mode ifstream preferences(buf_filename, ios_base::in); if (preferences.good()) { char name[128]; memset(name,0, sizeof(name)); preferences >> name; // skip comment lines if any while ( (strlen(name) >= 2) && (name[0] == '/') && ( (name[1] == '/') || (name[1] == '*') ) ) { preferences.getline(name, 128); memset(name,0, sizeof(name)); preferences >> name; } /* test for name similarity removed if ( (strlen(name)) && ( 0 == stricmp(name, aMapName)) ) */ { preferences >> *aDensity; if (*aDensity > 0) { preferences >> *aType; preferences >> *aRed; preferences >> *aGreen; preferences >> *aBlue; preferences >> *aBegin; preferences >> *aEnd; } // adjust settings info ostrstream settings(buf_filename, 63); settings << "cgf\\fog\\" << aMapName << ".fog" << char(0); strcpy(m_Settings, buf_filename); return true; } } return false; } void CGF_SFX_ActivateFog(vec_t aDensity, int aType, vec3_t aColor, vec_t aBegin, vec_t anEnd ) { #ifdef CGF if (CGF_Debug_IsLogging()) { char message[256]; if (aDensity) sprintf(message, "fog settings: mode %d, density %.2f, rgb=[%.2f, %.2f, %.2f], begin %d, end %d", (aType == GL_LINEAR ? 2 : aType - GL_FOG_START), aDensity, aColor[0], aColor[1], aColor[2], (int) aBegin, (int) anEnd ); else sprintf(message, "fog settings: mode %d, density %.2f == disabled", (aType == GL_LINEAR ? 2 : aType - GL_FOG_START), aDensity ); CGF_Debug_LogMessage(message); } #endif CGF_SFX_InitFogForDistance(aType, aDensity, aBegin, anEnd); glEnable (GL_FOG); // turn on fog, otherwise you won't see any glFogi (GL_FOG_MODE, aType); if (aType == GL_LINEAR) { glFogf (GL_FOG_START, aBegin); glFogf (GL_FOG_END, anEnd); } glFogfv (GL_FOG_COLOR, aColor); glFogf (GL_FOG_DENSITY, aDensity); glHint (GL_FOG_HINT, GL_NICEST); } void CGF_SFX_DeactivateFog() { CGF_SFX_InitFogForDistance(0, 0, 0, 0); // prevent opengl calls when no opengl if ( (vid_ref) && (0 == stricmp(vid_ref->string, "soft")) ) return; glDisable (GL_FOG); // turn off fog } int CGF_SFX_IsFogEnabled() { return m_FogEnabled; } void CGF_SFX_InitFogForDistance(int aFogMode, vec_t aFogDensity, vec_t aFogBegin, vec_t aFogEnd) { // determine how many cells int cells; cells = kMaxViewingDistance / kViewingDistanceStep; vec_t dist; vec_t maxdist; vec_t mindist; if (aFogDensity == 0.0) aFogMode = 0; // adjust fog density value to our values aFogDensity *= 100; switch (aFogMode) { case GL_LINEAR: maxdist = aFogEnd; mindist = aFogBegin; break; case GL_EXP: maxdist = 400.0 / sqrt(aFogDensity); break; case GL_EXP2: maxdist = 130.0 / aFogDensity; break; default : maxdist = kMaxViewingDistance; } dist = 0; for (int cell = 0; cell < cells; cell++) { vec_t reduction; switch (aFogMode) { case GL_LINEAR: if (dist < mindist) reduction = 1; else if (dist > maxdist) reduction = 0; else reduction = 1 - (dist - mindist) / (maxdist - mindist); break; case GL_EXP: reduction = 1 - dist / maxdist; break; case GL_EXP2: reduction = 1 - (dist / maxdist) * (dist / maxdist); break; default : reduction = 1.0; } if (reduction < 0) reduction = 0; m_FogViewReduction[cell] = reduction; dist += kViewingDistanceStep; } } const char* CGF_SFX_FogSettingsInfo() { return (const char*) m_Settings; } vec_t CGF_SFX_GetFogForDistance(vec_t dist) { int index; index = ((int) dist) / (int) kViewingDistanceStep; assert( (index < (kMaxViewingDistance / kViewingDistanceStep)) ); return m_FogViewReduction[index]; } vec_t CGF_SFX_GetViewingDistanceUpToReduction(vec_t aReduction) { int index; index = (kMaxViewingDistance / kViewingDistanceStep) - 1; while ( (index >= 0) && (m_FogViewReduction[index] < aReduction) ) index--; return (vec_t) (index * kViewingDistanceStep); } /* #ifdef _DEBUG extern "C" void CGF_SFX_Fog_DisplayRods(edict_t* aClient); void CGF_SFX_Fog_DisplayRods(edict_t* aClient) { vec3_t forward; vec3_t v1; vec3_t v2; bool half; bool ten; half = false; ten = false; AngleVectors(aClient->s.angles, forward, 0, 0); forward[2] = 0; VectorNormalize(forward); for (int rod = 0; rod < 20; rod ++) { VectorMA(aClient->s.origin, 100 * ((float) rod), forward, v1); VectorCopy(v1, v2); v2[2] -= 1000; SABIN_Debug_DisplayLine(v1, v2, 60); if ( (!half) && (half = (CGF_SFX_GetFogForDistance(100 * ((float) rod)) < 0.5)) ) { SABIN_Debug_DisplayPoint(v1, RF_SHELL_RED, 60); } if ( (!ten) && (ten = (CGF_SFX_GetFogForDistance(100 * ((float) rod)) < 0.1)) ) { SABIN_Debug_DisplayPoint(v1, RF_SHELL_RED, 60); } } } #endif */ #endif