Files
firestorm/Gameleap/code/mw4/Libraries/mlr/MLRLookUpLight.cpp
T
Cyd 2b8ca921cb Initial full mirror of c:\VWE (source + assets + toolchain + outputs) via Git LFS
Complete disaster-recovery snapshot: engine/game source, game data assets,
VC6 toolchain + DX SDKs, build outputs, deployed game, and _UNUSED archive.
Large binaries in Git LFS; text preserved byte-for-byte (core.autocrlf=false,
no eol attributes). See RECOVERY.md for the one-clone rebuild procedure.
2026-06-24 21:28:16 -05:00

506 lines
11 KiB
C++

#include "MLRHeaders.hpp"
//#############################################################################
//######################### MLRLookUpLight ################################
//#############################################################################
MLRLookUpLight::ClassData*
MLRLookUpLight::DefaultData = NULL;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
MLRLookUpLight::InitializeClass()
{
Verify(!DefaultData);
Verify(gos_GetCurrentHeap() == StaticHeap);
DefaultData =
new ClassData(
MLRLookUpLightClassID,
"MidLevelRenderer::MLRLookUpLight",
MLRInfiniteLight::DefaultData
);
Check_Object(DefaultData);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
MLRLookUpLight::TerminateClass()
{
Check_Object(DefaultData);
delete DefaultData;
DefaultData = NULL;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
MLRLookUpLight::MLRLookUpLight() :
MLRInfiniteLight(DefaultData)
{
Verify(gos_GetCurrentHeap() == LightsHeap);
mapOrigin.x = 0.0f;
mapOrigin.y = 0.0f;
mapOrigin.z = 0.0f;
mapZoneCountX = 1, mapZoneCountZ = 1;
zoneSizeX = 1260.0f, zoneSizeZ = 1260.0f;
one_Over_zoneSizeX = 1.0f/zoneSizeX;
one_Over_zoneSizeZ = 1.0f/zoneSizeZ;
shadowIntensity = 0.5f;
maps = NULL;
mapName = *MString::s_Empty;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
MLRLookUpLight::MLRLookUpLight(
Stuff::MemoryStream *stream,
int version
) :
MLRInfiniteLight(DefaultData, stream, version)
{
Check_Object(stream);
Verify(gos_GetCurrentHeap() == LightsHeap);
*stream >> mapOrigin;
*stream >> mapZoneCountX >> mapZoneCountZ;
*stream >> zoneSizeX >> zoneSizeZ;
*stream >> mapName;
one_Over_zoneSizeX = 1.0f/zoneSizeX;
one_Over_zoneSizeZ = 1.0f/zoneSizeZ;
if(version>16)
{
*stream >> shadowIntensity;
}
else
{
shadowIntensity = 0.5f;
}
maps = new BYTE * [mapZoneCountX * mapZoneCountZ];
Check_Pointer(maps);
for(int i=0;i<mapZoneCountX*mapZoneCountZ;i++)
{
maps[i] = static_cast<BYTE*>(stream->GetPointer());
stream->AdvancePointer(256*32);
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
MLRLookUpLight::MLRLookUpLight(Stuff::Page *page):
MLRInfiniteLight(DefaultData, page)
{
Check_Object(page);
Verify(gos_GetCurrentHeap() == LightsHeap);
maps = NULL;
const char *data;
mapOrigin.x = 0.0f;
mapOrigin.y = 0.0f;
mapOrigin.z = 0.0f;
if (page->GetEntry("MapOrigin", &data))
{
sscanf(data, "%f %f %f", &mapOrigin.x, &mapOrigin.y, &mapOrigin.z);
}
mapZoneCountX = 1, mapZoneCountZ = 1;
if(page->GetEntry("MapSize", &data))
{
sscanf(data, "%d %d", &mapZoneCountX, &mapZoneCountZ);
}
zoneSizeX = 1280.0f, zoneSizeZ = 1280.0f;
if(page->GetEntry("ZoneSize", &data))
{
sscanf(data, "%f %f", &zoneSizeX, &zoneSizeX);
}
one_Over_zoneSizeX = 1.0f/zoneSizeX;
one_Over_zoneSizeZ = 1.0f/zoneSizeZ;
shadowIntensity = 0.5f;
page->GetEntry("ShadowIntensity", &shadowIntensity);
mapName = *MString::s_Empty;
if(page->GetEntry("MapName", &data))
{
mapName = data;
}
LoadMap();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
MLRLookUpLight::~MLRLookUpLight()
{
if(maps!=NULL)
{
for(int i=0;i<mapZoneCountX*mapZoneCountZ;i++)
{
Check_Pointer(maps[i]);
maps[i] = NULL;
}
Check_Pointer(maps);
delete [] maps;
maps = NULL;
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
MLRLookUpLight::Save(Stuff::MemoryStream *stream)
{
Check_Object(this);
Check_Object(stream);
MLRInfiniteLight::Save(stream);
*stream << mapOrigin;
*stream << mapZoneCountX << mapZoneCountZ;
*stream << zoneSizeX << zoneSizeZ;
*stream << mapName;
*stream << shadowIntensity;
for(int i=0;i<mapZoneCountX*mapZoneCountZ;i++)
{
stream->WriteBytes(maps[i], 256*32);
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
MLRLookUpLight::Write(Stuff::Page *page)
{
Check_Object(this);
Check_Object(page);
MLRInfiniteLight::Write(page);
char data[256];
sprintf(data, "%f %f %f", mapOrigin.x, mapOrigin.y, mapOrigin.z);
Verify(strlen(data) < sizeof(data));
page->SetEntry("MapOrigin", data);
sprintf(data, "%d %d", mapZoneCountX, mapZoneCountZ);
Verify(strlen(data) < sizeof(data));
page->SetEntry("MapSize", data);
sprintf(data, "%f %f", zoneSizeX, zoneSizeZ);
Verify(strlen(data) < sizeof(data));
page->SetEntry("ZoneSize", data);
page->SetEntry("ShadowIntensity", shadowIntensity);
page->SetEntry("MapName", mapName);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
MLRLookUpLight::SetMapSizeAndName(int x, int z, const char *name)
{
Check_Object(this);
if(maps!=NULL)
{
for(int i=0;i<mapZoneCountX*mapZoneCountZ;i++)
{
Check_Pointer(maps[i]);
delete [] maps[i];
maps[i] = NULL;
}
Check_Pointer(maps);
delete [] maps;
maps = NULL;
}
mapZoneCountX = x;
mapZoneCountZ = z;
mapName = name;
LoadMap();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
bool
MLRLookUpLight::LoadMap()
{
Check_Object(this);
Stuff::FileStream element_stream(mapName);
BYTE *map = new BYTE [mapZoneCountX*mapZoneCountZ*256*256];
Check_Pointer(map);
element_stream.ReadBytes(map, mapZoneCountX*mapZoneCountZ*256*256);
Verify(maps==NULL);
maps = new BYTE * [mapZoneCountX * mapZoneCountZ];
Check_Pointer(maps);
int i, j;
for(j=0;j<mapZoneCountZ;j++)
{
for(i=0;i<mapZoneCountX;i++)
{
maps[j*mapZoneCountX+i] = new BYTE [256*32];
Check_Pointer(maps[j*mapZoneCountX+i]);
}
}
BYTE *uptr = map;
int k, l, m, mask;
for(j=0;j<mapZoneCountZ;j++)
{
for(k=0;k<256;k++)
{
for(i=0;i<mapZoneCountX;i++)
{
for(l=0;l<32;l++)
{
maps[j*mapZoneCountX+i][k*32+l] = 0;
mask = 0x80;
for(m=0;m<8;m++,mask>>=1)
{
if(*uptr++>128)
{
maps[j*mapZoneCountX+i][k*32+l] |= mask;
}
}
// Mem_Copy(&maps[j*mapZoneCountX+i][k*256], uptr, 256, (256-k)*256);
// uptr += 256;
// &map[(256*j+k)*(mapZoneCountX*256) + i*256]
}
}
}
}
Check_Pointer(map);
delete map;
return false;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
MLRLookUpLight::SetLightToShapeMatrix(const LinearMatrix4D& worldToShape)
{
Check_Object(this);
lightToShape.Multiply(lightToWorld, worldToShape);
shapeToWorld.Invert(worldToShape);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
MLRLookUpLight::TestInstance()
{
Verify(IsDerivedFrom(DefaultData));
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
MLRLookUpLight::LightVertex(const MLRVertexData& vertexData)
{
UnitVector3D light_z;
GetInShapeDirection(light_z);
// const Scalar One_Over_255 = 1.f/255.0f;
Point3D worldPoint;
worldPoint.Multiply(*(vertexData.point), shapeToWorld);
Scalar prep_x = mapZoneCountX*zoneSizeX - worldPoint.x - mapOrigin.x;
Scalar prep_z = mapZoneCountZ*zoneSizeZ - worldPoint.z - mapOrigin.z;
if(prep_x < 0)
{
prep_x = 0;
}
int map_x = Truncate_Float_To_Word(prep_x*one_Over_zoneSizeX);
if(prep_z < 0)
{
prep_z = 0;
}
int map_z = Truncate_Float_To_Word(prep_z*one_Over_zoneSizeZ);
if(map_x>=mapZoneCountX)
{
map_x = mapZoneCountX-1;
}
if(map_z>=mapZoneCountZ)
{
map_z = mapZoneCountZ-1;
}
// Verify(map_x>=0 && map_x<mapZoneCountX);
// Verify(map_z>=0 && map_z<mapZoneCountZ);
int off_x = Truncate_Float_To_Word((prep_x - map_x*zoneSizeX)*256.0f*one_Over_zoneSizeX);
int off_z = Truncate_Float_To_Word((prep_z - map_z*zoneSizeZ)*256.0f*one_Over_zoneSizeZ);
if(off_x < 0)
{
off_x = 0;
}
if(off_x>255)
{
off_x = 255;
}
if(off_z < 0)
{
off_z = 0;
}
if(off_z>255)
{
off_z = 255;
}
// Verify(off_x>=0 && off_x < 256);
// Verify(off_z>=0 && off_z < 256);
BYTE b = maps[map_z*mapZoneCountX+map_x][(off_z<<5) + (off_x>>3)];
Scalar mapIntensity = b & (0x80>>(off_x&7)) ? intensity : shadowIntensity;
//
//-------------------------------------------------------------------
// Now we reduce the light level falling on the vertex based upon the
// cosine of the angle between light and normal
//-------------------------------------------------------------------
//
Scalar cosine = mapIntensity;
if(vertexData.normal!=NULL)
{
cosine = -(light_z * (*vertexData.normal))*mapIntensity;
}
RGBColor light_color(color);
if (cosine > SMALL)
{
light_color.red *= cosine;
light_color.green *= cosine;
light_color.blue *= cosine;
Stuff::RGBAColor *t = const_cast<Stuff::RGBAColor*>(vertexData.color);
Check_Pointer(t);
t->red += light_color.red;
t->green += light_color.green;
t->blue += light_color.blue;
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
MLRLookUpLight::LightCenter(RGBAColor& rcol)
{
UnitVector3D light_z;
GetInShapeDirection(light_z);
// const Scalar One_Over_255 = 1.f/255.0f;
Point3D worldPoint;
worldPoint = shapeToWorld;
Scalar prep_x = mapZoneCountX*zoneSizeX - worldPoint.x - mapOrigin.x;
Scalar prep_z = mapZoneCountZ*zoneSizeZ - worldPoint.z - mapOrigin.z;
if(prep_x < 0.0f)
{
prep_x = 0.0f;
}
int map_x = Truncate_Float_To_Word(prep_x*one_Over_zoneSizeX);
if(prep_z < 0.0f)
{
prep_z = 0.0f;
}
int map_z = Truncate_Float_To_Word(prep_z*one_Over_zoneSizeZ);
if(map_x>=mapZoneCountX)
{
map_x = mapZoneCountX-1;
}
if(map_z>=mapZoneCountZ)
{
map_z = mapZoneCountZ-1;
}
// Verify(map_x>=0 && map_x<mapZoneCountX);
// Verify(map_z>=0 && map_z<mapZoneCountZ);
int off_x = Truncate_Float_To_Word((prep_x - map_x*zoneSizeX)*256.0f*one_Over_zoneSizeX);
int off_z = Truncate_Float_To_Word((prep_z - map_z*zoneSizeZ)*256.0f*one_Over_zoneSizeZ);
if(off_x < 0)
{
off_x = 0;
}
if(off_x>255)
{
off_x = 255;
}
if(off_z < 0)
{
off_z = 0;
}
if(off_z>255)
{
off_z = 255;
}
// Verify(off_x>=0 && off_x < 256);
// Verify(off_z>=0 && off_z < 256);
// Scalar mapIntensity = maps[map_z*mapZoneCountX+map_x][(off_z<<8)+off_x]*One_Over_255;
BYTE b = maps[map_z*mapZoneCountX+map_x][(off_z<<5)+(off_x>>3)];
Scalar mapIntensity = b & (0x80>>(off_x&3)) ? intensity : shadowIntensity;
//
//-------------------------------------------------------------------
// Now we reduce the light level falling on the vertex based upon the
// cosine of the angle between light and normal
//-------------------------------------------------------------------
//
Scalar cosine = mapIntensity;
RGBColor light_color(color);
if (cosine > SMALL)
{
light_color.red *= cosine;
light_color.green *= cosine;
light_color.blue *= cosine;
rcol.red += light_color.red;
rcol.green += light_color.green;
rcol.blue += light_color.blue;
}
}