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.
516 lines
13 KiB
C++
516 lines
13 KiB
C++
#include "MLRHeaders.hpp"
|
|
|
|
//#############################################################################
|
|
//######################### MLRProjectLight ################################
|
|
//#############################################################################
|
|
|
|
MLRProjectLight::ClassData*
|
|
MLRProjectLight::DefaultData = NULL;
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
MLRProjectLight::InitializeClass()
|
|
{
|
|
Verify(!DefaultData);
|
|
Verify(gos_GetCurrentHeap() == StaticHeap);
|
|
DefaultData =
|
|
new ClassData(
|
|
MLRProjectLightClassID,
|
|
"MidLevelRenderer::MLRProjectLight",
|
|
MLRInfiniteLightWithFalloff::DefaultData
|
|
);
|
|
Register_Object(DefaultData);
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
MLRProjectLight::TerminateClass()
|
|
{
|
|
Unregister_Object(DefaultData);
|
|
delete DefaultData;
|
|
DefaultData = NULL;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
MLRProjectLight::MLRProjectLight() :
|
|
MLRInfiniteLightWithFalloff(DefaultData)
|
|
{
|
|
Verify(gos_GetCurrentHeap() == LightsHeap);
|
|
lightMap = NULL;
|
|
|
|
inverseLightToShape = Matrix4D::Identity;
|
|
|
|
xMin = -0.005f;
|
|
xMax = 0.005f;
|
|
yMin = -0.005f;
|
|
yMax = 0.005f;
|
|
nnear = 0.1f;
|
|
ffar = 1.9f;
|
|
distance = -1.0f;
|
|
|
|
CreateProjectMatrix();
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
MLRProjectLight::MLRProjectLight(
|
|
Stuff::MemoryStream *stream,
|
|
int version
|
|
) :
|
|
MLRInfiniteLightWithFalloff(DefaultData, stream, version)
|
|
{
|
|
Check_Object(stream);
|
|
Verify(gos_GetCurrentHeap() == LightsHeap);
|
|
lightMap = NULL;
|
|
if (version > 7)
|
|
{
|
|
MString name;
|
|
*stream >> name;
|
|
if (name.GetLength() > 0)
|
|
{
|
|
Check_Object(MLRTexturePool::Instance);
|
|
MLRTexture *texture = (*MLRTexturePool::Instance)(name, 0);
|
|
if (!texture)
|
|
texture = MLRTexturePool::Instance->Add(name, 0);
|
|
Check_Object(texture);
|
|
lightMap = new MLRLightMap(texture);
|
|
Register_Object(lightMap);
|
|
lightMap->AttachReference();
|
|
lightMask |= MLRState::LightMapLightingMode;
|
|
}
|
|
}
|
|
Radian angle;
|
|
*stream >> angle;
|
|
SetSpreadAngle(angle);
|
|
|
|
inverseLightToShape = Matrix4D::Identity;
|
|
|
|
xMin = -0.05f;
|
|
xMax = 0.05f;
|
|
yMin = -0.05f;
|
|
yMax = 0.05f;
|
|
nnear = 0.1f;
|
|
ffar = 1.9f;
|
|
distance = -1.0f;
|
|
|
|
CreateProjectMatrix();
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
MLRProjectLight::MLRProjectLight(Stuff::Page *page):
|
|
MLRInfiniteLightWithFalloff(DefaultData, page)
|
|
{
|
|
Check_Object(page);
|
|
Verify(gos_GetCurrentHeap() == LightsHeap);
|
|
lightMap = NULL;
|
|
const char* lightmap;
|
|
if (page->GetEntry("LightMap", &lightmap))
|
|
{
|
|
Check_Pointer(lightmap);
|
|
Check_Object(MLRTexturePool::Instance);
|
|
MLRTexture *texture = (*MLRTexturePool::Instance)(lightmap, 0);
|
|
if (!texture)
|
|
texture = MLRTexturePool::Instance->Add(lightmap, 0);
|
|
Check_Object(texture);
|
|
lightMap = new MLRLightMap(texture);
|
|
Register_Object(lightMap);
|
|
lightMap->AttachReference();
|
|
lightMask |= MLRState::LightMapLightingMode;
|
|
}
|
|
Degree angle=45.0;
|
|
page->GetEntry("Spread", &angle.angle);
|
|
SetSpreadAngle(angle);
|
|
|
|
inverseLightToShape = Matrix4D::Identity;
|
|
|
|
xMin = -0.05f;
|
|
xMax = 0.05f;
|
|
yMin = -0.05f;
|
|
yMax = 0.05f;
|
|
nnear = 0.1f;
|
|
ffar = 1.9f;
|
|
distance = -1.0f;
|
|
|
|
CreateProjectMatrix();
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
MLRProjectLight::~MLRProjectLight()
|
|
{
|
|
if(lightMap!=NULL)
|
|
{
|
|
lightMap->DetachReference();
|
|
}
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
MLRProjectLight::Save(Stuff::MemoryStream *stream)
|
|
{
|
|
Check_Object(this);
|
|
Check_Object(stream);
|
|
|
|
MLRInfiniteLightWithFalloff::Save(stream);
|
|
if (lightMap)
|
|
{
|
|
Check_Object(lightMap);
|
|
unsigned handle = lightMap->GetState().GetTextureHandle();
|
|
MLRTexture *texture = (*MLRTexturePool::Instance)[handle];
|
|
Check_Object(texture);
|
|
MString name = texture->GetTextureName();
|
|
*stream << name;
|
|
}
|
|
else
|
|
*stream << *MString::s_Empty;
|
|
*stream << spreadAngle;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
MLRProjectLight::Write(Stuff::Page *page)
|
|
{
|
|
Check_Object(this);
|
|
Check_Object(page);
|
|
|
|
MLRInfiniteLightWithFalloff::Write(page);
|
|
if (lightMap)
|
|
{
|
|
Check_Object(lightMap);
|
|
unsigned handle = lightMap->GetState().GetTextureHandle();
|
|
MLRTexture *texture = (*MLRTexturePool::Instance)[handle];
|
|
Check_Object(texture);
|
|
page->SetEntry("LightMap", texture->GetTextureName());
|
|
}
|
|
page->SetEntry("Spread", spreadAngle * Degrees_Per_Radian);
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
MLRProjectLight::TestInstance()
|
|
{
|
|
Verify(IsDerivedFrom(DefaultData));
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
MLRProjectLight::CreateProjectMatrix()
|
|
{
|
|
Matrix4D m4_1, m4_2;
|
|
m4_1 = Matrix4D::Identity;
|
|
// m4_1.BuildTranslation(Point3D(0.5f, 0.5f, 0.0f));
|
|
|
|
// m4_1(0,0) = 0.5f;
|
|
// m4_1(1,1) = 0.5f;
|
|
// m4_1(2,2) = 1.0f;
|
|
|
|
m4_2 = Matrix4D::Identity;
|
|
m4_2.SetPerspective(nnear, ffar, xMax, xMin, yMax, yMin);
|
|
|
|
projMatrix.Multiply(m4_2, m4_1);
|
|
|
|
LinearMatrix4D moveBack;
|
|
moveBack = LinearMatrix4D::Identity;
|
|
moveBack.BuildTranslation(Point3D(0.0f, 0.0f, distance));
|
|
|
|
m4_1.Multiply(moveBack, projMatrix);
|
|
|
|
projMatrix = m4_1;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
MLRProjectLight::InitLineTextureProjection(
|
|
Stuff::Point3D *lineTestPoints,
|
|
Stuff::RGBAColor *lineTestColors
|
|
)
|
|
{
|
|
Point3D p[8];
|
|
|
|
p[0] = Point3D(xMin, yMin, (nnear + distance));
|
|
p[1] = Point3D(xMax, yMin, (nnear + distance));
|
|
p[2] = Point3D(xMax, yMax, (nnear + distance));
|
|
p[3] = Point3D(xMin, yMax, (nnear + distance));
|
|
|
|
float t = ffar / nnear;
|
|
p[4] = Point3D(xMin * t, yMin * t, (ffar + distance));
|
|
p[5] = Point3D(xMax * t, yMin * t, (ffar + distance));
|
|
p[6] = Point3D(xMax * t, yMax * t, (ffar + distance));
|
|
p[7] = Point3D(xMin * t, yMax * t, (ffar + distance));
|
|
|
|
lineTestPoints[0] = p[0]; lineTestPoints[1] = p[1];
|
|
lineTestPoints[2] = p[1]; lineTestPoints[3] = p[2];
|
|
lineTestPoints[4] = p[2]; lineTestPoints[5] = p[3];
|
|
lineTestPoints[6] = p[3]; lineTestPoints[7] = p[0];
|
|
|
|
lineTestPoints[8] = p[0]; lineTestPoints[9] = p[4];
|
|
lineTestPoints[10] = p[1]; lineTestPoints[11] = p[5];
|
|
lineTestPoints[12] = p[2]; lineTestPoints[13] = p[6];
|
|
lineTestPoints[14] = p[3]; lineTestPoints[15] = p[7];
|
|
|
|
lineTestPoints[16] = p[4]; lineTestPoints[17] = p[5];
|
|
lineTestPoints[18] = p[5]; lineTestPoints[19] = p[6];
|
|
lineTestPoints[20] = p[6]; lineTestPoints[21] = p[7];
|
|
lineTestPoints[22] = p[7]; lineTestPoints[23] = p[4];
|
|
|
|
|
|
for(int i=0;i<24;i++)
|
|
{
|
|
lineTestColors[i] = RGBAColor (
|
|
Random::GetFraction(),
|
|
Random::GetFraction(),
|
|
Random::GetFraction(),
|
|
1.0f
|
|
);
|
|
}
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
MLRProjectLight::SetLightToShapeMatrix(const LinearMatrix4D& worldToShape)
|
|
{
|
|
Check_Object(this);
|
|
|
|
lightToShape.Multiply(lightToWorld, worldToShape);
|
|
inverseLightToShape.Invert(lightToShape);
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
MLRProjectLight::SetSpreadAngle(const Radian &radian)
|
|
{
|
|
Check_Object(this);
|
|
|
|
spreadAngle = radian;
|
|
|
|
tanSpreadAngle = (Scalar)tan(spreadAngle);
|
|
cosSpreadAngle = (Scalar)cos(spreadAngle);
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
MLRProjectLight::SetSpreadAngle(const Degree °ree)
|
|
{
|
|
Check_Object(this);
|
|
|
|
spreadAngle = degree;
|
|
|
|
tanSpreadAngle = (Scalar)tan(spreadAngle);
|
|
cosSpreadAngle = (Scalar)cos(spreadAngle);
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
bool
|
|
MLRProjectLight::GetSpreadAngle(Radian *angle)
|
|
{
|
|
Check_Object(this);
|
|
|
|
*angle = spreadAngle;
|
|
|
|
return true;
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
MLRProjectLight::LightVertex(const MLRVertexData& vertexData)
|
|
{
|
|
UnitVector3D light_z;
|
|
RGBColor light_color(color);
|
|
Point3D vertex_to_light;
|
|
|
|
Verify(GetFalloffDistance(vertex_to_light.x, vertex_to_light.y));
|
|
|
|
GetInShapePosition(vertex_to_light);
|
|
|
|
vertex_to_light -= *vertexData.point;
|
|
|
|
//
|
|
//--------------------------------------------------------------
|
|
// If the distance to the vertex is zero, the light will not
|
|
// contribute to the vertex coloration. Otherwise, decrease the
|
|
// light level as appropriate to the distance
|
|
//--------------------------------------------------------------
|
|
//
|
|
Scalar length = vertex_to_light.GetApproximateLength();
|
|
|
|
Scalar falloff = 1.0f;
|
|
if(GetFalloff(length, falloff))
|
|
{
|
|
light_color.red *= falloff;
|
|
light_color.green *= falloff;
|
|
light_color.blue *= falloff;
|
|
}
|
|
else
|
|
{
|
|
return;
|
|
}
|
|
|
|
Scalar cos_spread_angle = GetCosSpreadAngle();
|
|
|
|
GetInShapeDirection(light_z);
|
|
|
|
length = -1.0f / length;
|
|
vertex_to_light *= length;
|
|
|
|
Scalar t = vertex_to_light * light_z;
|
|
|
|
if (t <= cos_spread_angle)
|
|
{
|
|
return;
|
|
}
|
|
|
|
/* Verify(!Close_Enough(cos_spread_angle, 1.0f));
|
|
|
|
spread = 1.0f - ((1.0f - t) / (1.0f - cos_spread_angle));
|
|
|
|
light_color.red *= cos_spread_angle;
|
|
light_color.green *= cos_spread_angle;
|
|
light_color.blue *= cos_spread_angle;
|
|
*/
|
|
light_z.x = vertex_to_light.x;
|
|
light_z.y = vertex_to_light.y;
|
|
light_z.z = vertex_to_light.z;
|
|
|
|
//
|
|
//-------------------------------------------------------------------
|
|
// Now we reduce the light level falling on the vertex based upon the
|
|
// cosine of the angle between light and normal
|
|
//-------------------------------------------------------------------
|
|
//
|
|
Scalar cosine = 0.7071f;
|
|
|
|
if(vertexData.normal!=NULL)
|
|
{
|
|
cosine = -(light_z * (*vertexData.normal)); // * intensity;
|
|
}
|
|
|
|
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
|
|
MLRProjectLight::LightCenter(RGBAColor& rcol)
|
|
{
|
|
UnitVector3D light_z;
|
|
RGBColor light_color(color);
|
|
Point3D vertex_to_light;
|
|
|
|
Verify(GetFalloffDistance(vertex_to_light.x, vertex_to_light.y));
|
|
|
|
GetInShapePosition(vertex_to_light);
|
|
|
|
//
|
|
//--------------------------------------------------------------
|
|
// If the distance to the vertex is zero, the light will not
|
|
// contribute to the vertex coloration. Otherwise, decrease the
|
|
// light level as appropriate to the distance
|
|
//--------------------------------------------------------------
|
|
//
|
|
Scalar length = vertex_to_light.GetApproximateLength();
|
|
|
|
Scalar falloff = 1.0f;
|
|
if(GetFalloff(length, falloff))
|
|
{
|
|
light_color.red *= falloff;
|
|
light_color.green *= falloff;
|
|
light_color.blue *= falloff;
|
|
}
|
|
else
|
|
{
|
|
return;
|
|
}
|
|
|
|
Scalar cos_spread_angle = GetCosSpreadAngle();
|
|
|
|
GetInShapeDirection(light_z);
|
|
|
|
length = -1.0f / length;
|
|
vertex_to_light *= length;
|
|
|
|
Scalar t = vertex_to_light * light_z;
|
|
|
|
if (t <= cos_spread_angle)
|
|
{
|
|
return;
|
|
}
|
|
|
|
/* Verify(!Close_Enough(cos_spread_angle, 1.0f));
|
|
|
|
spread = 1.0f - ((1.0f - t) / (1.0f - cos_spread_angle));
|
|
|
|
light_color.red *= cos_spread_angle;
|
|
light_color.green *= cos_spread_angle;
|
|
light_color.blue *= cos_spread_angle;
|
|
*/
|
|
light_z.x = vertex_to_light.x;
|
|
light_z.y = vertex_to_light.y;
|
|
light_z.z = vertex_to_light.z;
|
|
|
|
//
|
|
//-------------------------------------------------------------------
|
|
// Now we reduce the light level falling on the vertex based upon the
|
|
// cosine of the angle between light and normal
|
|
//-------------------------------------------------------------------
|
|
//
|
|
Scalar cosine = 0.7071f;
|
|
|
|
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;
|
|
}
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
MLRProjectLight::SetLightMap(MLRLightMap *light_map)
|
|
{
|
|
Check_Object(this);
|
|
if (lightMap)
|
|
{
|
|
lightMap->DetachReference();
|
|
}
|
|
lightMap = light_map;
|
|
|
|
if (lightMap == NULL)
|
|
{
|
|
lightMask &= ~MLRState::LightMapLightingMode;
|
|
}
|
|
else
|
|
{
|
|
lightMap->AttachReference();
|
|
lightMask |= MLRState::LightMapLightingMode;
|
|
}
|
|
}
|