Skip to content

Commit

Permalink
Only render active NiSwitchNode child to shadow maps
Browse files Browse the repository at this point in the history
Avoid rendering all NiSwitchNode children.
  • Loading branch information
pr0bability committed Dec 16, 2024
1 parent a028063 commit 20dc6e0
Show file tree
Hide file tree
Showing 3 changed files with 141 additions and 3 deletions.
32 changes: 31 additions & 1 deletion src/NewVegas/nvse/GameNi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,37 @@ bool NiSkinInstance::IsPartitionEnabled(UInt32 partitionIndex) {
}
}
return true;
}
}

// 0x6532C0
bool NiObject::IsKindOf(const NiRTTI& apRTTI) const {
return GetRTTI()->IsKindOf(apRTTI);
}

// 0x6532C0
bool NiObject::IsKindOf(const NiRTTI* const apRTTI) const {
return GetRTTI()->IsKindOf(apRTTI);
}

// 0x45BAF0
bool NiObject::IsExactKindOf(const NiRTTI* const apRTTI) const {
return GetRTTI()->IsExactKindOf(apRTTI);
}

// 0x45BAF0
bool NiObject::IsExactKindOf(const NiRTTI& apRTTI) const {
return GetRTTI()->IsExactKindOf(apRTTI);
}

// 0x45BAD0
bool NiObject::IsExactKindOf(const NiRTTI& apRTTI, NiObject* apObject) {
return apObject && apObject->IsExactKindOf(apRTTI);
}

// 0x45BAD0
bool NiObject::IsExactKindOf(const NiRTTI* const apRTTI, NiObject* apObject) {
return apObject && apObject->IsExactKindOf(apRTTI);
}

void NiObject::LogObjectAttributes(){
NiTArray<char*>* debug = (NiTArray<char*>*) Pointers::Functions::FormMemoryAlloc(sizeof(NiTArray<char*>));
Expand Down
98 changes: 96 additions & 2 deletions src/NewVegas/nvse/GameNi.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,9 +86,49 @@ class ImageSpaceShaderParam;
struct NiRTTI {
const char* name;
NiRTTI* parent;

const char* GetName() const { return name; }
const NiRTTI* GetBase() const { return parent; }

bool IsKindOf(const NiRTTI& apRTTI) const {
for (const NiRTTI* i = this; i; i = i->GetBase()) {
if (i == &apRTTI)
return true;
}
return false;
}

bool IsKindOf(const NiRTTI* apRTTI) const {
for (const NiRTTI* i = this; i; i = i->GetBase()) {
if (i == apRTTI)
return true;
}
return false;
}

template <typename T_RTTI>
bool IsKindOf() const {
return IsKindOf(T_RTTI::ms_RTTI);
}

bool IsExactKindOf(const NiRTTI* const apRTTI) const {
return this == apRTTI;
}

bool IsExactKindOf(const NiRTTI& apRTTI) const {
return this == &apRTTI;
}

template <typename T_RTTI>
bool IsExactKindOf() const {
return IsExactKindOf(T_RTTI::ms_RTTI);
}
};
assert(sizeof(NiRTTI) == 0x008);

#define NIRTTI_ADDRESS(address) \
static inline const NiRTTI* const ms_RTTI = (NiRTTI*)address;

enum NiMemEventType {
NI_UNKNOWN = 0x0,
NI_OPER_NEW = 0x1,
Expand Down Expand Up @@ -514,7 +554,7 @@ assert(sizeof(NiRefObject) == 0x008);

class NiObject : public NiRefObject {
public:
virtual const NiRTTI* GetRTTI();
virtual const NiRTTI* GetRTTI() const;
virtual NiNode* IsNiNode();
virtual BSFadeNode* IsFadeNode();
virtual BSMultiBoundNode* IsMultiBoundNode();
Expand Down Expand Up @@ -547,7 +587,30 @@ class NiObject : public NiRefObject {
virtual void Unk_20();
virtual void Unk_21();
virtual void Unk_22();


NIRTTI_ADDRESS(0x11F4418);

template <class T_RTTI>
bool IsKindOf() const {
return IsKindOf(T_RTTI::ms_RTTI);
}

template <class T_RTTI>
bool IsExactKindOf() const {
return IsExactKindOf(T_RTTI::ms_RTTI);
}

bool IsKindOf(const NiRTTI& apRTTI) const;

bool IsKindOf(const NiRTTI* const apRTTI) const;

bool IsExactKindOf(const NiRTTI* const apRTTI) const;

bool IsExactKindOf(const NiRTTI& apRTTI) const;

static bool IsExactKindOf(const NiRTTI& apRTTI, NiObject* apObject);

static bool IsExactKindOf(const NiRTTI* const apRTTI, NiObject* apObject);

void LogObjectAttributes();
};
Expand Down Expand Up @@ -676,6 +739,8 @@ class NiNode : public NiAVObject {
virtual bool Unk_3D();
virtual bool Unk_3E();
virtual bool Unk_3F();

NIRTTI_ADDRESS(0x11F4428);

void New(UInt16 Children);

Expand All @@ -688,9 +753,38 @@ class NiBillboardNode : public NiNode {
virtual void Unk_40();

UInt32 unkAC[2]; // AC

NIRTTI_ADDRESS(0x11D5E70);
};
assert(sizeof(NiBillboardNode) == 0xB4);

class NiSwitchNode : public NiNode {
public:
enum {
UPDATE_ONLY_ACTIVE_CHILD = 1,
UPDATE_CONTROLLERS = 2,
};

UInt16 m_usFlags;
SInt32 m_iIndex;
float m_fSavedTime;
UInt32 m_uiRevID;
NiTArray<UInt32> m_kChildRevID;

CREATE_OBJECT(NiSwitchNode, 0xA94550);
NIRTTI_ADDRESS(0x11F5EB4);
};
assert(sizeof(NiSwitchNode) == 0xCC);

class NiLODNode : public NiSwitchNode {
public:
void* m_spLODData;
bool m_bLODActive;

static SInt32 ms_iGlobalLOD;
};
assert(sizeof(NiLODNode) == 0xD4);

class NiCamera : public NiAVObject {
public:
D3DMATRIX WorldToCam; // 94
Expand Down
14 changes: 14 additions & 0 deletions src/core/ShadowManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,20 @@ void ShadowManager::AccumChildren(NiAVObject* NiObject, ShadowsExteriorEffect::F
if (!Node || Node->m_flags & NiAVObject::NiFlags::APP_CULLED) continue; // culling containers
if (!isLand && Node->GetWorldBoundRadius() < Forms->MinRadius) continue;

if (Node->IsKindOf<NiSwitchNode>()) {
// NiSwitchNode - only render active children (if exists) to the shadow map.
NiSwitchNode* SwitchNode = static_cast<NiSwitchNode*>(Node);
if (SwitchNode->m_iIndex < 0)
continue;

child = Node->m_children.data[SwitchNode->m_iIndex];
if (!child->IsGeometry())
containers.push(child);
else
AccumObject(&containers, child, Forms);
continue;
}

for (int i = 0; i < Node->m_children.end; i++) {
child = Node->m_children.data[i];
if (!child || child->m_flags & NiAVObject::NiFlags::APP_CULLED) continue; // culling children
Expand Down

0 comments on commit 20dc6e0

Please sign in to comment.