Files
firestorm/Gameleap/code/mw4/Libraries/elementrenderer/Element.hpp
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

750 lines
19 KiB
C++

#pragma once
#include "ElementRenderer.hpp"
#include <MLR\MLR.hpp>
#include <MLR\GOSVertex.hpp>
namespace MidLevelRenderer {
class MLRLight;
class MLRTexture;
class MLRShape;
}
namespace ElementRenderer {
class CameraElement;
class StateChange;
class Element__ClassData;
typedef MidLevelRenderer::MLRLight* LightList[MidLevelRenderer::Limits::Max_Number_Of_Lights_Per_Primitive];
class CollisionQuery
#if defined(_ARMOR)
: public Stuff::Signature
#endif
{
public:
CollisionQuery(Stuff::Line3D *l, Stuff::Normal3D *n):
m_line(l),
m_normal(n),
m_data(NULL)
{Check_Pointer(this);}
Stuff::Line3D *m_line;
Stuff::Normal3D *m_normal;
void *m_data;
BYTE m_material;
void TestInstance() const
{}
};
class SphereTest
#if defined(_ARMOR)
: public Stuff::Signature
#endif
{
public:
enum TestCase {
Disjoint=0,
Intersects=1,
Contains=2,
Contained=4
};
Stuff::Sphere m_sphere;
int m_type;
void TestInstance() const
{}
};
//#########################################################################
//########################### Element ###################################
//#########################################################################
class _declspec(novtable) Element:
public Stuff::Plug
{
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Initialization
//
public:
static void InitializeClass();
static void TerminateClass();
typedef Element__ClassData ClassData;
static ClassData *DefaultData;
typedef Stuff::Plug BaseClass;
static Stuff::RGBAColor FadeColor;
typedef MidLevelRenderer::MLRShape* (*ShapeHolder)(
Stuff::MemoryStream *stream,
int version,
int length
);
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Constructors/Destructors
//
protected:
Element(ClassData *class_data);
explicit Element(
ClassData *class_data,
Element *element
);
Element(
ClassData *class_data,
Stuff::MemoryStream *stream,
int version
);
public:
~Element();
typedef Element* (*Factory)(
Stuff::MemoryStream *stream,
int version,
ShapeHolder shapes
);
virtual void Save(Stuff::MemoryStream *stream);
static Element* Create(
Stuff::MemoryStream *stream,
int version,
ShapeHolder shapes=NULL
);
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Testing
//
public:
void TestInstance();
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Hierarchy
//
public:
Element* GetParentElement()
{Check_Object(this); return m_parent;}
void DetachFromParent()
{
Check_Object(this); Check_Object(m_parent);
m_parent->DetachChild(this); Verify(!m_parent);
}
void AttachToParent(Element *parent)
{
Check_Object(this); Check_Object(parent);
Verify(!m_parent); parent->AttachChild(this);
Check_Object(m_parent);
}
virtual void AttachChild(Element *child)=0;
virtual void DetachChild(Element *child)=0;
void SetClientData(void *data)
{Check_Object(this); m_data = data;}
void* GetClientData()
{Check_Object(this); return m_data;}
protected:
static void SetParentElement(
Element *child,
Element *parent
)
{Check_Object(child); child->m_parent = parent;}
Element *m_parent;
void *m_data;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// States
//
public:
enum {
LocalToParentIsIdentityBit = 0,
BoundsLockedBit,
SyncStateBit,
MatrixDirtyBit = SyncStateBit,
BoundsWrongBit,
SyncOnCullBit,
CullStateBit,
OBBBit = CullStateBit,
CullBit,
CullBits = 2,
AlignXBit = CullBit+CullBits,
SyncStateBits = AlignXBit - SyncStateBit,
AlignYBit = AlignXBit+1,
DrawStateBit,
CullStateBits = DrawStateBit - CullStateBit,
PropertyChangeBit = DrawStateBit,
DrawStateBits = 1,
CallbackBit = DrawStateBit+1,
CallbackBits = 3,
NoShadowBit = CallbackBit+CallbackBits
};
enum {
LocalToParentIsIdentityFlag = 1<<LocalToParentIsIdentityBit,
BoundsLockedFlag = 1<<BoundsLockedBit,
SyncStateMask = 0xFFFFFFFF >> (Stuff::INT_BITS - SyncStateBits),
SyncStateCount = 1<<SyncStateBits,
MatrixDirtyFlag = 1<<MatrixDirtyBit,
BoundsWrongFlag = 1<<BoundsWrongBit,
SyncOnCullFlag = 1<<SyncOnCullBit,
OBBFlag = 1<<OBBBit,
CullMask = (0xFFFFFFFF >> (Stuff::INT_BITS - CullBits)) << CullBit,
RootMode = 0,
VolumeCullMode = 1<<CullBit,
NeverCullMode = 2<<CullBit,
AlwaysCullMode = 3<<CullBit,
CullStateMask = 0xFFFFFFFF >> (Stuff::INT_BITS - CullStateBits),
CullStateCount = 1<<CullStateBits,
AlignXFlag = 1<<AlignXBit,
AlignYFlag = 1<<AlignYBit,
DrawStateMask = 0xFFFFFFFF >> (Stuff::INT_BITS - DrawStateBits),
DrawStateCount = 1<<DrawStateBits,
PropertyChangeFlag = 1<<PropertyChangeBit,
CallbackMask = (0xFFFFFFFF >> (Stuff::INT_BITS - CallbackBits)) << CallbackBit,
NoShadowFlag = 1<<NoShadowBit
};
bool IsLocalToParentIdentity()
{Check_Object(this); return (m_state & LocalToParentIsIdentityFlag) != 0;}
void LockBounds()
{Check_Object(this); m_state |= BoundsLockedFlag;}
void UnlockBounds()
{Check_Object(this); m_state &= ~BoundsLockedFlag;}
bool AreBoundsLocked()
{Check_Object(this); return (m_state & BoundsLockedFlag) != 0;}
void NeedMatrixSync()
{Check_Object(this); m_state |= MatrixDirtyFlag; SetSyncState();}
bool IsMatrixDirty()
{Check_Object(this); return (m_state & MatrixDirtyFlag) != 0;}
void NeedNewBounds()
{
Check_Object(this);
m_state &= ~CullMask;
m_state |= BoundsWrongFlag|VolumeCullMode;
Verify(!IsBoundedByOBB());
SetSyncState(); SetCullState();
}
bool AreBoundsWrong()
{Check_Object(this); return (m_state & BoundsWrongFlag) != 0;}
void ImmediateSync()
{Check_Object(this); m_state &= ~SyncOnCullFlag;}
void DeferredSync()
{Check_Object(this); m_state |= SyncOnCullFlag;}
bool IsSyncDeferred()
{Check_Object(this); return (m_state & SyncOnCullFlag) != 0;}
void SetOBBMode()
{
Check_Object(this); m_state |= OBBFlag;
SetSyncState(); SetCullState();
}
void SetSphereMode()
{
Check_Object(this); m_state &= ~OBBFlag;
SetSyncState(); SetCullState();
}
bool IsBoundedByOBB()
{Check_Object(this); return (m_state&OBBFlag) != 0;}
bool IsBoundedBySphere()
{Check_Object(this); return !(m_state&OBBFlag);}
void SetRootMode()
{
Check_Object(this);
m_parent = NULL;
m_state &= ~CullMask;
m_state |= RootMode;
SetSyncState(); SetCullState();
}
void SetAlwaysCullMode()
{
Check_Object(this);
Check_Object(m_parent);
m_state &= ~CullMask;
m_state |= AlwaysCullMode;
SetSyncState(); SetCullState();
}
void SetVolumeCullMode()
{
Check_Object(this);
Check_Object(m_parent);
m_state &= ~CullMask;
m_state |= VolumeCullMode|MatrixDirtyFlag;
SetSyncState(); SetCullState();
}
void SetNeverCullMode()
{
Check_Object(this);
Check_Object(m_parent);
m_state &= ~CullMask;
m_state |= NeverCullMode;
SetSyncState(); SetCullState();
}
unsigned GetCullMode()
{Check_Object(this); return m_state & CullMask;}
void SetCullMode(unsigned cullMode)
{
Check_Object(this);
m_state = (m_state & (~CullMask)) | cullMode;
SetSyncState(); SetCullState();
}
void SetAlignX()
{
Check_Object(this); m_state |= AlignXFlag|SyncOnCullFlag;
SetSyncState(); SetCullState();
}
void ClearAlignX()
{
Check_Object(this); m_state &= ~(AlignXFlag|SyncOnCullFlag);
SetSyncState(); SetCullState();
}
bool IsAlignX()
{Check_Object(this); return (m_state&AlignXFlag) != 0;}
void SetAlignY()
{
Check_Object(this); m_state |= AlignYFlag|SyncOnCullFlag;
SetSyncState(); SetCullState();
}
void ClearAlignY()
{
Check_Object(this); m_state &= ~(AlignYFlag|SyncOnCullFlag);
SetSyncState(); SetCullState();
}
bool IsShadowed()
{Check_Object(this); return (m_state&NoShadowFlag) == 0;}
void DisableShadow()
{Check_Object(this); m_state |= NoShadowFlag;}
void EnableShadow()
{Check_Object(this); m_state &= ~NoShadowFlag;}
bool IsAlignY()
{Check_Object(this); return (m_state&AlignYFlag) != 0;}
unsigned GetElementState()
{Check_Object(this); return m_state;}
void SetElementState(unsigned state)
{
Check_Object(this); m_state = state;
SetSyncState(); SetCullState(); SetDrawState();
}
static void ReadStateFromPage(
Stuff::Page *page,
const Stuff::MString &prefix,
unsigned *state,
unsigned *delta,
Stuff::OBB *bounds
);
protected:
unsigned m_state;
void MatrixIsClean()
{
Check_Object(this);
m_state &= ~MatrixDirtyFlag; SetSyncState();
}
void BoundsAreRight()
{
Check_Object(this);
m_state &= ~BoundsWrongFlag; SetSyncState();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Sync support
//
public:
typedef void (Element::*SyncMethod)();
void SetLocalToParent(const Stuff::LinearMatrix4D& matrix)
{
Check_Object(this); Check_Object(&matrix);
m_state &= ~LocalToParentIsIdentityFlag;
NeedMatrixSync(); m_newLocalToParent = matrix;
}
void SetLocalToParentToIdentity()
{
Check_Object(this);
m_state |= LocalToParentIsIdentityFlag|MatrixDirtyFlag;
SetSyncState();
m_newLocalToParent = Stuff::LinearMatrix4D::Identity;
}
const Stuff::LinearMatrix4D& GetLocalToParent()
{Check_Object(this); return m_localToParent;}
const Stuff::LinearMatrix4D& GetNewLocalToParent()
{Check_Object(this); return m_newLocalToParent;}
const Stuff::LinearMatrix4D& GetLocalToWorld()
{
Check_Object(this); Check_Object(&m_localToWorld);
return m_localToWorld;
}
void Sync()
{
Check_Object(this);
Verify(m_sync != NULL);
(this->*m_sync)();
}
protected:
virtual void SetSyncState();
SyncMethod m_sync;
static SyncMethod SyncMethods[SyncStateCount];
Stuff::LinearMatrix4D
m_newLocalToParent,
m_localToParent,
m_localToWorld;
void NoneSyncMethod();
void DirtyRootSyncMethod();
void DeferSyncMethod();
void CleanSyncMethod();
void DirtySyncMethod();
void CleanSphereSyncMethod();
void DirtySphereSyncMethod();
void CleanOBBSyncMethod();
void DirtyOBBSyncMethod();
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Culling
//
public:
typedef int (Element::*CameraCullMethod)(CameraElement *camera);
typedef bool (Element::*RayCullMethod)(CollisionQuery *query);
typedef int (Element::*SphereTestMethod)(SphereTest *test);
struct CullMethod {
CameraCullMethod m_cameraCull;
RayCullMethod m_rayCull;
SphereTestMethod m_sphereTest;
};
int Cull(CameraElement *camera)
{
Check_Object(this); Check_Pointer(camera);
Verify(m_cameraCull != NULL);
return (this->*m_cameraCull)(camera);
}
const Stuff::OBB& GetWorldOBB()
{Check_Object(this); return m_worldOBB;}
Stuff::OBB m_localOBB;
protected:
Stuff::OBB m_worldOBB;
virtual void SetCullState();
CameraCullMethod m_cameraCull;
RayCullMethod m_rayCull;
SphereTestMethod m_sphereTest;
static CullMethod CullMethods[CullStateCount];
int NeverCullMethod(CameraElement *camera);
int AlwaysCullMethod(CameraElement *camera);
int SphereCullMethod(CameraElement *camera);
int OBBCullMethod(CameraElement *camera);
void AlignX(CameraElement *camera);
int DeferredXNeverCullMethod(CameraElement *camera);
int DeferredXAlwaysCullMethod(CameraElement *camera);
int DeferredXSphereCullMethod(CameraElement *camera);
int DeferredXOBBCullMethod(CameraElement *camera);
void AlignY(CameraElement *camera);
int DeferredYNeverCullMethod(CameraElement *camera);
int DeferredYAlwaysCullMethod(CameraElement *camera);
int DeferredYSphereCullMethod(CameraElement *camera);
int DeferredYOBBCullMethod(CameraElement *camera);
void AlignXY(CameraElement *camera);
int DeferredXYNeverCullMethod(CameraElement *camera);
int DeferredXYAlwaysCullMethod(CameraElement *camera);
int DeferredXYSphereCullMethod(CameraElement *camera);
int DeferredXYOBBCullMethod(CameraElement *camera);
bool NeverRayCullMethod(CollisionQuery *query);
bool AlwaysRayCullMethod(CollisionQuery *query);
bool SphereRayCullMethod(CollisionQuery *query);
bool OBBRayCullMethod(CollisionQuery *query);
int NeverSphereTestMethod(SphereTest *test);
int AlwaysSphereTestMethod(SphereTest *test);
int SphereSphereTestMethod(SphereTest *test);
int OBBSphereTestMethod(SphereTest *test);
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Collision
//
public:
bool CastRay(CollisionQuery *query)
{
Check_Object(this); Check_Object(query);
Verify(m_rayCull != NULL);
if ((this->*m_rayCull)(query))
return CastCulledRay(query);
return false;
}
Element* FindSmallestElementContaining(SphereTest *test)
{
Check_Object(this); Check_Object(test);
Verify(m_sphereTest != NULL);
Verify(test->m_type == SphereTest::Contains);
if (((this->*m_sphereTest)(test)&SphereTest::Contains) != 0)
return FindSmallestElementContainingCulled(test);
return NULL;
}
protected:
virtual bool CastCulledRay(CollisionQuery *query)=0;
virtual Element* FindSmallestElementContainingCulled(SphereTest *test)=0;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Drawing
//
public:
typedef void (Element::*DrawMethod)(
CameraElement *camera,
const StateChange *inherited_state,
int culling_state
);
void DrawTo(
CameraElement *camera,
const StateChange *inherited_state,
int culling_state
)
{
Check_Object(this); Check_Pointer(camera);
Verify(m_draw != NULL);
(this->*m_draw)(
camera,
inherited_state,
culling_state
);
}
virtual int CountTriangles()=0;
static int MixLights(
LightList new_lights,
const LightList parent_lights,
const LightList child_lights
);
virtual void CleanDamage();
virtual void ApplyDamage(
const Stuff::LinearMatrix4D &damage_spot,
Stuff::Scalar radius
);
virtual void ApplyDamageDecal(
const Stuff::LinearMatrix4D &damage_spot,
Stuff::Scalar radius,
MidLevelRenderer::MLRTexture *texture
);
virtual void CastShadow(
const Stuff::LinearMatrix4D &shadow_to_world,
const Stuff::UnitVector3D &sun_in_world,
Stuff::Scalar radius
);
virtual void MakeFootStep(
MidLevelRenderer::MLRShape *shape,
const Stuff::LinearMatrix4D &foot,
Stuff::Scalar radius,
MidLevelRenderer::MLRTexture *tex
);
virtual MidLevelRenderer::MLRShape* GetMLRShape(CameraElement *camera=NULL)
{Check_Object(this); return NULL;}
virtual void GetCoordData(Stuff::DynamicArrayOf<Stuff::Point3D> *array);
protected:
virtual void SetDrawState()=0;
DrawMethod m_draw;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Debugging aids
//
public:
typedef void (*Callback)(
CameraElement *camera,
const StateChange *state,
int culling_state,
Element *element
);
enum {
DrawGreenBounds=1,
DrawYellowBounds,
DrawRedBounds,
DrawGreenBoundsOnce,
DrawYellowBoundsOnce,
DrawRedBoundsOnce
};
void SetCallbackIndex(unsigned function)
{
Check_Object(this); Verify(function < 1<<CallbackBits);
m_state &= ~CallbackMask; m_state |= function << CallbackBit;
}
unsigned GetCallbackIndex()
{Check_Object(this); return (m_state&CallbackMask)>>CallbackBit;}
static Callback* GetCallbackSet()
{return CallbackSet;}
static void UseCallbackSet(Callback *callback)
{CallbackSet = callback;}
static void DrawOBB(
const Stuff::OBB& obb,
const Stuff::RGBAColor& color,
CameraElement *camera,
const StateChange *state,
int culling_state
);
static void DrawSphere(
const Stuff::OBB& obb,
const Stuff::RGBAColor& color,
CameraElement *camera,
const StateChange *state,
int culling_state
);
static void DrawGreenBoundsCallback(
CameraElement *camera,
const StateChange *state,
int culling_state,
Element *element
);
static void DrawYellowBoundsCallback(
CameraElement *camera,
const StateChange *state,
int culling_state,
Element *element
);
static void DrawRedBoundsCallback(
CameraElement *camera,
const StateChange *state,
int culling_state,
Element *element
);
static void DrawGreenBoundsOnceCallback(
CameraElement *camera,
const StateChange *state,
int culling_state,
Element *element
);
static void DrawYellowBoundsOnceCallback(
CameraElement *camera,
const StateChange *state,
int culling_state,
Element *element
);
static void DrawRedBoundsOnceCallback(
CameraElement *camera,
const StateChange *state,
int culling_state,
Element *element
);
static Callback Callbacks[1<<CallbackBits];
protected:
static Callback *CallbackSet;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Properties
//
public:
StateChange* GetStateChange()
{Check_Object(this); return m_stateChange;}
void AdoptStateChange(StateChange *set);
void DestroyStateChange();
protected:
StateChange *m_stateChange;
};
#define SYNC_METHOD(t, s) static_cast<SyncMethod>(&t::s##SyncMethod)
#define CULL_METHOD(t, c, r)\
{\
static_cast<CameraCullMethod>(&t::c##CullMethod),\
static_cast<RayCullMethod>(&t::r##RayCullMethod),\
static_cast<SphereTestMethod>(&t::r##SphereTestMethod)\
}
#define DRAW_METHOD(t, d) static_cast<DrawMethod>(&t::d##DrawMethod)
//##########################################################################
//####################### Element__ClassData #########################
//##########################################################################
class Element__ClassData:
public Stuff::Plug__ClassData
{
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
public:
Element__ClassData(
Stuff::RegisteredClass::ClassID class_id,
const char* class_name,
Stuff::Plug__ClassData *parent_class,
Element::Factory element_factory
):
RegisteredClass__ClassData(class_id, class_name, parent_class),
m_elementFactory(element_factory)
{}
Element::Factory m_elementFactory;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
public:
void TestInstance();
};
}