Initial gamelib integration AAS2 with some animation and physics and another integration pass on idLib.

This commit is contained in:
Justin Marshall
2026-08-09 03:52:45 -07:00
parent cdf7d52214
commit 6d92a71d19
111 changed files with 15204 additions and 2275 deletions
@@ -0,0 +1,243 @@
#include "gamelib/animstack/animator_base.h"
#include "idlib/lib_print.h"
#include <cmath>
// idAnimStack and idGameTimeManager are not yet safe to materialize from the
// generated declarations. These named boundaries preserve every recovered
// animator-base call while their authoritative translation units are ported.
int GameLib_GetAnimatorIndex(const idAnimStack* stack,
const idAnimator_Base* animator);
void GameLib_AddAnimator(idAnimStack* stack, idAnimator_Base* animator);
void GameLib_RemoveAnimator(idAnimStack* stack, idAnimator_Base* animator);
void GameLib_SetAnimatorFlag(idAnimStack* stack, idAnimator_Base* animator,
int flag);
void GameLib_ClearAnimatorFlag(idAnimStack* stack, idAnimator_Base* animator,
int flag);
bool GameLib_IsAnimatorFlagSet(const idAnimStack* stack,
const idAnimator_Base* animator, int flag);
int GameLib_ConvertRealMillisecondsToGameTime(
const idGameTimeManager* gameTimeManager, int milliseconds);
int GameLib_GetGameTicksPerSecond();
bool GameLib_IsMD6NodeValid(const idMD6Node* node);
namespace {
enum animatorFlag_t {
ANIMATORFLAG_INITIALIZED = 0x01,
ANIMATORFLAG_ENABLED = 0x02,
ANIMATORFLAG_SERIALIZE = 0x08
};
bool IsBlendFinished(const idMD6Branch& branch) {
return branch.alphaRate == 0.0f ||
branch.currentAlpha == branch.targetAlpha;
}
bool IsBlendingOut(const idMD6Branch& branch) {
return branch.currentAlpha > 0.0f &&
branch.targetAlpha == 0.0f && branch.alphaRate != 0.0f;
}
bool IsBlendingIn(const idMD6Branch& branch) {
return branch.currentAlpha < 1.0f &&
branch.targetAlpha >= 1.0f && branch.alphaRate != 0.0f;
}
idTypesafeNumber<int, gameTimeUnique_t> ConvertBlendTime(
const idGameTimeManager* gameTimeManager, const int milliseconds) {
return idTypesafeNumber<int, gameTimeUnique_t>(
GameLib_ConvertRealMillisecondsToGameTime(
gameTimeManager, milliseconds));
}
} // namespace
idAnimator_Base::idAnimator_Base()
: gametimeManager{nullptr}
, weightGroup(MD6_WEIGHTGROUP_ALL)
, filterGroup(MD6_WEIGHTGROUP_ALL)
, serializeProps{{nullptr, nullptr}, nullptr, nullptr, false}
, initialized(false) {
}
idAnimator_Base::~idAnimator_Base() = default;
bool idAnimator_Base::InternalPostInit(
const idAnimatorParms_Base& parameters) {
if (parameters.animStack == nullptr) {
return false;
}
GameLib_SetAnimatorFlag(parameters.animStack, this,
ANIMATORFLAG_SERIALIZE);
return true;
}
void idAnimator_Base::Shutdown(idAnimStack* const stack) {
InternalShutdown(stack);
GameLib_ClearAnimatorFlag(stack, this, ANIMATORFLAG_INITIALIZED);
GameLib_RemoveAnimator(stack, this);
}
bool idAnimator_Base::IsInitialized(idAnimStack* const stack) const {
return stack != nullptr && GameLib_IsAnimatorFlagSet(
stack, this, ANIMATORFLAG_INITIALIZED);
}
bool idAnimator_Base::IsEnabled(idAnimStack* const stack) const {
return stack != nullptr && GameLib_IsAnimatorFlagSet(
stack, this, ANIMATORFLAG_ENABLED);
}
void idAnimator_Base::SetEnabled(idAnimStack* const stack,
const bool enabled) {
if (enabled) {
GameLib_SetAnimatorFlag(stack, this, ANIMATORFLAG_ENABLED);
} else {
GameLib_ClearAnimatorFlag(stack, this, ANIMATORFLAG_ENABLED);
}
}
bool idAnimator_Base::Init(idGameTimeManager* const gameTimeManager,
const idAnimatorParms_Base& parameters) {
if (GameLib_GetAnimatorIndex(parameters.animStack, this) >= 0 &&
initialized) {
idLibPrint::Error("Attempted to add idAnimator %s twice.",
parameters.name.c_str());
}
gametimeManager.gameTimeManager = gameTimeManager;
weightGroup = parameters.weightGroup;
filterGroup = parameters.filterGroup;
if (!InternalInit(parameters)) {
return false;
}
idMD6Branch* const branch = InternalGetMergeBranch();
if (branch != nullptr) {
branch->op = static_cast<std::uint8_t>(parameters.blendOp);
branch->originBlend =
static_cast<std::uint8_t>(parameters.originBlend);
branch->currentAlpha = parameters.alpha;
branch->targetAlpha = parameters.alpha;
branch->alphaRate = 0.0f;
branch->filterGroup =
static_cast<std::uint8_t>(parameters.filterGroup);
}
GameLib_AddAnimator(parameters.animStack, this);
GameLib_SetAnimatorFlag(parameters.animStack, this,
ANIMATORFLAG_INITIALIZED);
GameLib_SetAnimatorFlag(parameters.animStack, this,
ANIMATORFLAG_ENABLED);
initialized = true;
return InternalPostInit(parameters);
}
void idAnimator_Base::Blend(const idAnimStack* const stack,
const int currentTime, const float targetAlpha,
const int blendDurationMS, const bool reset) {
idMD6Branch* const branch = InternalGetMergeBranch();
branch->targetAlpha = targetAlpha;
const idTypesafeNumber<int, gameTimeUnique_t> blendTime =
ConvertBlendTime(gametimeManager.gameTimeManager, blendDurationMS);
const bool alreadyBlending = targetAlpha <= branch->currentAlpha
? IsBlendingOut(*branch)
: IsBlendingIn(*branch);
if (blendTime.value <= 0) {
branch->currentAlpha = targetAlpha;
branch->alphaRate = 0.0f;
} else if (reset || !alreadyBlending) {
branch->alphaRate = std::fabs(targetAlpha - branch->currentAlpha) *
(1000.0f / static_cast<float>(blendTime.value));
}
InternalBlend(stack, currentTime, targetAlpha, blendTime);
}
bool idAnimator_Base::IsContributing() const {
const idMD6Branch* const branch = InternalGetMergeBranch();
return branch != nullptr && branch->right != nullptr &&
GameLib_IsMD6NodeValid(branch->right) &&
(branch->currentAlpha > 0.0f || !IsBlendFinished(*branch)) &&
InternalIsContributing();
}
md6WeightGroup_t idAnimator_Base::GetFilterGroup() const {
return static_cast<md6WeightGroup_t>(
InternalGetMergeBranch()->filterGroup);
}
float idAnimator_Base::GetAlpha() const {
return InternalGetMergeBranch()->currentAlpha;
}
void idAnimator_Base::SetAlpha(const float alpha) {
InternalGetMergeBranch()->currentAlpha = alpha;
}
void idAnimator_Base::Pause(const idAnimStack* const stack,
const idTypesafeNumber<int, gameTimeUnique_t> currentTime) {
InternalPause(stack, currentTime);
}
void idAnimator_Base::Unpause(const idAnimStack* const stack,
const idTypesafeNumber<int, gameTimeUnique_t> currentTime) {
InternalUnpause(stack, currentTime);
}
void idAnimator_Base::Start(const idAnimStack* const stack,
const int currentTime, const int blendDurationMS, const bool reset) {
idMD6Branch* const branch = InternalGetMergeBranch();
const idTypesafeNumber<int, gameTimeUnique_t> blendTime =
ConvertBlendTime(gametimeManager.gameTimeManager, blendDurationMS);
if (blendTime.value <= 0) {
branch->currentAlpha = 1.0f;
branch->targetAlpha = 1.0f;
branch->alphaRate = 0.0f;
} else if (reset || !IsBlendingIn(*branch)) {
branch->targetAlpha = 1.0f;
branch->alphaRate = (1.0f - branch->currentAlpha) *
(static_cast<float>(GameLib_GetGameTicksPerSecond()) /
static_cast<float>(blendTime.value));
}
InternalStart(stack, currentTime, blendTime);
}
void idAnimator_Base::End(const idAnimStack* const stack,
const int currentTime, const int blendDurationMS, const bool reset) {
if (!initialized) {
return;
}
idMD6Branch* const branch = InternalGetMergeBranch();
branch->targetAlpha = 0.0f;
const idTypesafeNumber<int, gameTimeUnique_t> blendTime =
ConvertBlendTime(gametimeManager.gameTimeManager, blendDurationMS);
if (blendTime.value <= 0) {
branch->alphaRate = 0.0f;
branch->currentAlpha = 0.0f;
} else if (reset || !IsBlendingOut(*branch)) {
branch->alphaRate = branch->currentAlpha *
(static_cast<float>(GameLib_GetGameTicksPerSecond()) /
static_cast<float>(blendTime.value));
}
InternalEnd(stack, currentTime, blendTime);
}
void idAnimator_Base::PreSerializeInit(idAnimStack* const stack,
idClip* const clip, idGameTimeManager* const gameTimeManager) {
serializeProps.animStack = stack;
serializeProps.clip = clip;
gametimeManager.gameTimeManager = gameTimeManager;
serializeProps.createdThroughSerialization = true;
}
+95 -60
View File
@@ -1,72 +1,107 @@
#pragma once
// Reconstructed C++ declarations from IDA Local Types and PDB/DIA metadata.
// Original PDB header: w:\tech5\engine\gamelib\animstack\animator_base.h
// Recovered logical types: 4
// Signatures retain Xbox 360 ABI evidence and may still require manual review.
#include "gamelib/animstack/animstacktypes.h"
#include "idlib/text/str.h"
#include "idlib/typesafenumber.h"
class idSerializer;
// IDA Local Type ordinal 1357; PDB kind: enum.
enum idAnimator_Base::priority_t : __int32
{
PRIORITY_WEB = 0x0,
PRIORITY_AFTER_WEB = 0x1,
PRIORITY_IK = 0x63,
PRIORITY_AF = 0x64,
};
class idAnimatorParms_Base;
// IDA Local Type ordinal 14224; PDB kind: class.
class __declspec(align(4)) idAnimator_Base
{
class idAnimator_Base {
public:
// Recovered virtual interface; IDA vtable ordinal 14289.
virtual ~idAnimator_Base();
virtual idAnimator_Base::priority_t GetStackPriority();
virtual serializeType_t GetSerializeType();
virtual void SerializeSnapshot(idSerializer *);
virtual void PreBlendSnapshot(idAnimStack *, int, const int, float);
virtual void PreSerializeInit(idAnimStack *, idClip *, idGameTimeManager *);
virtual bool InternalInit(const idAnimatorParms_Base *);
virtual bool InternalPostInit(const idAnimatorParms_Base *);
virtual void InternalShutdown(idAnimStack *);
virtual void InternalPreBlendTree(const idAnimStack *, const int, const int);
virtual void InternalPostBlendTree(const idAnimStack *, const int);
virtual void InternalStart(const idAnimStack *, const int, const idTypesafeNumber<int,enum gameTimeUnique_t>);
virtual void InternalEnd(const idAnimStack *, const int, const idTypesafeNumber<int,enum gameTimeUnique_t>);
virtual void InternalBlend(const idAnimStack *, const int, const float, const idTypesafeNumber<int,enum gameTimeUnique_t>);
virtual bool InternalIsContributing();
virtual const idMD6Branch *InternalGetMergeBranch();
virtual idMD6Branch *InternalGetMergeBranch_2();
virtual void InternalPause(const idAnimStack *, const idTypesafeNumber<int,enum gameTimeUnique_t>);
virtual void InternalUnpause(const idAnimStack *, const idTypesafeNumber<int,enum gameTimeUnique_t>);
virtual const idMD6Branch *InternalGetEndBranch();
virtual idMD6Branch *InternalGetEndBranch_2();
enum priority_t : int {
PRIORITY_WEB = 0,
PRIORITY_AFTER_WEB = 1,
PRIORITY_IK = 99,
PRIORITY_AF = 100
};
idGameTimeManagerPtr gametimeManager;
md6WeightGroup_t weightGroup;
md6WeightGroup_t filterGroup;
idAnimator_Base::serializeProps_t serializeProps;
bool initialized;
struct serializeProps_t {
idMD6Branch* serializedTrees[2];
idAnimStack* animStack;
idClip* clip;
bool createdThroughSerialization;
};
idAnimator_Base();
virtual ~idAnimator_Base();
bool Init(idGameTimeManager* gameTimeManager,
const idAnimatorParms_Base& parameters);
void Shutdown(idAnimStack* stack);
bool IsInitialized(idAnimStack* stack) const;
bool IsEnabled(idAnimStack* stack) const;
void SetEnabled(idAnimStack* stack, bool enabled);
void Blend(const idAnimStack* stack, int currentTime, float targetAlpha,
int blendDurationMS, bool reset);
bool IsContributing() const;
md6WeightGroup_t GetFilterGroup() const;
float GetAlpha() const;
void SetAlpha(float alpha);
void Pause(const idAnimStack* stack,
idTypesafeNumber<int, gameTimeUnique_t> currentTime);
void Unpause(const idAnimStack* stack,
idTypesafeNumber<int, gameTimeUnique_t> currentTime);
void Start(const idAnimStack* stack, int currentTime,
int blendDurationMS, bool reset);
void End(const idAnimStack* stack, int currentTime,
int blendDurationMS, bool reset);
virtual priority_t GetStackPriority();
virtual serializeType_t GetSerializeType();
virtual void SerializeSnapshot(idSerializer* serializer);
virtual void PreBlendSnapshot(idAnimStack* stack, int currentTime,
int ticksPerSecond, float fraction);
virtual void PreSerializeInit(idAnimStack* stack, idClip* clip,
idGameTimeManager* gameTimeManager);
virtual bool InternalInit(const idAnimatorParms_Base& parameters);
virtual bool InternalPostInit(const idAnimatorParms_Base& parameters);
virtual void InternalShutdown(idAnimStack* stack);
virtual void InternalPreBlendTree(const idAnimStack* stack,
int currentTime, int ticksPerSecond);
virtual void InternalPostBlendTree(const idAnimStack* stack,
int currentTime);
virtual void InternalStart(const idAnimStack* stack, int currentTime,
idTypesafeNumber<int, gameTimeUnique_t> blendTime);
virtual void InternalEnd(const idAnimStack* stack, int currentTime,
idTypesafeNumber<int, gameTimeUnique_t> blendTime);
virtual void InternalBlend(const idAnimStack* stack, int currentTime,
float targetAlpha,
idTypesafeNumber<int, gameTimeUnique_t> blendTime);
virtual bool InternalIsContributing() const;
virtual const idMD6Branch* InternalGetMergeBranch() const;
virtual idMD6Branch* InternalGetMergeBranch();
virtual void InternalPause(const idAnimStack* stack,
idTypesafeNumber<int, gameTimeUnique_t> currentTime);
virtual void InternalUnpause(const idAnimStack* stack,
idTypesafeNumber<int, gameTimeUnique_t> currentTime);
virtual const idMD6Branch* InternalGetEndBranch() const;
virtual idMD6Branch* InternalGetEndBranch();
idGameTimeManagerPtr gametimeManager;
md6WeightGroup_t weightGroup;
md6WeightGroup_t filterGroup;
serializeProps_t serializeProps;
bool initialized;
};
// IDA Local Type ordinal 14288; PDB kind: class.
class idAnimatorParms_Base
{
class idAnimatorParms_Base {
public:
idAnimStack *animStack;
idStr name;
idMD6Blend::blendOp_t blendOp;
idMD6Blend::originBlend_t originBlend;
md6WeightGroup_t weightGroup;
md6WeightGroup_t filterGroup;
float alpha;
idAnimStack* animStack;
idStr name;
int blendOp;
int originBlend;
md6WeightGroup_t weightGroup;
md6WeightGroup_t filterGroup;
float alpha;
};
// IDA Local Type ordinal 14291; PDB kind: struct.
struct __declspec(align(4)) idAnimator_Base::serializeProps_t
{
idMD6Branch *serializedTrees[2];
idAnimStack *animStack;
idClip *clip;
bool createdThroughSerialization;
};
#if defined(_WIN32) && !defined(_WIN64)
static_assert(sizeof(idAnimator_Base::serializeProps_t) == 20,
"Recovered animator serialization properties ABI changed");
static_assert(sizeof(idAnimator_Base) == 40,
"Recovered idAnimator_Base ABI changed");
static_assert(sizeof(idAnimatorParms_Base) == 56,
"Recovered idAnimatorParms_Base ABI changed");
#endif
@@ -0,0 +1,79 @@
#include "gamelib/animstack/animator_paused.h"
idMD6Branch* GameLib_AllocMD6Branch(idAnimStack* stack);
idMD6LeafPause* GameLib_AllocMD6LeafPause(idAnimStack* stack);
void GameLib_FreeMD6Branch(idAnimStack* stack, idMD6Branch* branch);
void GameLib_FreeMD6LeafPause(idAnimStack* stack, idMD6LeafPause* leaf);
int GameLib_GetMD6AnimNumFrames(const idMD6Anim* animation);
idAnimator_Paused::idAnimator_Paused()
: idAnimator_Base()
, leaf(nullptr)
, mergeBranch(nullptr)
, anim(nullptr) {
}
idAnimator_Paused::~idAnimator_Paused() {
leaf = nullptr;
mergeBranch = nullptr;
anim = nullptr;
}
void idAnimator_Paused::SetAnim(const idMD6Anim* const animation) {
anim = animation;
if (animation != nullptr) {
leaf->Init(animation, leaf->frame, leaf->wrapMode,
MD6_WEIGHTGROUP_ALL);
}
leaf->anim = animation;
}
void idAnimator_Paused::SetFrame(const float animationFrame) {
leaf->frame = animationFrame;
}
float idAnimator_Paused::GetFrame() const {
return leaf->frame;
}
void idAnimator_Paused::SetNormalizedFrame(const float normalizedFrame) {
leaf->frame = static_cast<float>(GameLib_GetMD6AnimNumFrames(leaf->anim) - 1) *
normalizedFrame;
}
bool idAnimator_Paused::InternalInit(
const idAnimatorParms_Base& parameters) {
const idAnimatorParms_Pause& pauseParameters =
static_cast<const idAnimatorParms_Pause&>(parameters);
mergeBranch = GameLib_AllocMD6Branch(parameters.animStack);
leaf = GameLib_AllocMD6LeafPause(parameters.animStack);
mergeBranch->right = leaf;
anim = pauseParameters.anim;
if (anim != nullptr) {
leaf->Init(anim, leaf->frame, leaf->wrapMode, MD6_WEIGHTGROUP_ALL);
}
leaf->anim = anim;
if (pauseParameters.normalizedStartFrame < 0.0f) {
leaf->frame = pauseParameters.startFrame;
} else {
SetNormalizedFrame(pauseParameters.normalizedStartFrame);
}
return true;
}
void idAnimator_Paused::InternalShutdown(idAnimStack* const stack) {
if (mergeBranch != nullptr) {
GameLib_FreeMD6Branch(stack, mergeBranch);
mergeBranch = nullptr;
}
if (leaf != nullptr) {
GameLib_FreeMD6LeafPause(stack, leaf);
leaf = nullptr;
}
}
bool idAnimator_Paused::InternalIsContributing() const {
return leaf != nullptr && leaf->anim != nullptr;
}
@@ -1,48 +1,60 @@
#pragma once
// Reconstructed C++ declarations from IDA Local Types and PDB/DIA metadata.
// Original PDB header: w:\tech5\engine\gamelib\animstack\animator_paused.h
// Recovered logical types: 2
// Signatures retain Xbox 360 ABI evidence and may still require manual review.
#include "gamelib/animstack/animator_base.h"
class idAnimatorParms_Pause;
// IDA Local Type ordinal 18898; PDB kind: class.
class idAnimator_Paused : public idAnimator_Base
{
class idAnimator_Paused : public idAnimator_Base {
public:
// Recovered virtual interface; IDA vtable ordinal 18899.
virtual ~idAnimator_Paused();
virtual idAnimator_Base::priority_t GetStackPriority();
virtual serializeType_t GetSerializeType();
virtual void SerializeSnapshot(idSerializer *);
virtual void PreBlendSnapshot(idAnimStack *, int, const int, float);
virtual void PreSerializeInit(idAnimStack *, idClip *, idGameTimeManager *);
virtual bool InternalInit(const idAnimatorParms_Base *);
virtual bool InternalPostInit(const idAnimatorParms_Base *);
virtual void InternalShutdown(idAnimStack *);
virtual void InternalPreBlendTree(const idAnimStack *, const int, const int);
virtual void InternalPostBlendTree(const idAnimStack *, const int);
virtual void InternalStart(const idAnimStack *, const int, const idTypesafeNumber<int,enum gameTimeUnique_t>);
virtual void InternalEnd(const idAnimStack *, const int, const idTypesafeNumber<int,enum gameTimeUnique_t>);
virtual void InternalBlend(const idAnimStack *, const int, const float, const idTypesafeNumber<int,enum gameTimeUnique_t>);
virtual bool InternalIsContributing();
virtual const idMD6Branch *InternalGetMergeBranch();
virtual idMD6Branch *InternalGetMergeBranch_2();
virtual void InternalPause(const idAnimStack *, const idTypesafeNumber<int,enum gameTimeUnique_t>);
virtual void InternalUnpause(const idAnimStack *, const idTypesafeNumber<int,enum gameTimeUnique_t>);
virtual const idMD6Branch *InternalGetEndBranch();
virtual idMD6Branch *InternalGetEndBranch_2();
idAnimator_Paused();
~idAnimator_Paused() override;
idMD6LeafPause *leaf;
idMD6Branch *mergeBranch;
const idMD6Anim *anim;
void SetAnim(const idMD6Anim* animation);
const idMD6Anim* GetAnim() const { return anim; }
void SetFrame(float frame);
float GetFrame() const;
void SetNormalizedFrame(float normalizedFrame);
bool InternalInit(const idAnimatorParms_Base& parameters) override;
void InternalShutdown(idAnimStack* stack) override;
bool InternalIsContributing() const override;
const idMD6Branch* InternalGetMergeBranch() const override {
return mergeBranch;
}
idMD6Branch* InternalGetMergeBranch() override { return mergeBranch; }
idMD6LeafPause* leaf;
idMD6Branch* mergeBranch;
const idMD6Anim* anim;
};
// IDA Local Type ordinal 18908; PDB kind: class.
class idAnimatorParms_Pause : public idAnimatorParms_Base
{
class idAnimatorParms_Pause : public idAnimatorParms_Base {
public:
const idMD6Anim *anim;
float startFrame;
float normalizedStartFrame;
idAnimatorParms_Pause(const idMD6Anim* animation, float startFrame_,
float normalizedStartFrame_, idAnimStack* stack, const char* name_,
int blendOp_, int originBlend_, md6WeightGroup_t weightGroup_,
md6WeightGroup_t filterGroup_, float alpha_)
: idAnimatorParms_Base()
, anim(animation)
, startFrame(startFrame_)
, normalizedStartFrame(normalizedStartFrame_) {
animStack = stack;
name = name_;
blendOp = blendOp_;
originBlend = originBlend_;
weightGroup = weightGroup_;
filterGroup = filterGroup_;
alpha = alpha_;
}
const idMD6Anim* anim;
float startFrame;
float normalizedStartFrame;
};
#if defined(_WIN32) && !defined(_WIN64)
static_assert(sizeof(idAnimator_Paused) == 52,
"Recovered idAnimator_Paused ABI changed");
static_assert(sizeof(idAnimatorParms_Pause) == 68,
"Recovered idAnimatorParms_Pause ABI changed");
#endif
@@ -0,0 +1,39 @@
#include "gamelib/animstack/animator_proxy.h"
// These allocator calls are owned by the idAnimStack/md6Allocator recovery.
// Keeping the boundary explicit allows the complete Proxy TU to compile now
// without inventing an allocator layout or a temporary allocation policy.
idMD6Branch* GameLib_AllocMD6Branch(idAnimStack* stack);
void GameLib_FreeMD6Branch(idAnimStack* stack, idMD6Branch* branch);
idAnimator_Proxy::idAnimator_Proxy()
: idAnimator_Base()
, mergeBranch(nullptr) {
}
idAnimator_Proxy::~idAnimator_Proxy() {
mergeBranch = nullptr;
}
void idAnimator_Proxy::SetTree(idMD6Node* const tree) {
if (mergeBranch != nullptr) {
mergeBranch->right = tree;
}
}
bool idAnimator_Proxy::InternalInit(
const idAnimatorParms_Base& parameters) {
mergeBranch = GameLib_AllocMD6Branch(parameters.animStack);
return true;
}
void idAnimator_Proxy::InternalShutdown(idAnimStack* const stack) {
if (stack != nullptr && mergeBranch != nullptr) {
GameLib_FreeMD6Branch(stack, mergeBranch);
mergeBranch = nullptr;
}
}
bool idAnimator_Proxy::InternalIsContributing() const {
return mergeBranch != nullptr && mergeBranch->right != nullptr;
}
@@ -1,37 +1,27 @@
#pragma once
// Reconstructed C++ declarations from IDA Local Types and PDB/DIA metadata.
// Original PDB header: w:\tech5\engine\gamelib\animstack\animator_proxy.h
// Recovered logical types: 1
// Signatures retain Xbox 360 ABI evidence and may still require manual review.
#include "gamelib/animstack/animator_base.h"
// IDA Local Type ordinal 15219; PDB kind: class.
class idAnimator_Proxy : public idAnimator_Base
{
class idAnimator_Proxy : public idAnimator_Base {
public:
// Recovered virtual interface; IDA vtable ordinal 15220.
virtual ~idAnimator_Proxy();
virtual idAnimator_Base::priority_t GetStackPriority();
virtual serializeType_t GetSerializeType();
virtual void SerializeSnapshot(idSerializer *);
virtual void PreBlendSnapshot(idAnimStack *, int, const int, float);
virtual void PreSerializeInit(idAnimStack *, idClip *, idGameTimeManager *);
virtual bool InternalInit(const idAnimatorParms_Base *);
virtual bool InternalPostInit(const idAnimatorParms_Base *);
virtual void InternalShutdown(idAnimStack *);
virtual void InternalPreBlendTree(const idAnimStack *, const int, const int);
virtual void InternalPostBlendTree(const idAnimStack *, const int);
virtual void InternalStart(const idAnimStack *, const int, const idTypesafeNumber<int,enum gameTimeUnique_t>);
virtual void InternalEnd(const idAnimStack *, const int, const idTypesafeNumber<int,enum gameTimeUnique_t>);
virtual void InternalBlend(const idAnimStack *, const int, const float, const idTypesafeNumber<int,enum gameTimeUnique_t>);
virtual bool InternalIsContributing();
virtual const idMD6Branch *InternalGetMergeBranch();
virtual idMD6Branch *InternalGetMergeBranch_2();
virtual void InternalPause(const idAnimStack *, const idTypesafeNumber<int,enum gameTimeUnique_t>);
virtual void InternalUnpause(const idAnimStack *, const idTypesafeNumber<int,enum gameTimeUnique_t>);
virtual const idMD6Branch *InternalGetEndBranch();
virtual idMD6Branch *InternalGetEndBranch_2();
idAnimator_Proxy();
~idAnimator_Proxy() override;
idMD6Branch *mergeBranch;
void SetTree(idMD6Node* tree);
bool InternalInit(const idAnimatorParms_Base& parameters) override;
void InternalShutdown(idAnimStack* stack) override;
bool InternalIsContributing() const override;
const idMD6Branch* InternalGetMergeBranch() const override {
return mergeBranch;
}
idMD6Branch* InternalGetMergeBranch() override {
return mergeBranch;
}
idMD6Branch* mergeBranch;
};
#if defined(_WIN32) && !defined(_WIN64)
static_assert(sizeof(idAnimator_Proxy) == 44,
"Recovered idAnimator_Proxy ABI changed");
#endif
@@ -0,0 +1,131 @@
#pragma once
#include "idlib/bv/bounds.h"
#include "idlib/math/vector.h"
#include <cstdint>
class idAnimStack;
class idClip;
class idGameTimeManager;
class idMD6Anim;
enum gameTimeUnique_t : int;
enum md6WeightGroup_t : int {
MD6_WEIGHTGROUP_ALL = 0,
MD6_WEIGHTGROUP_LEGS = 1,
MD6_WEIGHTGROUP_TORSO = 2,
MD6_WEIGHTGROUP_HEAD = 3,
MD6_WEIGHTGROUP_FACE = 4,
MD6_WEIGHTGROUP_MOUTH = 5,
MD6_WEIGHTGROUP_EYELIDS = 6,
MD6_WEIGHTGROUP_USER0 = 7,
MD6_WEIGHTGROUP_MAX = 8
};
enum serializeType_t : int {
STYPE_GENERIC = 0,
STYPE_AF = 1,
STYPE_ANIMWEB_HANDS = 2,
STYPE_WALK_IK = 3,
STYPE_TORSO_TRACKER = 4,
STYPE_PAIN = 5,
STYPE_JOINTMOD = 6,
STYPE_REACH_IK = 7,
STYPE_MAX = 8
};
class idMD6Node {
public:
enum nodeType_t : int {
NODE_BRANCH = 0,
NODE_LEAF_PAUSE = 1,
NODE_LEAF_PLAY = 2,
NODE_BLEND_BRANCH = 3,
NODE_BLENDA_BRANCH = 4,
NODE_FUSION_BRANCH = 5,
NODE_BEST_LEAF = 6,
NODE_TAG_FILTER = 7,
NODE_NONE = 0xFF
};
std::uint8_t type;
};
class idMD6Branch : public idMD6Node {
public:
enum blendType_t : int {
BLEND_LINEAR = 0,
BLEND_EASEIN = 1,
BLEND_EASEOUT = 2,
BLEND_EASEIN_EASEOUT = 3,
BLEND_TYPE_COUNT = 4
};
idMD6Node* left;
idMD6Node* right;
int leftTimeOverride;
int rightTimeOverride;
std::uint8_t filterGroup;
std::uint8_t op;
std::uint8_t originBlend;
float currentAlpha;
float targetAlpha;
float alphaRate;
blendType_t blendType;
};
// The leaf layout is materialized only to the extent proven by the recovered
// md6animtree and idAnimator_Paused bodies. The two list records remain opaque
// until the joint-mod translation unit is activated.
struct idMD6OpaqueList {
void* list;
int num;
int size;
std::int16_t granularity;
std::uint8_t memTag;
std::uint8_t listStatic;
};
class idMD6LeafPause : public idMD6Node {
public:
std::uint8_t nodePadding[3];
const idMD6Anim* anim;
std::uint8_t weightGroup;
std::uint8_t wrapMode;
std::uint8_t initCounter;
std::uint8_t pad;
int currentDeferred;
idMD6OpaqueList animMods[2];
std::int16_t flags;
std::uint8_t framePadding[2];
float frame;
idBounds bounds;
void Init(const idMD6Anim* animation, float animationFrame,
std::uint8_t animationWrapMode, md6WeightGroup_t animationWeightGroup) {
frame = animationFrame;
anim = animation;
flags = 0;
weightGroup = static_cast<std::uint8_t>(animationWeightGroup);
wrapMode = animationWrapMode;
}
};
struct idGameTimeManagerPtr {
idGameTimeManager* gameTimeManager;
};
#if defined(_WIN32) && !defined(_WIN64)
static_assert(sizeof(idMD6Node) == 1,
"Recovered idMD6Node ABI changed");
static_assert(sizeof(idMD6Branch) == 40,
"Recovered idMD6Branch ABI changed");
static_assert(sizeof(idMD6OpaqueList) == 16,
"Recovered MD6 opaque list ABI changed");
static_assert(sizeof(idMD6LeafPause) == 80,
"Recovered idMD6LeafPause ABI changed");
static_assert(sizeof(idGameTimeManagerPtr) == 4,
"Recovered idGameTimeManagerPtr ABI changed");
#endif
@@ -1,13 +1,61 @@
#pragma once
// Reconstructed C++ declarations from IDA Local Types and PDB/DIA metadata.
// Original PDB header: w:\tech5\engine\gamelib\animstack\animweb\animwebpath.h
// Recovered logical types: 1
// Signatures retain Xbox 360 ABI evidence and may still require manual review.
#include "idlib/index.h"
#include "idlib/text/str.h"
#include <cstdint>
#include <utility>
// IDA Local Type ordinal 16590; PDB kind: class.
class idAnimWebPath : public idStr
{
// idAnimWebPath has no storage beyond its recovered idStr base.
class idAnimWebPath : public idStr {
public:
using idStr::idStr;
using idStr::operator=;
};
// The owning idDeclAnimWeb declaration is not compile-locked yet. This tag
// retains the recovered two-byte node-index representation without importing
// that malformed generated declaration into GameLib's active boundary.
enum class idAnimWebInvalidNodeIndex_t : int {
invalid = -1
};
using idAnimWebNodeIndex = idIndex<short, idAnimWebInvalidNodeIndex_t>;
struct idAnimWebRoute {
idAnimWebNodeIndex path[32];
int num;
int cost;
// Materialized in the authoritative animwebpath.h dump.
void Invert() {
for (int index = 0; index < num / 2; ++index) {
std::swap(path[index], path[num - index - 1]);
}
}
// Materialized in the authoritative animwebpath.h dump. A shared prefix
// node is consumed so concatenated routes do not duplicate their join.
void AppendPath(const idAnimWebRoute& other) {
int first = 0;
if (num > 0) {
while (first < other.num
&& path[num - 1].Get() == other.path[first].Get()) {
++first;
}
}
while (first < other.num && num < 32) {
path[num++] = other.path[first++];
}
cost += other.cost;
}
};
#if INTPTR_MAX == INT32_MAX
static_assert(sizeof(idAnimWebPath) == 32,
"Recovered idAnimWebPath ABI changed");
static_assert(sizeof(idAnimWebNodeIndex) == 2,
"Recovered AnimWeb node index ABI changed");
static_assert(sizeof(idAnimWebRoute) == 72,
"Recovered idAnimWebRoute ABI changed");
#endif
@@ -0,0 +1,100 @@
#include "gamelib/animstack/animweb/animwebutils.h"
#include <algorithm>
#include <cmath>
float LerpToWithScale(const float current, const float destination,
const float scale) {
const float delta = destination - current;
return delta <= -0.000001f || delta >= 0.000001f
? current + delta * scale
: destination;
}
float LerpToWithRate(const float current, const float destination,
const float absoluteRate) {
if (current < destination) {
const float next = current + absoluteRate;
if (next < current) {
return current;
}
return next > destination ? destination : next;
}
if (current > destination) {
const float next = current - absoluteRate;
if (next > current) {
return current;
}
return next < destination ? destination : next;
}
return current;
}
namespace {
void SetSync8(const float angle, const bool reverse, float& index1,
float& index2, float& blend) {
constexpr float inverse45 = 1.0f / 45.0f;
const int sector = static_cast<int>(angle * inverse45);
const float fraction = (angle - static_cast<float>(sector) * 45.0f)
* inverse45;
const int first = reverse ? 7 - sector : sector;
index1 = static_cast<float>(first);
index2 = static_cast<float>((first + 1) & 7);
blend = reverse ? 1.0f - fraction : fraction;
}
} // namespace
bool UpdateWalkBlend(const idVec3& velocity, const idMat3& axis,
const float lerpScale, float& blendBack, float& blendRight,
float& blendAngle, float& sync8Index1, float& sync8Index2,
float& sync8BlendAngle) {
const float speed = velocity.Length();
if (speed <= 0.1f) {
return false;
}
const float inverseSpeed = 1.0f / speed;
const float forward = (std::max)(-1.0f, (std::min)(1.0f,
velocity.Dot(axis[0]) * inverseSpeed));
const float right = (std::max)(-1.0f, (std::min)(1.0f,
velocity.Dot(axis[1]) * inverseSpeed));
constexpr float radiansToDegrees = 57.29577951308232f;
const float angle = std::acos(forward) * radiansToDegrees;
const float forwardAmount = forward < 0.0f
? (angle - 90.0f) / 90.0f
: 1.0f - angle / 90.0f;
blendBack = LerpToWithScale(blendBack, forward < 0.0f ? 1.0f : 0.0f,
lerpScale);
blendRight = LerpToWithScale(blendRight, right < 0.0f ? 1.0f : 0.0f,
lerpScale);
blendAngle = LerpToWithScale(blendAngle, 1.0f - forwardAmount,
lerpScale);
SetSync8(angle, right >= 0.0f, sync8Index1, sync8Index2,
sync8BlendAngle);
return true;
}
bool UpdateWalkBlendFromAngle(const float angle, const float lerpScale,
float& blendBack, float& blendRight, float& blendAngle,
float& sync8Index1, float& sync8Index2, float& sync8BlendAngle) {
const bool forward = angle > -90.0f && angle < 90.0f;
const bool positive = angle > 0.0f && angle < 180.0f;
const float absoluteAngle = std::fabs(angle);
const float forwardAmount = forward
? 1.0f - absoluteAngle / 90.0f
: (absoluteAngle - 90.0f) / 90.0f;
blendBack = LerpToWithScale(blendBack, forward ? 0.0f : 1.0f,
lerpScale);
blendRight = LerpToWithScale(blendRight, positive ? 0.0f : 1.0f,
lerpScale);
blendAngle = LerpToWithScale(blendAngle, 1.0f - forwardAmount,
lerpScale);
SetSync8(absoluteAngle, positive, sync8Index1, sync8Index2,
sync8BlendAngle);
return true;
}
@@ -0,0 +1,14 @@
#pragma once
#include "idlib/math/vector.h"
float LerpToWithScale(float current, float destination, float scale);
float LerpToWithRate(float current, float destination, float absoluteRate);
bool UpdateWalkBlend(const idVec3& velocity, const idMat3& axis,
float lerpScale, float& blendBack, float& blendRight, float& blendAngle,
float& sync8Index1, float& sync8Index2, float& sync8BlendAngle);
bool UpdateWalkBlendFromAngle(float angle, float lerpScale,
float& blendBack, float& blendRight, float& blendAngle,
float& sync8Index1, float& sync8Index2, float& sync8BlendAngle);
@@ -1,14 +1,71 @@
#pragma once
// Reconstructed C++ declarations from IDA Local Types and PDB/DIA metadata.
// Original PDB header: w:\tech5\engine\gamelib\animstack\animweb\dijkstra.h
// Recovered logical types: 1
// Signatures retain Xbox 360 ABI evidence and may still require manual review.
#include "idlib/index.h"
#include <cstdint>
// IDA Local Type ordinal 23485; PDB kind: class.
class idDijkstra<idAnimator_AnimWeb,idDeclAnimWeb::idNodeCache,idIndex<short,enum idDeclAnimWeb::invalidNodeIndex_t>,idDeclAnimWeb::idEdgeCache,idAnimWebRoute>
{
// Recovered idDijkstra storage and interface. The materialized Xbox binary is
// the AnimWeb specialization, while keeping the original template boundary
// lets the algorithm be compiled and tested before idDeclAnimWeb is active.
template<typename nodeHolderType, typename nodeCacheType,
typename nodeIndexType, typename edgeCacheType, typename pathType>
class idDijkstra {
public:
int lastStartNode;
struct djScratch_t {
short prevIndex;
std::uint16_t costAndVisited;
int Cost() const {
return costAndVisited & 0x7FFFu;
}
bool Visited() const {
return (costAndVisited & 0x8000u) != 0;
}
void SetCost(const int cost) {
costAndVisited = static_cast<std::uint16_t>(
(costAndVisited & 0x8000u) | (cost & 0x7FFF));
}
void SetVisited(const bool visited) {
if (visited) {
costAndVisited |= 0x8000u;
} else {
costAndVisited &= 0x7FFFu;
}
}
};
idDijkstra()
: lastStartNode(-1) {
}
bool TracePath(
const nodeHolderType& nodeHolder,
nodeIndexType startNode,
nodeIndexType destNode,
const djScratch_t* scratchBuff,
pathType& path);
bool FindShortestPaths(
const nodeHolderType& nodeHolder,
nodeIndexType startNode,
const nodeIndexType* destNodes,
int numDestNodes,
const edgeCacheType* edges,
djScratch_t* scratchBuff,
int skipFlags,
int requiredFlags);
int lastStartNode;
};
static_assert(sizeof(typename idDijkstra<int, int,
idIndex<short, idRecoveredInvalidIndex>, int, int>::djScratch_t) == 4,
"Recovered idDijkstra scratch ABI changed");
static_assert(sizeof(idDijkstra<int, int,
idIndex<short, idRecoveredInvalidIndex>, int, int>) == 4,
"Recovered idDijkstra ABI changed");
#include "gamelib/animstack/animweb/dijkstra_impl.h"
@@ -0,0 +1,158 @@
#pragma once
#include <algorithm>
#include <cstring>
#include <queue>
#include <utility>
#include <vector>
template<typename nodeHolderType, typename nodeCacheType,
typename nodeIndexType, typename edgeCacheType, typename pathType>
bool idDijkstra<nodeHolderType, nodeCacheType, nodeIndexType,
edgeCacheType, pathType>::TracePath(
const nodeHolderType& nodeHolder,
const nodeIndexType startNode,
const nodeIndexType destNode,
const djScratch_t* scratchBuff,
pathType& path) {
(void)nodeHolder;
const int start = static_cast<int>(startNode.Get());
const int destination = static_cast<int>(destNode.Get());
if (lastStartNode != start) {
return false;
}
path.num = 0;
path.cost = 0x7FFFFFFF;
if (destination == start) {
return false;
}
path.path[path.num++] = nodeIndexType(
static_cast<short>(destination));
const djScratch_t* scratch = &scratchBuff[destination];
path.cost = scratch->Cost();
while (path.num < 32) {
const short previous = scratch->prevIndex;
if (previous < 0) {
path.cost = 0x7FFFFFFF;
path.num = 0;
return false;
}
path.path[path.num++] = nodeIndexType(previous);
scratch = &scratchBuff[previous];
if (previous == start) {
path.Invert();
return true;
}
}
// The recovered implementation returns the first 32 nodes when a route
// exceeds the fixed route buffer, then reverses that bounded prefix.
path.Invert();
return true;
}
template<typename nodeHolderType, typename nodeCacheType,
typename nodeIndexType, typename edgeCacheType, typename pathType>
bool idDijkstra<nodeHolderType, nodeCacheType, nodeIndexType,
edgeCacheType, pathType>::FindShortestPaths(
const nodeHolderType& nodeHolder,
const nodeIndexType startNode,
const nodeIndexType* destNodes,
const int numDestNodes,
const edgeCacheType* edges,
djScratch_t* scratchBuff,
const int skipFlags,
const int requiredFlags) {
const int nodeCount = nodeHolder.decl->nodes.num;
std::memset(scratchBuff, 0xFF,
sizeof(djScratch_t) * static_cast<std::size_t>(nodeCount));
for (int listIndex = 0;
listIndex < nodeHolder.pathableSubWebNodeLists.num;
++listIndex) {
const auto* const pathable =
nodeHolder.pathableSubWebNodeLists.list[listIndex];
for (int nodeIndex = 0; nodeIndex < pathable->num; ++nodeIndex) {
const int value = static_cast<int>(pathable->list[nodeIndex].Get());
scratchBuff[value].SetVisited(false);
}
}
const int start = static_cast<int>(startNode.Get());
scratchBuff[start].SetVisited(false);
scratchBuff[start].SetCost(0);
scratchBuff[start].prevIndex = -1;
lastStartNode = -1;
using heapEntry_t = std::pair<int, int>;
std::priority_queue<heapEntry_t, std::vector<heapEntry_t>,
std::greater<heapEntry_t>> heap;
heap.push(heapEntry_t(0, start));
int destinationsFound = 0;
int processedNodes = 0;
while (!heap.empty() && processedNodes < nodeCount) {
const int node = heap.top().second;
heap.pop();
djScratch_t& nodeScratch = scratchBuff[node];
if (nodeScratch.Visited()) {
continue;
}
for (int destinationIndex = 0;
destinationIndex < numDestNodes;
++destinationIndex) {
if (destNodes[destinationIndex].Get() == node) {
++destinationsFound;
if (destinationsFound == numDestNodes) {
lastStartNode = start;
return true;
}
break;
}
}
const nodeCacheType& nodeCache = nodeHolder.decl->nodeCache.list[node];
const int nodeCost = nodeScratch.Cost();
nodeScratch.SetVisited(true);
if ((nodeCache.flags & skipFlags) == 0
&& (nodeCache.flags & requiredFlags) == requiredFlags) {
for (int localEdge = 0; localEdge < nodeCache.numEdges;
++localEdge) {
const int edgeIndex = nodeHolder.decl->edgeIndexCache[
nodeCache.edgeIndexOffset + localEdge];
const edgeCacheType& edge = edges[edgeIndex];
const int destination = static_cast<int>(
edge.destNodeIndex.Get());
djScratch_t& destinationScratch = scratchBuff[destination];
if (destinationScratch.Visited()) {
continue;
}
const float scaledCost = static_cast<float>(
nodeHolder.InternalGetEdgeCost(
nodeIndexType(static_cast<short>(node)),
{ static_cast<short>(edgeIndex) }))
* (static_cast<float>(edge.weightScale) * 0.0625f);
const int newCost = nodeCost + static_cast<int>(scaledCost);
if (destinationScratch.Cost() > newCost) {
destinationScratch.prevIndex = static_cast<short>(node);
destinationScratch.SetCost(newCost);
heap.push(heapEntry_t(newCost, destination));
}
}
}
++processedNodes;
}
lastStartNode = start;
return true;
}
@@ -0,0 +1,129 @@
#include "gamelib/animstack/coneconstraint.h"
#include <cmath>
namespace {
idQuat Multiply(const idQuat& lhs, const idQuat& rhs) {
return idQuat(
lhs.w * rhs.x + lhs.x * rhs.w + lhs.y * rhs.z - lhs.z * rhs.y,
lhs.w * rhs.y + lhs.y * rhs.w + lhs.z * rhs.x - lhs.x * rhs.z,
lhs.w * rhs.z + lhs.z * rhs.w + lhs.x * rhs.y - lhs.y * rhs.x,
lhs.w * rhs.w - lhs.x * rhs.x - lhs.y * rhs.y - lhs.z * rhs.z);
}
idVec3 ToForward(const idQuat& quaternion) {
return idVec3(
1.0f - 2.0f * (quaternion.y * quaternion.y
+ quaternion.z * quaternion.z),
2.0f * (quaternion.x * quaternion.y
- quaternion.w * quaternion.z),
2.0f * (quaternion.w * quaternion.y
+ quaternion.x * quaternion.z));
}
idVec3 ConstrainDirection(
const idVec3& center,
const idVec3& direction,
const float limitAngleDot,
const float halfLimitAngleCosine,
const float halfLimitAngleSine) {
const float dot = center.Dot(direction);
if (dot >= limitAngleDot) {
return direction;
}
idVec3 tangent = direction - center * dot;
if (tangent.NormalizeFast() == 0.0f) {
return center;
}
const float sine = 2.0f * halfLimitAngleSine
* halfLimitAngleCosine;
return center * limitAngleDot + tangent * sine;
}
} // namespace
idConeConstraint_Vec3::idConeConstraint_Vec3(
const idConeConstraint_Vec3& other) = default;
idConeConstraint_Quat::idConeConstraint_Quat(
const idConeConstraint_Quat& other) = default;
idConeConstraint_Vec3::idConeConstraint_Vec3(
const idVec3& center_,
const radians_t maxAngle_)
: current(center_)
, center(center_)
, limitAngleDot(std::cos(maxAngle_.value))
, halfLimitAngleCosine(std::cos(maxAngle_.value * 0.5f))
, halfLimitAngleSine(std::sin(maxAngle_.value * 0.5f)) {
}
void idConeConstraint_Vec3::RotateTo(
const idVec3& dir,
const float lerpRate) {
const idVec3 target = ConstrainDirection(
center,
dir,
limitAngleDot,
halfLimitAngleCosine,
halfLimitAngleSine);
current = current + (target - current) * lerpRate;
current.NormalizeFast();
}
idConeConstraint_Quat::idConeConstraint_Quat(
const idQuat& center_,
const radians_t maxAngle_)
: current(center_)
, center(center_)
, limitAngleDot(std::cos(maxAngle_.value))
, halfLimitAngleCosine(std::cos(maxAngle_.value * 0.5f))
, halfLimitAngleSine(std::sin(maxAngle_.value * 0.5f)) {
}
void idConeConstraint_Quat::RotateTo(
const idVec3& dir,
const float lerpRate) {
const idVec3 forward = ToForward(current);
const float forwardDot = dir.Dot(forward);
if (forwardDot > -1.0f && forwardDot < 1.0f) {
idVec3 blendedForward = forward
+ (dir - forward) * (lerpRate * 0.5f);
blendedForward.NormalizeFast();
const float rotationDot = blendedForward.Dot(forward);
const float rotationSine = rotationDot < 1.0f
? std::sqrt(1.0f - rotationDot * rotationDot)
: 0.0f;
idVec3 rotationAxis = blendedForward.Cross(forward);
rotationAxis.NormalizeFast();
const idQuat rotation(
rotationAxis.x * rotationSine,
rotationAxis.y * rotationSine,
rotationAxis.z * rotationSine,
rotationDot);
current = Multiply(current, rotation);
current.Normalize();
}
const idVec3 centerForward = ToForward(center);
const idVec3 currentForward = ToForward(current);
if (centerForward.Dot(currentForward) < limitAngleDot) {
idVec3 rotationAxis = currentForward.Cross(centerForward);
rotationAxis.NormalizeFast();
const idQuat rotation(
rotationAxis.x * halfLimitAngleSine,
rotationAxis.y * halfLimitAngleSine,
rotationAxis.z * halfLimitAngleSine,
halfLimitAngleCosine);
current = Multiply(center, rotation);
current.Normalize();
}
}
+45 -195
View File
@@ -1,207 +1,57 @@
#pragma once
// Reconstructed C++ declarations from IDA Local Types and PDB/DIA metadata.
// Original PDB header: w:\tech5\engine\gamelib\animstack\coneconstraint.h
// Recovered logical types: 4
// Signatures retain Xbox 360 ABI evidence and may still require manual review.
#include "idlib/math/quat.h"
#include "idlib/math/radians.h"
// IDA Local Type ordinal 16484; PDB kind: class.
class idConeConstraint_Quat
{
// Reconstructed from the recovered coneconstraint.h declarations and the
// six authoritative functions in animstack/coneconstraint.cpp.
class idConeConstraint_Quat {
public:
idQuat current;
idQuat center;
float limitAngleDot;
float halfLimitAngleCosine;
float halfLimitAngleSine;
idConeConstraint_Quat(const idConeConstraint_Quat& other);
idConeConstraint_Quat(const idQuat& center_, radians_t maxAngle_);
void RotateTo(const idVec3& dir, float lerpRate);
idQuat current;
idQuat center;
float limitAngleDot;
float halfLimitAngleCosine;
float halfLimitAngleSine;
};
// IDA Local Type ordinal 19154; PDB kind: class.
class idConeConstraint_Vec3
{
class idConeConstraint_Vec3 {
public:
idVec3 current;
idVec3 center;
float limitAngleDot;
float halfLimitAngleCosine;
float halfLimitAngleSine;
idConeConstraint_Vec3(const idConeConstraint_Vec3& other);
idConeConstraint_Vec3(const idVec3& center_, radians_t maxAngle_);
void RotateTo(const idVec3& dir, float lerpRate);
idVec3 current;
idVec3 center;
float limitAngleDot;
float halfLimitAngleCosine;
float halfLimitAngleSine;
};
// IDA Local Type ordinal 19160; PDB kind: class.
class idTest_ConeConstraint : public idEntity
{
// The matrix form has declaration/layout evidence but no materialized methods
// in this translation unit.
class idConeConstraint_Mat3 {
public:
// Recovered virtual interface; IDA vtable ordinal 19161.
virtual idTypeInfo *GetType();
virtual ~idTest_ConeConstraint();
virtual idEventArg *CallEvent(idEventArg *result, const idEventDef *, const idEventArg *);
virtual bool RespondsTo(const idEventDef *);
virtual idEventArg *InternalCallEvent(idEventArg *result, const idEventDef *, const idEventArg *);
virtual bool InternalRespondsTo(const idEventDef *);
virtual void PostSpawn();
virtual void Remove();
virtual void DeleteSubEntities();
virtual bool Draw(idPlayer *);
virtual void JobSync();
virtual void Think();
virtual void PauseThink();
virtual bool ShouldEnterDormancy();
virtual bool ShouldLeaveDormancy();
virtual void DormantBegin();
virtual void DormantEnd(const int);
virtual idRenderModelInfo *GetRenderModelInfo();
virtual const idRenderModelInfo *GetRenderModelInfo_2();
virtual void GetScale(idVec3 *);
virtual void SetScale(const idVec3 *);
virtual void SetModelByName(const char *);
virtual void SetModel(idRenderModel *);
virtual const idMaterial *GetCustomMaterial();
virtual void SetColor(const idVec4 *);
virtual void SetColor_2(const idColor *);
virtual void SetColor_3(const idVec3 *);
virtual void SetColor_4(float, float, float);
virtual void SetColor_5(float, float, float, float);
virtual void GetColor(idVec4 *);
virtual void GetColor_2(idColor *);
virtual void GetColor_3(idVec3 *);
virtual void Hide(bool);
virtual void Hide_2();
virtual void Show();
virtual void GetModelTransform(idVec3 *, idMat3 *);
virtual void GetSoundTransform(idVec3 *, idMat3 *);
virtual void UpdateModelTransform();
virtual void UpdateFX();
virtual void ProjectOverlay(const idVec3 *, const idVec3 *, float, const char *);
virtual idPresentable *AllocPresentable(idRenderModel *);
virtual const idComponentTimeLine *GetComponentTimeLine();
virtual idComponentTimeLine *GetComponentTimeLine_2();
virtual bool UpdateAnimationControllers();
virtual void UpdateAttachments();
virtual const idAnimStack *GetAnimStack();
virtual idAnimStack *GetAnimStack_2();
virtual idIndex<short,enum invalidJointIndex_t> *GetJointIndexFromTrace(idIndex<short,enum invalidJointIndex_t> *result, trace_t);
virtual awPathResult_t ChangeAnimWebState(const char *, const char *);
virtual awPathResult_t ChangeAnimWebState_2(const char *);
virtual awPathResult_t ForceAnimWebState(const char *);
virtual awPathResult_t ChangeAnimWebStateVia(const char *, const char *, const char *, const char *);
virtual awPathResult_t ChangeAnimWebStateVia_2(const char *, const char *);
virtual idAnimWebCmdCtx *GetAnimWebCmdCtx();
virtual const idAnimWebCmdCtx *GetAnimWebCmdCtx_2();
virtual const idAnimator_AF *GetAF();
virtual idAnimator_AF *GetAF_2();
virtual void PreBind();
virtual void PostBind();
virtual void PreUnbind();
virtual void PostUnbind();
virtual const splineLocation_t *GetSplineLocation();
virtual void SetAxis(const idMat3 *);
virtual bool CanDisablePhysics(const idEntity *);
virtual collide_t Collide(const int, trace_t *, const idVec3 *);
virtual collide_t Contact(const int, contactInfo_t *);
virtual void ApplyImpulse(const int, const int, const idVec3 *, const idVec3 *);
virtual void ApplyImpulseFromEntity(const idEntity *, const int, const idVec3 *, const idVec3 *);
virtual void ApplyForce(const int, const int, const idVec3 *, const idVec3 *);
virtual bool Crush(const int);
virtual void ApplyDamage(const int, const int, const idDeclDamage *);
virtual void ActivatePhysics(const int);
virtual void DeactivatePhysics(const int);
virtual void ApplyWaterEffects(const int, const int);
virtual void ApplyWaterSplashEffects(const int, const int, surfTypes_t, idPhysicsCallbacks::splashState_t);
virtual bool TakesDamage();
virtual void DamageFeedback(idEntity *, idEntity *, const idDeclDamage *, float *);
virtual void KilledNotification(const idEntity *, const idEntity *, const idDeclDamage *, const float);
virtual float Damage(idEntity *, idEntity *, const idDeclDamage *, const float, const idVec3 *, trace_t *);
virtual bool CalcDamageImpulse(const idEntity *, const idEntity *, const idDeclDamage *, const float, const idVec3 *, const trace_t *, idVec3 *, idVec3 *);
virtual bool IsTargetLockable(const idDeclAmmo *);
virtual void AddProjectileLock();
virtual void RemoveProjectileLock();
virtual const idScriptObject *GetScriptObject();
virtual idScriptObject *GetScriptObject_2();
virtual bool ShouldConstructScriptObjectAtSpawn();
virtual idThread *GetStateThread();
virtual int AddThread(const idHandle<int,enum invalidThreadHandle_t,0>);
virtual void RemoveThread(const idHandle<int,enum invalidThreadHandle_t,0>);
virtual idHandle<int,enum invalidThreadHandle_t,0> *GetThread(idHandle<int,enum invalidThreadHandle_t,0> *result, const int);
virtual int NumThreads();
virtual int MaxThreads();
virtual void ExecuteThread(idThread *);
virtual void ResetFSMWaitThreadIfPossible(idThread *);
virtual bool HandleGuiEvent(const sysEvent_t *);
virtual void ActivateTargets(idEntity *);
virtual bool GetRcCarCanTarget();
virtual const idBaseHealth *GetHealthComponent();
virtual idBaseHealth *GetHealthComponent_2();
virtual const idSmartLootComponent *GetSmartLootComponent();
virtual idSmartLootComponent *GetSmartLootComponent_2();
virtual void Teleport(const idVec3 *, const idAngles *);
virtual bool IsPusher();
virtual const idList<idEntityPtr<idEntity>,5> *GetTriggerTouchList();
virtual idList<idEntityPtr<idEntity>,5> *GetTriggerTouchList_2();
virtual void TestFunctionality();
virtual float GetUsableDistance();
virtual float GetCrosshairIconDistance();
virtual usableState_t GetUsableState(const idEntity *, const idFocusTrace *);
virtual bool ModifyCrosshairInfo(const idEntity *, const idFocusTrace *, const usableState_t, idCrosshairInfo *);
virtual bool IsCrosshairDisabled(const idEntity *, const idFocusTrace *, const usableState_t);
virtual bool IsCrosshairSubdued(const idEntity *, const idFocusTrace *, const usableState_t);
virtual bool IsEverUsable(const idEntity *);
virtual bool IsCurrentlyUsable(const idEntity *);
virtual bool Use(idEntity *, const usableState_t);
virtual void Dropped(idEntity *, const idDeclInventory *);
virtual const idInventoryCollection *GetInventory();
virtual idInventoryCollection *GetInventory_2();
virtual void InventoryAdded(idInventoryItem *, int);
virtual void InventoryRemoved(idInventoryItem *);
virtual const idAttachmentCollection *GetAttachments();
virtual idAttachmentCollection *GetAttachments_2();
virtual void EnableAIEventResponse(const idAIEvent::aiEventClass_t);
virtual void DisableAIEventResponse(const idAIEvent::aiEventClass_t);
virtual bool CanReceiveAIEvents(const int);
virtual bool RespondsToAIEvent(const idAIEvent *);
virtual void OnAIEvent(const idAIEvent *);
virtual bool IsDead();
virtual bool IsDying();
virtual idFaction *GetFaction();
virtual const idFaction *GetFaction_2();
virtual idEntityAuditor *GetAuditor();
virtual void GetVisibilityPoint(const visPoint_t, idVec3 *);
virtual void GetAimPoint(const aimPoint_t, idVec3 *);
virtual void GetEyePos(idVec3 *);
virtual bool IsVisible();
virtual idDynamicCoverMgr *GetDynamicCoverMgr();
virtual const idDynamicCoverMgr *GetDynamicCoverMgr_2();
virtual const idAAS2 *GetAAS();
virtual void GetViewStateFOV(idVec3 *, unsigned __int8 *, unsigned __int8 *);
virtual void GetViewStateFOV_2(idVec3 *, unsigned __int8 *, unsigned __int8 *);
virtual int GetNumRepairBotTetherPoints();
virtual bool GetRepairBotTetherPoint(const int, const int, idVec3 *);
virtual idEntityInterface *CreateEntityInterface(idGame *);
virtual void ShowEditingDialog();
virtual void UpdateEditingDialog();
virtual void UpdateModifiedProperties();
virtual inputSettings_t *GetInputSettings(inputSettings_t *result, idPlayer *);
virtual bool EvaluateControls(usercmd_t *, usercmd_t *);
virtual void CheckForErrors(idList<idStr,5> *);
virtual void DebugDrawEntity(const idColor *, int);
virtual void ClientThink();
virtual void Serialize(idSerializer *);
virtual void PostSerializeRead(bool);
virtual void OnActivate(idEntity *);
virtual void OnMakeActivatable(const bool);
virtual void OnNotifyProgressionOwner();
int numSegments;
idSegment **segments;
idMat3 current;
idMat3 center;
float limitAngleDot;
float halfLimitAngleCosine;
float halfLimitAngleSine;
};
// IDA Local Type ordinal 21649; PDB kind: class.
class idConeConstraint_Mat3
{
public:
idMat3 current;
idMat3 center;
float limitAngleDot;
float halfLimitAngleCosine;
float halfLimitAngleSine;
};
// The fourth recovered logical type is a test entity derived from idEntity.
// Its full base-class boundary belongs to the later game-entity recovery, so
// retain the real owner name without inventing a substitute base class here.
class idTest_ConeConstraint;
static_assert(sizeof(idConeConstraint_Quat) == 44,
"Recovered idConeConstraint_Quat ABI changed");
static_assert(sizeof(idConeConstraint_Vec3) == 36,
"Recovered idConeConstraint_Vec3 ABI changed");
static_assert(sizeof(idConeConstraint_Mat3) == 84,
"Recovered idConeConstraint_Mat3 ABI changed");