Files
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

507 lines
13 KiB
C++

#include "ElementRendererHeaders.hpp"
//############################################################################
//############################ LODElement ################################
//############################################################################
HGOSHEAP
ElementRenderer::LODElement::s_Heap = NULL;
ElementRenderer::LODElement::ClassData*
ElementRenderer::LODElement::DefaultData = NULL;
ElementRenderer::Element::DrawMethod
ElementRenderer::LODElement::DrawMethods[DrawStateCount]=
{
DRAW_METHOD(LODElement, Inherit),
DRAW_METHOD(LODElement, Override)
};
Stuff::Scalar ElementRenderer::LODElement::s_Offset = 0.0f;
bool ElementRenderer::LODElement::s_ShadeLODs = false;
Stuff::RGBAColor ElementRenderer::LODElement::s_Shades[6]={
Stuff::RGBAColor(1.0f, 1.0f, 1.0f, 1.0),
Stuff::RGBAColor(1.0f, 0.0f, 0.0f, 1.0),
Stuff::RGBAColor(0.0f, 1.0f, 0.0f, 1.0),
Stuff::RGBAColor(0.0f, 0.0f, 1.0f, 1.0),
Stuff::RGBAColor(1.0f, 1.0f, 0.0f, 1.0),
Stuff::RGBAColor(1.0f, 0.0f, 1.0f, 1.0)
};
static bool
__stdcall Check100m()
{
return ElementRenderer::LODElement::s_Offset == 625.0f;
}
static bool
__stdcall Check250m()
{
return ElementRenderer::LODElement::s_Offset == 2500.0f;
}
static bool
__stdcall Check500m()
{
return ElementRenderer::LODElement::s_Offset == 10000.0f;
}
static void
__stdcall Enable100m()
{
ElementRenderer::LODElement::s_Offset = (ElementRenderer::LODElement::s_Offset == 625.0f) ? 0.0f : 625.0f;
}
static void
__stdcall Enable250m()
{
ElementRenderer::LODElement::s_Offset = (ElementRenderer::LODElement::s_Offset == 2500.0f) ? 0.0f : 2500.0f;
}
static void
__stdcall Enable500m()
{
ElementRenderer::LODElement::s_Offset = (ElementRenderer::LODElement::s_Offset == 10000.0f) ? 0.0f : 10000.0f;
}
extern DWORD Disable_Lights;
static bool __stdcall CheckShadeLODs() {return ElementRenderer::LODElement::s_ShadeLODs;}
static void __stdcall EnableShadeLODs()
{
ElementRenderer::LODElement::s_ShadeLODs = !ElementRenderer::LODElement::s_ShadeLODs;
if (ElementRenderer::LODElement::s_ShadeLODs)
Disable_Lights = true;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
ElementRenderer::LODElement::InitializeClass(Stuff::NotationFile *startup_ini)
{
Verify(!s_Heap);
s_Heap = gos_CreateMemoryHeap("LOD", 0, g_LibraryHeap);
Check_Pointer(s_Heap);
Verify(!DefaultData);
DefaultData =
new ClassData(
LODElementClassID,
"ElementRenderer::LODElement",
BaseClass::DefaultData,
reinterpret_cast<Factory>(&Make)
);
Register_Object(DefaultData);
AddDebuggerMenuItem("Libraries\\ElementRenderer\\Shade LODs", CheckShadeLODs, EnableShadeLODs, 0 );
AddDebuggerMenuItem("Libraries\\Graphics Options\\+25m Shape LODs", Check100m, Enable100m, 0 );
AddDebuggerMenuItem("Libraries\\Graphics Options\\+50m Shape LODs", Check250m, Enable250m, 0 );
AddDebuggerMenuItem("Libraries\\Graphics Options\\+100m Shape LODs", Check500m, Enable500m, 0 );
if (startup_ini)
{
Check_Object(startup_ini);
Stuff::Page *page = startup_ini->FindPage("Graphics Options");
if (page)
{
Check_Object(page);
page->GetEntry("LOD", &s_Offset);
}
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
ElementRenderer::LODElement::TerminateClass(Stuff::NotationFile *startup_ini)
{
if (startup_ini)
{
Check_Object(startup_ini);
Stuff::Page *page = startup_ini->SetPage("Graphics Options");
Check_Object(page);
page->SetEntry("LOD", s_Offset);
}
Unregister_Object(DefaultData);
delete DefaultData;
DefaultData = NULL;
Check_Pointer(s_Heap);
gos_DestroyMemoryHeap(s_Heap);
s_Heap = NULL;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
ElementRenderer::LODElement::LODElement(
Stuff::MemoryStream *stream,
int version,
ShapeHolder shapes
):
SwitchElement(DefaultData, stream, version, shapes)
{
Check_Pointer(this);
Check_Object(stream);
unsigned index = (m_state>>DrawStateBit) & DrawStateMask;
Verify(index < DrawStateCount);
m_draw = DrawMethods[index];
//
//---------------------------------
// Create the shape from the stream
//---------------------------------
//
Verify(m_list.GetLength() < 65536);
WORD lod_count = static_cast<WORD>(m_list.GetLength());
m_LODs.SetLength(lod_count);
for (WORD lod=0; lod<lod_count; ++lod)
*stream >> m_LODs[lod].m_nearSquared >> m_LODs[lod].m_farSquared;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
ElementRenderer::LODElement::LODElement():
SwitchElement(DefaultData)
{
Check_Pointer(this);
unsigned index = (m_state>>DrawStateBit) & DrawStateMask;
Verify(index < DrawStateCount);
m_draw = DrawMethods[index];
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
ElementRenderer::LODElement::~LODElement()
{
Check_Object(this);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
ElementRenderer::LODElement*
ElementRenderer::LODElement::Make(
Stuff::MemoryStream *stream,
int version,
ShapeHolder shapes
)
{
Check_Object(stream);
gos_PushCurrentHeap(s_Heap);
LODElement *element = new LODElement(stream, version, shapes);
gos_PopCurrentHeap();
return element;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
ElementRenderer::LODElement::Save(Stuff::MemoryStream *stream)
{
Check_Object(this);
Check_Object(stream);
BaseClass::Save(stream);
//
//--------------------
// Save each LOD entry
//--------------------
//
Verify(m_list.GetLength() < 65536);
WORD lod_count = static_cast<WORD>(m_LODs.GetLength());
for (WORD lod=0; lod<lod_count; ++lod)
*stream << m_LODs[lod].m_nearSquared << m_LODs[lod].m_farSquared;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
ElementRenderer::LODElement::TestInstance()
{
Verify(IsDerivedFrom(DefaultData));
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
ElementRenderer::LODElement::AttachLOD(
WORD index,
Element *element,
const Entry &entry
)
{
Check_Object(this);
Verify(index < m_LODs.GetLength());
m_LODs[index] = entry;
AttachIndexedChild(index, element);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
ElementRenderer::LODElement::SetSize(WORD max_size)
{
Check_Object(this);
m_LODs.SetLength(max_size);
for (WORD i=0; i<max_size; ++i)
{
m_LODs[i].m_nearSquared = 0.0f;
m_LODs[i].m_farSquared = 0.0f;
}
BaseClass::SetSize(max_size);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
ElementRenderer::LODElement::DetachChild(Element *child)
{
Check_Object(this);
Check_Object(child);
//
//-------------------------------
// Find the element and unhook it
//-------------------------------
//
Verify(m_list.GetLength() < 65536);
WORD lod_count = static_cast<WORD>(m_LODs.GetLength());
for (WORD i=0; i<lod_count; ++i)
{
Entry *entry = &m_LODs[i];
if (m_list[i] == child)
{
entry->m_nearSquared = 0.0f;
entry->m_farSquared = 0.0f;
break;
}
}
BaseClass::DetachChild(child);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
ElementRenderer::LODElement::SetDrawState()
{
Check_Object(this);
unsigned index = (m_state>>DrawStateBit) & DrawStateMask;
Verify(index < DrawStateCount);
m_draw = DrawMethods[index];
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
ElementRenderer::LODElement::InheritDrawMethod(
CameraElement *camera,
const StateChange *inherited_state,
int culling_state
)
{
Check_Object(this);
Check_Object(inherited_state);
Check_Object(camera);
Verify(culling_state != -1);
//
//--------------------------------------
// Draw our bounds if we are supposed to
//--------------------------------------
//
#if defined(LAB_ONLY)
Callback *callback = GetCallbackSet();
unsigned index = GetCallbackIndex();
if (callback && callback[index])
{
Check_Pointer(callback[index]);
(*callback[index])(camera, inherited_state, culling_state, this);
}
#endif
//
//----------------------------------------------------------------------
// We need to find out which lod the camera should traverse into, so
// transform the camera into LOD space and get the distance from the LOD
//----------------------------------------------------------------------
//
Stuff::Point3D camera_origin(camera->GetLocalToWorld());
Stuff::Point3D lod_origin(GetLocalToWorld());
camera_origin -= lod_origin;
Stuff::Scalar distance = camera_origin.GetLengthSquared() + s_Offset;
Min_Clamp(distance, 0.0f);
//
//---------------------------------------------------
// Search the lod entries looking for the first match
//---------------------------------------------------
//
for (WORD i=0; i<m_LODs.GetLength(); ++i)
{
Entry *entry = &m_LODs[i];
if (entry->m_nearSquared <= distance && entry->m_farSquared >= distance)
{
#if defined(LAB_ONLY)
Stuff::RGBAColor old_fade;
if (s_ShadeLODs && i<ELEMENTS(s_Shades))
{
old_fade = FadeColor;
FadeColor = s_Shades[i];
}
#endif
Element *element = m_list[i];
Check_Object(element);
SetSwitch(i);
camera->DrawElement(element, inherited_state);
#if defined(LAB_ONLY)
if (s_ShadeLODs && i<ELEMENTS(s_Shades))
FadeColor = old_fade;
#endif
break;
}
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
ElementRenderer::LODElement::OverrideDrawMethod(
CameraElement *camera,
const StateChange *inherited_state,
int culling_state
)
{
Check_Object(this);
Check_Object(inherited_state);
Check_Object(camera);
Verify(culling_state != -1);
//
//-------------------
// Mix the properties
//-------------------
//
Check_Object(m_stateChange);
StateChange mixed;
mixed.Mix(*inherited_state, *m_stateChange);
MixLights(
mixed.m_lights,
inherited_state->m_lights,
m_stateChange->m_lights
);
//
//--------------------------------------
// Draw our bounds if we are supposed to
//--------------------------------------
//
#if defined(LAB_ONLY)
Callback *callback = GetCallbackSet();
unsigned index = GetCallbackIndex();
if (callback && callback[index])
{
Check_Pointer(callback[index]);
(*callback[index])(camera, inherited_state, culling_state, this);
}
#endif
//
//----------------------------------------------------------------------
// We need to find out which lod the camera should traverse into, so
// transform the camera into LOD space and get the distance from the LOD
//----------------------------------------------------------------------
//
Stuff::Point3D camera_origin(camera->GetLocalToWorld());
Stuff::Point3D lod_origin(GetLocalToWorld());
camera_origin -= lod_origin;
Stuff::Scalar distance = camera_origin.GetLengthSquared() + s_Offset;
Min_Clamp(distance, 0.0f);
//
//---------------------------------------------------
// Search the lod entries looking for the first match
//---------------------------------------------------
//
for (WORD i=0; i<m_LODs.GetLength(); ++i)
{
Entry *entry = &m_LODs[m_switch];
if (entry->m_nearSquared <= distance && entry->m_farSquared >= distance)
{
#if defined(LAB_ONLY)
Stuff::RGBAColor old_fade;
if (s_ShadeLODs && i<ELEMENTS(s_Shades))
{
old_fade = FadeColor;
FadeColor = s_Shades[i];
}
#endif
Element *element = m_list[m_switch];
Check_Object(element);
SetSwitch(i);
camera->DrawElement(element, &mixed);
#if defined(LAB_ONLY)
if (s_ShadeLODs && i<ELEMENTS(s_Shades))
FadeColor = old_fade;
#endif
break;
}
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
ElementRenderer::LODElement::CleanDamage()
{
Check_Object(this);
for(WORD i=0;i<GetActiveCount();i++)
{
Element *child = GetIndexedElement(i);
Check_Object(child);
child->CleanDamage();
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
ElementRenderer::LODElement::ApplyDamage(
const Stuff::LinearMatrix4D &damage_spot,
Stuff::Scalar radius
)
{
Check_Object(this);
for(WORD i=0;i<GetActiveCount();i++)
{
Element *child = GetIndexedElement(i);
Check_Object(child);
child->ApplyDamage(damage_spot, radius);
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
ElementRenderer::LODElement::ApplyDamageDecal(
const Stuff::LinearMatrix4D &damage_spot,
Stuff::Scalar radius,
MidLevelRenderer::MLRTexture *texture
)
{
Check_Object(this);
Check_Object(texture);
for(WORD i=0;i<GetActiveCount();i++)
{
Element *child = GetIndexedElement(i);
Check_Object(child);
child->ApplyDamageDecal(damage_spot, radius, texture);
}
}