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.
506 lines
11 KiB
C++
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;
|
|
}
|
|
} |