JurassicParkTrespasser/jp2_pc/Source/Lib/Renderer/Primitives/FastBumpTable.cpp

305 lines
9.8 KiB
C++
Raw Permalink Normal View History

2018-01-01 22:07:24 +00:00
/***********************************************************************************************
*
* Copyright <EFBFBD> DreamWorks Interactive. 1996
*
* Contents:
* Implementation of 'FastBumpTable.hpp.'
*
* To do:
* Add filters for preprocessing bumpmaps.
* Use curve fitting for height-field to bumpmap conversion.
*
***********************************************************************************************
*
* $Log:: /JP2_PC/Source/Lib/Renderer/Primitives/FastBumpTable.cpp $
*
* 35 10/03/98 4:40a Rwyatt
* Disabled translation primitive in bsetupBump()
*
* 34 8/05/98 2:24p Pkeet
* Fixed crash bug.
*
* 33 98/07/22 14:43 Speter
* Use new CMaterial and CClut functions for bump table. MakeTranslationTable algorithm
* simplified, doesn't rely on old clut implementation.
*
* 32 98/03/13 14:05 Speter
* Removed bump-quantize test stuff.
*
* 31 98/02/10 12:58 Speter
* CBumpTable now requires just a CClu for conversions, not a CClut or CPalClut.
*
* 30 1/19/98 7:30p Pkeet
* Added support for 16 bit bumpmaps by adding lower colour resolution and a smaller size for
* 'CBumpAnglePair.'
*
* 29 97/10/12 20:39 Speter
* Bump tables are now tailored to particular materials and cluts. Translated bump mapping is
* now used only for lighting changes. Changed CBumpLookup to CBumpTable. Now just one routine
* is required for bump setup: bSetupBump. Added Update() to force update. Removed
* au1BumpToCos primary table; now new primary table is calculated for each material. Replaced
* au1CosToIntensity with pau1IntensityTrans. Removed au1BumpFirst.
*
* 28 97/09/18 21:09 Speter
* Bump-mapping now works with iPHI_B_BITS and iPHI_L_BITS of different resolution. Use new
* fGetPhiL() function. Fixed specular code re light size.
*
* 27 97/09/16 15:36 Speter
* Incorporated simper SBumpLighting structure in bump-map setup. Specular folding is now done
* in lighting code. Removed old code for separate specular bump-mapping. Changed SetupBump to
* return only 'translate' flag. Added temporary iBumpQuantizeMask, for bump resolution
* testing.
*
* 26 97/09/11 17:38 Speter
* Bump lighting ranges are now subject to fCombine() operation in here, rather than requiring
* it be done outside.
*
* 25 97/08/05 13:33 Speter
* Added bSPECULAR_POWER flag (disabled).
*
* 24 97/06/23 20:33 Speter
* Gamma correction is now incorporated into bump-mapping.
*
* 23 6/16/97 3:00p Mlange
* Updated for fast float to integer conversion functions' name change.
*
* 22 97-04-23 17:53 Speter
* Fixed stupid bug. Commented out old translation functions.
*
* 21 97-04-23 14:40 Speter
* Moved all bump lookup table setup into CBumpLookup::SetupBump(), from ScreenRenderDWI. Now
* fold specular lighting into translated bump-mapping, eliminating separate, slow specular
* primitive.
* Moved bangLight and bangSpecular variables here from MapT.hpp.
* Removed code in disabled bREFLECTION_PRIMARY section.
*
**********************************************************************************************/
//
// Includes.
//
#include "GblInc/Common.hpp"
#include "FastBumpTable.hpp"
#include "Lib/W95/WinInclude.hpp"
#include "Lib/Sys/DebugConsole.hpp"
#include <math.h>
//
// Definitions.
//
#define fMAX_COSINE (float(iMAX_NUM_INTENSITIES) - 0.05f)
//
// Constants.
//
#define bMODULATE_SPECULAR 0
#define bSPECULAR_POWER 0
//*********************************************************************************************
//
// CBumpTable functions.
//
//*********************************************************************************************
//
void FillBumpTable
(
uint8* au1_bump, // Table to fill.
const SBumpLighting& blt, // Lighting conditions.
const CClu& clu // Output clu.
)
//
// Fills the au1_bump table according to the parameters.
//
// Notes:
// For every combination of angles, the cosine between the bump and light angles is calculated.
// This is passed through the T functor, then converted to an integer and stored in the table.
//
//**********************************
{
Assert(au1_bump);
dprintf("Making bump angle table..\n");
CBumpAnglePair bang; // Bumpmap lighting value.
for (int i_phi_l = iMIN_PHI_L; i_phi_l <= iMAX_PHI_L; i_phi_l++)
{
// Set the phi for the light.
bang.SetPhiL(i_phi_l);
// Initialize phi for the light.
float f_phi_l = bang.fGetPhiL();
//
// Get the sine and cosine of the light's phi value and store for use by all
// the inner loops.
//
float f_sin_phi_l = sin(f_phi_l);
float f_cos_phi_l = cos(f_phi_l);
for (int i_phi_b = 0; i_phi_b <= iMAX_PHI_B; i_phi_b++)
{
bang.SetPhiB(i_phi_b);
float f_phi_b = bang.fGetPhiB();
float f_cos_phi = f_cos_phi_l * cos(f_phi_b);
float f_sin_phi = f_sin_phi_l * sin(f_phi_b);
for (int i_theta = 0; i_theta <= (1 << (iTHETA_BITS-1)); i_theta++)
{
bang.SetTheta(uint(i_theta));
//
// Get the sine and cosine of the light's theta and store for use by all the inner
// loops.
//
float f_theta_b = bang.fGetTheta();
float f_cos_theta_b = cos(f_theta_b);
//
// Obtain the dot product between the normals described by the two angle
// pairs. This corresponds to the formula:
//
// dot product = cos(Tb) * cos(Pb) * cos(Pl) + sin(Pb) * sin(Pl)
//
float f_dot = f_cos_theta_b * f_cos_phi + f_sin_phi;
//
// Statement for verifying the accuracy of this method of building the
// table. Note that this statement is too slow even for debug mode, so
// it was run once and then commented out.
//
//Assert(Fuzzy(f_dot) == bang.dir3MakeNormal() * b.dir3MakeNormal());
// Clamp dot product values.
Assert(bWithin(f_dot, -1.0, 1.0));
SetMinMax(f_dot, 0.0f, 1.0f);
// Set table entry.
TLightVal lv;
if (clu.pmatMaterial->bRefractive)
lv = clu.pmatMaterial->fReflected(f_dot);
else
lv = blt.lvAmbient + f_dot * blt.lvStrength;
// Get composite reflection value from material.
TReflectVal rv = clu.pmatMaterial->rvSingle(lv);
// Convert to integer clut index.
int i_output = iPosFloatCast(clu.cvFromReflect(rv));
Assert(bang.br < iBUMP_TABLE_SIZE);
au1_bump[bang.br] = i_output;
// Set the same value for negative theta.
bang.SetTheta(uint(-i_theta));
Assert(bang.br < iBUMP_TABLE_SIZE);
au1_bump[bang.br] = i_output;
}
}
}
}
//*********************************************************************************************
//
// CBumpTable implementation.
//
CBumpAnglePair CBumpTable::bangLight;
//*********************************************************************************************
CBumpTable::CBumpTable(const CClu* pclu)
: pcluCLU(pclu)
{
// Initialise tracking vars to invalid values, so tables are always built first time.
bltMain.lvStrength = -1;
bltTrans.lvStrength = -1;
Assert(pcluCLU);
fLightTolerance = (pcluCLU) ? (1.0 / pcluCLU->iNumRampValues) : ( 1.0f / 32.0f);
}
//*********************************************************************************************
void CBumpTable::MakeTranslationTable(const SBumpLighting& blt)
{
if (!pau1IntensityTrans)
pau1IntensityTrans = CPArray<uint8>(pcluCLU->iNumRampValues);
// Pretty simple scheme. Just linearly translate the clut values as
// the light ranges transform. Add 0.5 for automatic rounding.
TClutVal cv_max = pcluCLU->iNumRampValues;
CTransLinear<> tlr_clut
(
bltMain.lvAmbient * cv_max, bltMain.lvStrength * cv_max,
blt.lvAmbient * cv_max + 0.5, blt.lvStrength * cv_max
);
// Translate'em.
for (int i = 0; i < pcluCLU->iNumRampValues; i++)
{
int i_new = iFloatCast((float)i * tlr_clut);
pau1IntensityTrans[i] = MinMax(i_new, 0, pcluCLU->iNumRampValues-1);
}
}
//*********************************************************************************************
bool CBumpTable::bSetupBump(const SBumpLighting& blt_main, const SBumpLighting& blt_poly)
{
bangLight.SetBump(blt_poly.d3Light, true);
Assert(bWithin(blt_main.lvAmbient, 0, 1));
Assert(Fuzzy(blt_main.lvStrength).bWithin(0, 1 - blt_main.lvAmbient));
if (Fuzzy((float)bltMain.lvAmbient, fLightTolerance) != blt_main.lvAmbient ||
Fuzzy((float)bltMain.lvStrength, fLightTolerance) != blt_main.lvStrength)
{
// Fill the bumpmap table.
bltMain = blt_main;
FillBumpTable(au1BumpToIntensity, bltMain, *pcluCLU);
}
Assert(bWithin(blt_poly.lvAmbient, 0, 1));
Assert(Fuzzy(blt_poly.lvStrength).bWithin(0, 1 - blt_poly.lvAmbient));
//
// Assert that we are not going to try to use the translated bump maps as the translation
// code is commented out below!
//
Assert ((Fuzzy((float)bltMain.lvAmbient, fLightTolerance) != blt_poly.lvAmbient ||
Fuzzy((float)bltMain.lvStrength, fLightTolerance) != blt_poly.lvStrength) == 0);
// Use translated bump-mapping if the material or lighting differ from defaults.
/* if (Fuzzy((float)bltMain.lvAmbient, fLightTolerance) != blt_poly.lvAmbient ||
Fuzzy((float)bltMain.lvStrength, fLightTolerance) != blt_poly.lvStrength)
{
// The bump data for this triangle is different than the primary data.
// We must use slow table bumping.
// Compare with current params, and return if equivalent.
if (Fuzzy((float)bltTrans.lvAmbient, fLightTolerance) != blt_poly.lvAmbient ||
Fuzzy((float)bltTrans.lvStrength, fLightTolerance) != blt_poly.lvStrength)
{
// Rebuild the translation table.
bltTrans = blt_poly;
MakeTranslationTable(bltTrans);
}
return true;
}
else
return false;*/
return false;
}
//*********************************************************************************************
void CBumpTable::Update()
{
// Initialise tracking vars to invalid values, so tables are built next time.
bltMain.lvStrength = -1;
bltTrans.lvStrength = -1;
}