mirror of
https://github.com/OpenTrespasser/JurassicParkTrespasser.git
synced 2024-12-18 14:41:56 +00:00
11d6505414
- std::* treatment
495 lines
14 KiB
C++
495 lines
14 KiB
C++
/***********************************************************************************************
|
|
*
|
|
* Copyright © DreamWorks Interactive. 1996
|
|
*
|
|
* Contents:
|
|
* Implementation of 'Fop.hpp.'
|
|
*
|
|
***********************************************************************************************
|
|
*
|
|
* $Log:: /JP2_PC/Source/Lib/Renderer/Fog.cpp $
|
|
*
|
|
* 42 98.09.19 12:39a Mmouni
|
|
* Added "forceinline" to many small inline functions.
|
|
* Inlined some functions for speed.
|
|
*
|
|
* 41 98/09/16 12:15 Speter
|
|
* Removed a redundant check.
|
|
*
|
|
* 40 98.09.13 7:04p Mmouni
|
|
* Changed the ApplyTerrainFog() method.
|
|
*
|
|
* 39 8/26/98 5:50p Mmouni
|
|
* If the clipping plane is adjusted to be inside the fog half_y the fog is now adjust to some
|
|
* hard coded values.
|
|
*
|
|
* 38 98.06.26 12:33p Mmouni
|
|
* Removed some junk that was left in.
|
|
*
|
|
* 37 98.06.25 8:46p Mmouni
|
|
* Added stuff to support render quality setting.
|
|
*
|
|
* 36 98/06/18 11:35 Speter
|
|
* Fixed terrain fog clipping bug.
|
|
*
|
|
* 35 98/01/15 14:14 Speter
|
|
* Moved ApplyTerrainFog here from Pipeline.cpp. Made ApplyFirst and ApplyLast private.
|
|
*
|
|
* 34 97.12.08 3:52p Mmouni
|
|
* Removed unused variables/code.
|
|
*
|
|
* 33 11/16/97 2:34p Sblack
|
|
* Start first fog band at 1/4 instead of 2/10.
|
|
*
|
|
* 32 97.11.14 11:39a Mmouni
|
|
* Made changes to support smooth foggin into the first fog band.
|
|
*
|
|
* 31 97/11/13 1:02a Pkeet
|
|
* Added code to cut off last fog band.
|
|
*
|
|
* 30 11/12/97 7:17a Shernd
|
|
* Added the ability to use flags to not have output files used
|
|
*
|
|
* 29 97/11/07 10:42a Pkeet
|
|
* Added the 'ApplyLast' member function.
|
|
*
|
|
* 28 97/11/06 6:31p Pkeet
|
|
* Added the 'ApplyFirst' member function. Setup code initializes the 'fFogTerrainThreshold' and
|
|
* 'fInvFogTerrainFirstBandRange' parameters. Modified the 'bGetFogLevels' to return a boolean
|
|
* value set to 'true' if the polygon is entirely below the terrain threshold value.
|
|
*
|
|
* 27 97/11/06 4:52p Pkeet
|
|
* Changed maximum allowed value for the floating point fog value.
|
|
*
|
|
* 26 97/11/05 7:32p Pkeet
|
|
* Implemented the 'SetFogLevelsFloat' member function.
|
|
*
|
|
* 25 97/11/03 5:52p Pkeet
|
|
* Added the 'fogTerrainFog' global variable.
|
|
*
|
|
* 24 97/10/06 11:01 Speter
|
|
* Moved fogFog here from Render.hpp.
|
|
*
|
|
* 23 97/07/23 18:05 Speter
|
|
* Replaced CCamera argument to clipping functions with b_perspective flag.
|
|
*
|
|
* 22 97/06/10 15:46 Speter
|
|
* Now takes camera as an argument (for new vertex projection).
|
|
*
|
|
* 21 97/05/13 13:40 Speter
|
|
* Renamed SRenderTriangle::seterfTri to seterfFace.
|
|
*
|
|
* 20 97-04-21 17:10 Speter
|
|
* Changed interface of Apply function, to use new CPipelineHeap. Rewrote Apply() to use new
|
|
* CClipPlane splitting function.
|
|
*
|
|
* 19 97-04-04 12:38 Speter
|
|
* A big change: now pipeline uses CRenderPolygon rather than SRenderTriangle (currently always
|
|
* as a triangle). Changed associated variable names and comments.
|
|
*
|
|
* 18 97/02/03 11:00 Speter
|
|
* Renamed dartTriangles to dartFogTriangles to avoid confusion with Pipeline variable.
|
|
*
|
|
* 17 12/19/96 1:23p Mlange
|
|
* Removed some redundant functions. Updated the todo list. Updated the fog class interface. It
|
|
* now uses a property structure. Re-implemented the various fog functions. Removed the inverse
|
|
* fog function.
|
|
*
|
|
* 16 12/14/96 6:25p Mlange
|
|
* Implemented new fog method.
|
|
*
|
|
* 15 12/14/96 3:19p Pkeet
|
|
* Set 'iPRINT_FOG_TABLE' to 0.
|
|
*
|
|
* 14 12/09/96 1:41p Mlange
|
|
* Updated for changes to the CCamera interface.
|
|
*
|
|
* 13 96/12/06 15:09 Speter
|
|
* Removed unneeded pras_screen argument from ConstructTable().
|
|
*
|
|
* 12 11/27/96 4:55p Pkeet
|
|
* Added extended print functions for the fog table.
|
|
*
|
|
* 11 11/23/96 5:33p Mlange
|
|
* Made the camera pointer in ConstructTable() const.
|
|
*
|
|
* 10 96/11/21 18:57 Speter
|
|
* Changed fog table to use hard-coded size, rather than calculating from Z clipping values.
|
|
*
|
|
* 9 96/10/22 11:27 Speter
|
|
* Changed CPresenceCamera to CCamera, prscam prefix to cam.
|
|
*
|
|
* 8 96/10/22 11:11 Speter
|
|
* Changed CEntity to CPresence in appropriate contexts.
|
|
*
|
|
* 7 9/26/96 1:54p Pkeet
|
|
* Changed default fog values.
|
|
*
|
|
* 6 9/25/96 8:57p Pkeet
|
|
* Made linear fog building the default.
|
|
*
|
|
* 5 96/09/25 19:50 Speter
|
|
* The Big Change.
|
|
* In transforms, replaced TReal with TR, TDefReal with TReal.
|
|
* Replaced all references to transform templates that have <TObjReal> with <>.
|
|
* Replaced TObjReal with TReal, and "or" prefix with "r".
|
|
* Replaced CObjPoint, CObjNormal, and CObjPlacement with equivalent transform types, and
|
|
* prefixes likewise.
|
|
* Removed some unnecessary casts to TReal.
|
|
* Finally, replaced VER_GENERAL_DEBUG_ASSERTS with VER_DEBUG.
|
|
*
|
|
* 4 96/09/25 15:39 Speter
|
|
* Added efogFunction field to specify function for fog table.
|
|
* Changed fK field to fZMaxDist.
|
|
* Added iShiftFogUp field, removed iSizeofDestPixel.
|
|
* Made u4GetFog() return fog index. Added u4GetClutOffset to return clut offset for fog index.
|
|
* Implemented bConstantFog function.
|
|
* Changed f_inv_max_depth value to be CCamera::fInvZAdjust.
|
|
*
|
|
* 3 8/22/96 4:29p Pkeet
|
|
* Made the fog table build according to values for ramp and depth in the main clut.
|
|
*
|
|
* 2 8/20/96 4:45p Pkeet
|
|
* Initial implementation of fogging.
|
|
*
|
|
* 1 8/19/96 10:19a Pkeet
|
|
*
|
|
**********************************************************************************************/
|
|
|
|
// If this defines a value, print out the most recently created fog table.
|
|
#define bPRINT_FOG_TABLE 1
|
|
|
|
//
|
|
// Includes.
|
|
//
|
|
#include "Common.hpp"
|
|
#include "Fog.hpp"
|
|
|
|
#include "ScreenRender.hpp"
|
|
#include "Clip.hpp"
|
|
#include "Lib/GeomDBase/PlaneAxis.hpp"
|
|
#include "Camera.hpp"
|
|
#include "Lib/GeomDBase/PartitionPriv.hpp"
|
|
#include "Lib/EntityDBase/Query/QRenderer.hpp"
|
|
|
|
#if bPRINT_FOG_TABLE
|
|
#include <fstream>
|
|
#include <iomanip>
|
|
|
|
std::ofstream stream;
|
|
#endif
|
|
|
|
extern bool bUseOutputFiles;
|
|
|
|
#define rMIN_FOG_BAND_WIDTH TReal(.005) // Minimum width of a fog band.
|
|
|
|
//*********************************************************************************************
|
|
//
|
|
// CFog implemenation.
|
|
//
|
|
|
|
//******************************************************************************************
|
|
void CFog::SetProperties(const CFog::SProperties& fogprop)
|
|
{
|
|
// Set the new properties.
|
|
fogpropCurrent = fogprop;
|
|
|
|
// Compute adjusted fog values based on adjusted far clip.
|
|
TReal rAdjustedHalfFogY = fogpropCurrent.rHalfFogY * fogpropCurrent.rHalfFogYAdjusment;
|
|
TReal rAdjustedPower = fogpropCurrent.rPower;
|
|
|
|
// Check if we have pulled the clipping plane in past the middle of the fog.
|
|
if (rAdjustedHalfFogY > 1.0f)
|
|
{
|
|
// If so, use these hard coded settings.
|
|
rAdjustedHalfFogY = 0.8f;
|
|
rAdjustedPower = 5.0f;
|
|
}
|
|
|
|
#if bPRINT_FOG_TABLE
|
|
|
|
if (bUseOutputFiles)
|
|
{
|
|
stream.open("fog.txt");
|
|
|
|
stream << std::setiosflags(std::ios::left) << std::setprecision(5);
|
|
stream << "Fog Creation...\n\n" << "Level to Y\n";
|
|
}
|
|
#endif
|
|
|
|
int i_curr_index = 0;
|
|
TReal r_last_fog_end_y = 0;
|
|
|
|
for (int i_fog_level = 0; i_fog_level < (int)parLevelToY.uLen; i_fog_level++)
|
|
{
|
|
//
|
|
// First, calculate the end y value for the current fog level. (Actually,
|
|
// the start y value of the next fog level.)
|
|
//
|
|
|
|
// Get the next fog level normalised for the range: [0,1].
|
|
TReal r_fog_level = TReal(i_fog_level + 1) / parLevelToY.uLen;
|
|
|
|
Assert(bWithin(r_fog_level, 0, 1));
|
|
|
|
TReal r_fog_end_y;
|
|
|
|
switch (fogpropCurrent.efogFunction)
|
|
{
|
|
case efogLINEAR :
|
|
{
|
|
//
|
|
// The fog level is linear with y raised to some power:
|
|
//
|
|
// p 1/p
|
|
// fog = y => y = fog
|
|
//
|
|
// We want the fog level to be half of maximum at some distance h_y, thus we need some
|
|
// constant k:
|
|
//
|
|
// 1/p 1/p 1/p
|
|
// y = fog * k, with: h_y = .5 * k => k = h_y * 2
|
|
//
|
|
float f_k = rAdjustedHalfFogY * pow(2.0, 1.0 / rAdjustedPower);
|
|
|
|
r_fog_end_y = pow(r_fog_level, 1 / rAdjustedPower) * f_k;
|
|
break;
|
|
}
|
|
|
|
case efogEXPONENTIAL :
|
|
{
|
|
//
|
|
// The fog level calculated with the exponential decay function:
|
|
//
|
|
// -ky
|
|
// fog = A(1 - e ) (in our case: A = 1) => y = ln(-fog + 1) / -k
|
|
//
|
|
// We want the fog level to be half of maximum at some distance h_y, thus the
|
|
// constant k is calculated with:
|
|
//
|
|
// -kh_y
|
|
// 1 - e = .5 => k = -ln(.5) / h_y
|
|
//
|
|
float f_k = -log(.5) / rAdjustedHalfFogY;
|
|
|
|
if (r_fog_level < 1 - FLT_EPSILON * 10)
|
|
r_fog_end_y = log(-r_fog_level + 1) / -f_k;
|
|
else
|
|
r_fog_end_y = FLT_MAX;
|
|
|
|
break;
|
|
}
|
|
|
|
default :
|
|
{
|
|
Assert(false);
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
#if bPRINT_FOG_TABLE
|
|
if (bUseOutputFiles)
|
|
{
|
|
stream << std::setw(4) << i_fog_level << " -> " << std::setw(5) << r_fog_end_y << " ";
|
|
}
|
|
#endif
|
|
|
|
// Ensure the fog band has the minimum witdh.
|
|
if (r_fog_end_y < r_last_fog_end_y + rMIN_FOG_BAND_WIDTH)
|
|
r_fog_end_y = r_last_fog_end_y + rMIN_FOG_BAND_WIDTH;
|
|
|
|
r_last_fog_end_y = r_fog_end_y;
|
|
|
|
// We want maximum fog to extend to the far clipping plane, so if this is the last fog level,
|
|
// force its y distance to be beyond the far clipping plane. Also, if this fog band ends
|
|
// after or sufficiently close to the far clipping plane, extend it to be beyond it as well to
|
|
// avoid unnessary clipping operations.
|
|
if (i_fog_level == (int)parLevelToY.uLen - 1 || r_fog_end_y + rMIN_FOG_BAND_WIDTH / 2 > 1)
|
|
r_fog_end_y = FLT_MAX;
|
|
|
|
|
|
// Now fill in the y to fog level conversion table.
|
|
for (; i_curr_index < (int)paiYToLevel.uLen; i_curr_index++)
|
|
{
|
|
// Convert the table index to a y value in the range [0,1].
|
|
TReal r_y = (TReal)i_curr_index / (TReal)paiYToLevel.uLen;
|
|
|
|
// Fill the table with the current fog level until the y value is greater than the y value
|
|
// of the end of the fog band.
|
|
paiYToLevel[i_curr_index] = i_fog_level;
|
|
|
|
if (r_y >= r_fog_end_y)
|
|
{
|
|
// Now set the end y value of the current fog band to the y value calculated for this
|
|
// table index. This way, the two conversion tables will match.
|
|
r_fog_end_y = r_y;
|
|
break;
|
|
}
|
|
}
|
|
|
|
#if bPRINT_FOG_TABLE
|
|
if (bUseOutputFiles)
|
|
{
|
|
stream << r_fog_end_y << std::endl;
|
|
}
|
|
#endif
|
|
|
|
parLevelToY[i_fog_level] = r_fog_end_y;
|
|
}
|
|
|
|
// Ensure the entire table is initialised.
|
|
Assert(i_curr_index == paiYToLevel.uLen);
|
|
Assert(pafYToLevel.uLen == paiYToLevel.uLen);
|
|
|
|
// Initialize the floating point table.
|
|
SetFogLevelsFloat();
|
|
|
|
#if bPRINT_FOG_TABLE
|
|
if (bUseOutputFiles)
|
|
{
|
|
stream << "\n\n\nY to level\n";
|
|
}
|
|
|
|
for (i_curr_index = 0; i_curr_index < (int)paiYToLevel.uLen; i_curr_index++)
|
|
{
|
|
TReal r_range_start = (TReal)i_curr_index / (TReal)paiYToLevel.uLen;
|
|
TReal r_range_end = (TReal)(i_curr_index + 1) / (TReal)paiYToLevel.uLen;
|
|
|
|
if (bUseOutputFiles)
|
|
{
|
|
stream << std::setw(4) << i_curr_index << " [" << std::setw(9) << r_range_start << ", " << std::setw(9) << r_range_end << ")";
|
|
stream << " -> " << paiYToLevel[i_curr_index] << ", " << pafYToLevel[i_curr_index] << std::endl;
|
|
}
|
|
}
|
|
|
|
if (bUseOutputFiles)
|
|
{
|
|
stream.close();
|
|
}
|
|
#endif
|
|
}
|
|
|
|
//******************************************************************************************
|
|
//
|
|
void CFog::SetQualityAdjustment
|
|
(
|
|
float f_actual_farclip, // Actual far clipping value.
|
|
float f_desired_farclip // Far clipping value before adjustment.
|
|
)
|
|
//
|
|
// Update the properties based on quality adjustment to the camera.
|
|
//
|
|
//**************************************
|
|
{
|
|
TReal rHalfFogYAdjusment = f_desired_farclip / f_actual_farclip;
|
|
|
|
// Avoid doing anything if we can.
|
|
if (rHalfFogYAdjusment != fogpropCurrent.rHalfFogYAdjusment)
|
|
{
|
|
fogpropCurrent.rHalfFogYAdjusment = f_desired_farclip / f_actual_farclip;
|
|
SetProperties(fogpropCurrent);
|
|
}
|
|
}
|
|
|
|
//*****************************************************************************************
|
|
void CFog::SetFogLevelsFloat()
|
|
{
|
|
float f_k;
|
|
float f_inv_k;
|
|
float f_num_bands = float(iNumBands);
|
|
float f_fog_max = float(iNumBands) - 1.001f;
|
|
|
|
// Compute adjusted fog values based on adjusted far clip.
|
|
TReal rAdjustedHalfFogY = fogpropCurrent.rHalfFogY * fogpropCurrent.rHalfFogYAdjusment;
|
|
TReal rAdjustedPower = fogpropCurrent.rPower;
|
|
|
|
// Check if we have pulled the clipping plane in past the middle of the fog.
|
|
if (rAdjustedHalfFogY > 1.0f)
|
|
{
|
|
// If so, use these hard coded settings.
|
|
rAdjustedHalfFogY = 0.8f;
|
|
rAdjustedPower = 5.0f;
|
|
}
|
|
|
|
// Set the fog half power constant.
|
|
switch (fogpropCurrent.efogFunction)
|
|
{
|
|
case efogLINEAR:
|
|
{
|
|
f_inv_k = 1.0f / (rAdjustedHalfFogY * pow(2.0, 1.0 / rAdjustedPower));
|
|
break;
|
|
}
|
|
case efogEXPONENTIAL:
|
|
{
|
|
f_k = log(0.5) / rAdjustedHalfFogY;
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
Assert(false);
|
|
break;
|
|
}
|
|
}
|
|
|
|
fFogTerrainThreshold = 0.0f;
|
|
|
|
for (int i_curr_index = 0; i_curr_index < (int)pafYToLevel.uLen; i_curr_index++)
|
|
{
|
|
TReal r_fog; // Storage for the fog value.
|
|
|
|
// Calculate the normalized 'y' value.
|
|
TReal r_y = TReal(i_curr_index) / TReal(pafYToLevel.uLen);
|
|
|
|
switch (fogpropCurrent.efogFunction)
|
|
{
|
|
case efogLINEAR:
|
|
{
|
|
//
|
|
// The fog level is linear with y raised to some power:
|
|
//
|
|
// 1/p p
|
|
// y = fog * k qed fog = (y / k)
|
|
//
|
|
r_fog = pow(r_y * f_inv_k, rAdjustedPower) * f_num_bands;
|
|
break;
|
|
}
|
|
|
|
case efogEXPONENTIAL:
|
|
{
|
|
//
|
|
// The fog level calculated with the exponential decay function:
|
|
//
|
|
// -ky
|
|
// fog = A(1 - e ) where A = 1
|
|
//
|
|
r_fog = (1.0f - exp(r_y * f_k)) * f_num_bands;
|
|
break;
|
|
}
|
|
}
|
|
|
|
SetMinMax(r_fog, 0.0f, f_fog_max);
|
|
|
|
if (r_fog > 0.25f && fFogTerrainThreshold == 0.0f)
|
|
{
|
|
// Set the threshold to near clip at to the Y at which the fog value is > 1/5.
|
|
fFogTerrainThreshold = r_y;
|
|
}
|
|
|
|
pafYToLevel[i_curr_index] = r_fog;
|
|
}
|
|
|
|
// Set the threshold to far clip at.
|
|
fFogLastBand = parLevelToY[iNumBands - 2];
|
|
}
|
|
|
|
|
|
//*********************************************************************************************
|
|
//
|
|
// Main fog table.
|
|
//
|
|
|
|
CFog fogFog;
|
|
CFog fogTerrainFog(iNUM_TERRAIN_FOG_BANDS);
|
|
|