Merge branch 'master' of ssh+git://git.axiodl.com:6431/AxioDL/urde

This commit is contained in:
Phillip Stephens 2020-05-13 06:20:52 -07:00
commit 9c217c9115
Signed by: Antidote
GPG Key ID: F8BEE4C83DACA60D
19 changed files with 752 additions and 548 deletions

View File

@ -106,24 +106,27 @@ void CAnimSourceReaderBase::UpdatePOIStates() {
const std::vector<CSoundPOINode>& soundNodes = x4_sourceInfo->GetSoundPOIStream();
while (x14_passedBoolCount < boolNodes.size() && boolNodes[x14_passedBoolCount].GetTime() <= xc_curTime) {
auto& node = boolNodes[x14_passedBoolCount];
if (node.GetIndex() >= 0)
const auto& node = boolNodes[x14_passedBoolCount];
if (node.GetIndex() >= 0) {
x24_boolStates[node.GetIndex()].second = node.GetValue();
}
++x14_passedBoolCount;
}
while (x18_passedIntCount < int32Nodes.size() && int32Nodes[x18_passedIntCount].GetTime() <= xc_curTime) {
auto& node = int32Nodes[x18_passedIntCount];
if (node.GetIndex() >= 0)
const auto& node = int32Nodes[x18_passedIntCount];
if (node.GetIndex() >= 0) {
x34_int32States[node.GetIndex()].second = node.GetValue();
}
++x18_passedIntCount;
}
while (x1c_passedParticleCount < particleNodes.size() &&
particleNodes[x1c_passedParticleCount].GetTime() <= xc_curTime) {
auto& node = particleNodes[x1c_passedParticleCount];
if (node.GetIndex() >= 0)
const auto& node = particleNodes[x1c_passedParticleCount];
if (node.GetIndex() >= 0) {
x44_particleStates[node.GetIndex()].second = node.GetParticleData().GetParentedMode();
}
++x1c_passedParticleCount;
}

View File

@ -25,10 +25,11 @@ void CAnimTreeTweenBase::VGetSegStatementSet(const CSegIdList& list, CSegStateme
if (w >= 1.f) {
x18_b->VGetSegStatementSet(list, setOut);
} else if (sStack > 3) {
auto& n = w > 0.5f ? x18_b : x14_a;
const auto& n = w > 0.5f ? x18_b : x14_a;
auto ptr = n->GetBestUnblendedChild();
if (!ptr)
if (!ptr) {
ptr = n;
}
ptr->VGetSegStatementSet(list, setOut);
} else {
CSegStatementSet setA, setB;
@ -61,7 +62,7 @@ void CAnimTreeTweenBase::VGetSegStatementSet(const CSegIdList& list, CSegStateme
if (w >= 1.f) {
x18_b->VGetSegStatementSet(list, setOut, time);
} else if (sStack > 3) {
auto& n = w > 0.5f ? x18_b : x14_a;
const auto& n = w > 0.5f ? x18_b : x14_a;
n->GetBestUnblendedChild()->VGetSegStatementSet(list, setOut, time);
} else {
CSegStatementSet setA, setB;

View File

@ -27,13 +27,14 @@ void CMetaAnimRandom::GetUniquePrimitives(std::set<CPrimitive>& primsOut) const
std::shared_ptr<CAnimTreeNode> CMetaAnimRandom::VGetAnimationTree(const CAnimSysContext& animSys,
const CMetaAnimTreeBuildOrders& orders) const {
u32 r = animSys.x8_random->Range(1, 100);
const u32 r = animSys.x8_random->Range(1, 100);
const std::pair<std::shared_ptr<IMetaAnim>, u32>* useRd = nullptr;
for (auto& rd : x4_randomData) {
for (const auto& rd : x4_randomData) {
useRd = &rd;
if (r <= rd.second)
if (r <= rd.second) {
break;
}
}
return useRd->first->GetAnimationTree(animSys, orders);
}

View File

@ -205,38 +205,41 @@ void CParticleDatabase::Update(float dt, const CPoseAsTransforms& pose, const CC
}
void CParticleDatabase::RenderParticleGenMap(const std::map<std::string, std::unique_ptr<CParticleGenInfo>>& map) {
for (auto& e : map) {
for (const auto& e : map) {
e.second->Render();
}
}
void CParticleDatabase::RenderParticleGenMapMasked(const std::map<std::string, std::unique_ptr<CParticleGenInfo>>& map,
int mask, int target) {
for (auto& e : map) {
if ((e.second->GetFlags() & mask) == target)
for (const auto& e : map) {
if ((e.second->GetFlags() & mask) == target) {
e.second->Render();
}
}
}
void CParticleDatabase::AddToRendererClippedParticleGenMap(
const std::map<std::string, std::unique_ptr<CParticleGenInfo>>& map, const zeus::CFrustum& frustum) {
for (auto& e : map) {
auto bounds = e.second->GetBounds();
if (bounds && frustum.aabbFrustumTest(*bounds))
for (const auto& e : map) {
const auto bounds = e.second->GetBounds();
if (bounds && frustum.aabbFrustumTest(*bounds)) {
e.second->AddToRenderer();
}
}
}
void CParticleDatabase::AddToRendererClippedParticleGenMapMasked(
const std::map<std::string, std::unique_ptr<CParticleGenInfo>>& map, const zeus::CFrustum& frustum, int mask,
int target) {
for (auto& e : map) {
for (const auto& e : map) {
if ((e.second->GetFlags() & mask) == target) {
auto bounds = e.second->GetBounds();
if (bounds && frustum.aabbFrustumTest(*bounds))
const auto bounds = e.second->GetBounds();
if (bounds && frustum.aabbFrustumTest(*bounds)) {
e.second->AddToRenderer();
}
}
}
}
void CParticleDatabase::RenderSystemsToBeDrawnLastMasked(int mask, int target) const {

View File

@ -340,12 +340,13 @@ CBooModel::ModelInstance* CBooModel::PushNewModelInstance(int sharedLayoutBuf) {
};
if (!g_DummyTextures) {
for (const auto& ch : mat.chunks) {
if (auto pass = ch.get_if<MaterialSet::Material::PASS>()) {
if (const auto* const pass = ch.get_if<MaterialSet::Material::PASS>()) {
auto search = x1c_textures.find(pass->texId.toUint32());
boo::ObjToken<boo::ITexture> btex;
if (search != x1c_textures.cend() && (btex = search->second.GetObj()->GetBooTexture()))
if (search != x1c_textures.cend() && (btex = search->second.GetObj()->GetBooTexture())) {
texs[MaterialSet::Material::TexMapIdx(pass->type)] = btex;
} else if (auto pass = ch.get_if<MaterialSet::Material::CLR>()) {
}
} else if (const auto* const pass = ch.get_if<MaterialSet::Material::CLR>()) {
boo::ObjToken<boo::ITexture> btex = g_Renderer->GetColorTexture(zeus::CColor(pass->color));
texs[MaterialSet::Material::TexMapIdx(pass->type)] = btex;
}
@ -424,7 +425,7 @@ void CBooModel::MakeTexturesFromMats(const MaterialSet& matSet,
IObjectStore& store) {
for (const auto& mat : matSet.materials) {
for (const auto& chunk : mat.chunks) {
if (auto pass = chunk.get_if<MaterialSet::Material::PASS>()) {
if (const auto* const pass = chunk.get_if<MaterialSet::Material::PASS>()) {
toksOut.emplace(std::make_pair(pass->texId.toUint32(), store.GetObj({SBIG('TXTR'), pass->texId.toUint32()})));
}
}
@ -485,8 +486,8 @@ bool CBooModel::TryLockTextures() {
}
if (allLoad) {
for (auto& pipeline : *m_pipelines) {
for (auto& subpipeline : *pipeline.second) {
for (const auto& pipeline : *m_pipelines) {
for (const auto& subpipeline : *pipeline.second) {
if (!subpipeline->isReady()) {
allLoad = false;
break;
@ -682,7 +683,7 @@ void CBooModel::WarmupDrawSurface(const CBooSurface& surf) const {
return;
const ModelInstance& inst = m_instances[m_uniUpdateCount - 1];
for (auto& binding : inst.m_shaderDataBindings[surf.selfIdx]) {
for (const auto& binding : inst.m_shaderDataBindings[surf.selfIdx]) {
CGraphics::SetShaderDataBinding(binding);
CGraphics::DrawArrayIndexed(surf.m_data.idxStart, std::min(u32(3), surf.m_data.idxCount));
}
@ -865,7 +866,7 @@ void CBooModel::UVAnimationBuffer::Update(u8*& bufOut, const MaterialSet* matSet
}
u8* bufOrig = bufOut;
for (const auto& chunk : mat.chunks) {
if (auto pass = chunk.get_if<MaterialSet::Material::PASS>()) {
if (const auto* const pass = chunk.get_if<MaterialSet::Material::PASS>()) {
ProcessAnimation(bufOut, *pass);
}
}
@ -1289,14 +1290,14 @@ bool CModel::IsLoaded(int shaderIdx) const {
size_t CModel::GetPoolVertexOffset(size_t idx) const { return m_hmdlMeta.vertStride * idx; }
zeus::CVector3f CModel::GetPoolVertex(size_t idx) const {
auto* floats = reinterpret_cast<const float*>(m_dynamicVertexData.get() + GetPoolVertexOffset(idx));
const auto* floats = reinterpret_cast<const float*>(m_dynamicVertexData.get() + GetPoolVertexOffset(idx));
return {floats};
}
size_t CModel::GetPoolNormalOffset(size_t idx) const { return m_hmdlMeta.vertStride * idx + 12; }
zeus::CVector3f CModel::GetPoolNormal(size_t idx) const {
auto* floats = reinterpret_cast<const float*>(m_dynamicVertexData.get() + GetPoolNormalOffset(idx));
const auto* floats = reinterpret_cast<const float*>(m_dynamicVertexData.get() + GetPoolNormalOffset(idx));
return {floats};
}

View File

@ -151,13 +151,13 @@ void CRainSplashGenerator::Update(float dt, CStateManager& mgr) {
u32 CRainSplashGenerator::GetNextBestPt(u32 pt, const std::vector<std::pair<zeus::CVector3f, zeus::CVector3f>>& vn,
CRandom16& rand, float minZ) {
auto& refVert = vn[pt];
const auto& refVert = vn[pt];
float maxDist = 0.f;
u32 nextPt = pt;
for (int i = 0; i < 3; ++i) {
auto idx = u32(rand.Range(0, int(vn.size() - 1)));
auto& vert = vn[idx];
float distSq = (refVert.first - vert.first).magSquared();
const auto idx = u32(rand.Range(0, int(vn.size() - 1)));
const auto& vert = vn[idx];
const float distSq = (refVert.first - vert.first).magSquared();
if (distSq > maxDist && vert.second.dot(zeus::skUp) >= 0.f &&
(vert.first.z() <= 0.f || vert.first.z() > minZ)) {
nextPt = idx;

View File

@ -1,5 +1,7 @@
#include "Runtime/Graphics/CTexture.hpp"
#include <array>
#include "Runtime/CSimplePool.hpp"
#include "Runtime/CToken.hpp"
#include "Runtime/Graphics/CGraphics.hpp"
@ -7,28 +9,43 @@
#include "Runtime/GameGlobalObjects.hpp"
namespace urde {
static logvisor::Module Log("urde::CTextureBoo");
namespace {
logvisor::Module Log("urde::CTextureBoo");
struct RGBA8 {
u8 r;
u8 g;
u8 b;
u8 a;
};
struct DXT1Block {
u16 color1;
u16 color2;
std::array<u8, 4> lines;
};
/* GX uses this upsampling technique to extract full 8-bit range */
constexpr uint8_t Convert3To8(uint8_t v) {
constexpr u8 Convert3To8(u8 v) {
/* Swizzle bits: 00000123 -> 12312312 */
return (v << 5) | (v << 2) | (v >> 1);
return static_cast<u8>((u32{v} << 5) | (u32{v} << 2) | (u32{v} >> 1));
}
constexpr uint8_t Convert4To8(uint8_t v) {
constexpr u8 Convert4To8(u8 v) {
/* Swizzle bits: 00001234 -> 12341234 */
return (v << 4) | v;
return static_cast<u8>((u32{v} << 4) | u32{v});
}
constexpr uint8_t Convert5To8(uint8_t v) {
constexpr u8 Convert5To8(u8 v) {
/* Swizzle bits: 00012345 -> 12345123 */
return (v << 3) | (v >> 2);
return static_cast<u8>((u32{v} << 3) | (u32{v} >> 2));
}
constexpr uint8_t Convert6To8(uint8_t v) {
constexpr u8 Convert6To8(u8 v) {
/* Swizzle bits: 00123456 -> 12345612 */
return (v << 2) | (v >> 4);
return static_cast<u8>((u32{v} << 2) | (u32{v} >> 4));
}
} // Anonymous namespace
size_t CTexture::ComputeMippedTexelCount() const {
size_t w = x4_w;
@ -58,32 +75,25 @@ size_t CTexture::ComputeMippedBlockCountDXT1() const {
return ret;
}
struct RGBA8 {
u8 r;
u8 g;
u8 b;
u8 a;
};
void CTexture::BuildI4FromGCN(CInputStream& in) {
size_t texelCount = ComputeMippedTexelCount();
const size_t texelCount = ComputeMippedTexelCount();
std::unique_ptr<RGBA8[]> buf(new RGBA8[texelCount]);
int w = x4_w;
int h = x6_h;
RGBA8* targetMip = buf.get();
for (u32 mip = 0; mip < x8_mips; ++mip) {
int bwidth = (w + 7) / 8;
int bheight = (h + 7) / 8;
const int bwidth = (w + 7) / 8;
const int bheight = (h + 7) / 8;
for (int by = 0; by < bheight; ++by) {
int baseY = by * 8;
const int baseY = by * 8;
for (int bx = 0; bx < bwidth; ++bx) {
int baseX = bx * 8;
const int baseX = bx * 8;
for (int y = 0; y < 8; ++y) {
RGBA8* target = targetMip + (baseY + y) * w + baseX;
u8 source[4];
in.readBytesToBuf(source, 4);
for (int x = 0; x < 8; ++x) {
std::array<u8, 4> source;
in.readBytesToBuf(source.data(), source.size());
for (size_t x = 0; x < 8; ++x) {
target[x].r = Convert4To8(source[x / 2] >> ((x & 1) ? 0 : 4) & 0xf);
target[x].g = target[x].r;
target[x].b = target[x].r;
@ -93,11 +103,13 @@ void CTexture::BuildI4FromGCN(CInputStream& in) {
}
}
targetMip += w * h;
if (w > 1)
if (w > 1) {
w /= 2;
if (h > 1)
}
if (h > 1) {
h /= 2;
}
}
CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) {
m_booTex = ctx.newStaticTexture(x4_w, x6_h, x8_mips, boo::TextureFormat::RGBA8, boo::TextureClampMode::Repeat,
@ -108,24 +120,24 @@ void CTexture::BuildI4FromGCN(CInputStream& in) {
}
void CTexture::BuildI8FromGCN(CInputStream& in) {
size_t texelCount = ComputeMippedTexelCount();
const size_t texelCount = ComputeMippedTexelCount();
std::unique_ptr<RGBA8[]> buf(new RGBA8[texelCount]);
int w = x4_w;
int h = x6_h;
RGBA8* targetMip = buf.get();
for (u32 mip = 0; mip < x8_mips; ++mip) {
int bwidth = (w + 7) / 8;
int bheight = (h + 3) / 4;
const int bwidth = (w + 7) / 8;
const int bheight = (h + 3) / 4;
for (int by = 0; by < bheight; ++by) {
int baseY = by * 4;
const int baseY = by * 4;
for (int bx = 0; bx < bwidth; ++bx) {
int baseX = bx * 8;
const int baseX = bx * 8;
for (int y = 0; y < 4; ++y) {
RGBA8* target = targetMip + (baseY + y) * w + baseX;
u8 source[8];
in.readBytesToBuf(source, 8);
for (int x = 0; x < 8; ++x) {
std::array<u8, 8> source;
in.readBytesToBuf(source.data(), source.size());
for (size_t x = 0; x < source.size(); ++x) {
target[x].r = source[x];
target[x].g = source[x];
target[x].b = source[x];
@ -135,11 +147,13 @@ void CTexture::BuildI8FromGCN(CInputStream& in) {
}
}
targetMip += w * h;
if (w > 1)
if (w > 1) {
w /= 2;
if (h > 1)
}
if (h > 1) {
h /= 2;
}
}
CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) {
m_booTex = ctx.newStaticTexture(x4_w, x6_h, x8_mips, boo::TextureFormat::RGBA8, boo::TextureClampMode::Repeat,
@ -150,25 +164,25 @@ void CTexture::BuildI8FromGCN(CInputStream& in) {
}
void CTexture::BuildIA4FromGCN(CInputStream& in) {
size_t texelCount = ComputeMippedTexelCount();
const size_t texelCount = ComputeMippedTexelCount();
std::unique_ptr<RGBA8[]> buf(new RGBA8[texelCount]);
int w = x4_w;
int h = x6_h;
RGBA8* targetMip = buf.get();
for (u32 mip = 0; mip < x8_mips; ++mip) {
int bwidth = (w + 7) / 8;
int bheight = (h + 3) / 4;
const int bwidth = (w + 7) / 8;
const int bheight = (h + 3) / 4;
for (int by = 0; by < bheight; ++by) {
int baseY = by * 4;
const int baseY = by * 4;
for (int bx = 0; bx < bwidth; ++bx) {
int baseX = bx * 8;
const int baseX = bx * 8;
for (int y = 0; y < 4; ++y) {
RGBA8* target = targetMip + (baseY + y) * w + baseX;
u8 source[8];
in.readBytesToBuf(source, 8);
for (int x = 0; x < 8; ++x) {
u8 intensity = Convert4To8(source[x] >> 4 & 0xf);
std::array<u8, 8> source;
in.readBytesToBuf(source.data(), source.size());
for (size_t x = 0; x < source.size(); ++x) {
const u8 intensity = Convert4To8(source[x] >> 4 & 0xf);
target[x].r = intensity;
target[x].g = intensity;
target[x].b = intensity;
@ -178,11 +192,13 @@ void CTexture::BuildIA4FromGCN(CInputStream& in) {
}
}
targetMip += w * h;
if (w > 1)
if (w > 1) {
w /= 2;
if (h > 1)
}
if (h > 1) {
h /= 2;
}
}
CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) {
m_booTex = ctx.newStaticTexture(x4_w, x6_h, x8_mips, boo::TextureFormat::RGBA8, boo::TextureClampMode::Repeat,
@ -193,25 +209,25 @@ void CTexture::BuildIA4FromGCN(CInputStream& in) {
}
void CTexture::BuildIA8FromGCN(CInputStream& in) {
size_t texelCount = ComputeMippedTexelCount();
const size_t texelCount = ComputeMippedTexelCount();
std::unique_ptr<RGBA8[]> buf(new RGBA8[texelCount]);
int w = x4_w;
int h = x6_h;
RGBA8* targetMip = buf.get();
for (u32 mip = 0; mip < x8_mips; ++mip) {
int bwidth = (w + 3) / 4;
int bheight = (h + 3) / 4;
const int bwidth = (w + 3) / 4;
const int bheight = (h + 3) / 4;
for (int by = 0; by < bheight; ++by) {
int baseY = by * 4;
const int baseY = by * 4;
for (int bx = 0; bx < bwidth; ++bx) {
int baseX = bx * 4;
const int baseX = bx * 4;
for (int y = 0; y < 4; ++y) {
RGBA8* target = targetMip + (baseY + y) * w + baseX;
u16 source[4];
in.readBytesToBuf(source, 8);
for (int x = 0; x < 4; ++x) {
u8 intensity = source[x] >> 8;
std::array<u16, 4> source;
in.readBytesToBuf(source.data(), sizeof(source));
for (size_t x = 0; x < source.size(); ++x) {
const u8 intensity = source[x] >> 8;
target[x].r = intensity;
target[x].g = intensity;
target[x].b = intensity;
@ -221,11 +237,13 @@ void CTexture::BuildIA8FromGCN(CInputStream& in) {
}
}
targetMip += w * h;
if (w > 1)
if (w > 1) {
w /= 2;
if (h > 1)
}
if (h > 1) {
h /= 2;
}
}
CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) {
m_booTex = ctx.newStaticTexture(x4_w, x6_h, x8_mips, boo::TextureFormat::RGBA8, boo::TextureClampMode::Repeat,
@ -277,7 +295,7 @@ static std::vector<RGBA8> DecodePalette(int numEntries, CInputStream& in) {
}
void CTexture::BuildC4FromGCN(CInputStream& in) {
size_t texelCount = ComputeMippedTexelCount();
const size_t texelCount = ComputeMippedTexelCount();
std::unique_ptr<RGBA8[]> buf(new RGBA8[texelCount]);
std::vector<RGBA8> palette = DecodePalette(16, in);
@ -285,27 +303,30 @@ void CTexture::BuildC4FromGCN(CInputStream& in) {
int h = x6_h;
RGBA8* targetMip = buf.get();
for (u32 mip = 0; mip < x8_mips; ++mip) {
int bwidth = (w + 7) / 8;
int bheight = (h + 7) / 8;
const int bwidth = (w + 7) / 8;
const int bheight = (h + 7) / 8;
for (int by = 0; by < bheight; ++by) {
int baseY = by * 8;
const int baseY = by * 8;
for (int bx = 0; bx < bwidth; ++bx) {
int baseX = bx * 8;
const int baseX = bx * 8;
for (int y = 0; y < 8; ++y) {
RGBA8* target = targetMip + (baseY + y) * w + baseX;
u8 source[4];
in.readBytesToBuf(source, 4);
for (int x = 0; x < 8; ++x)
std::array<u8, 4> source;
in.readBytesToBuf(source.data(), source.size());
for (size_t x = 0; x < 8; ++x) {
target[x] = palette[source[x / 2] >> ((x & 1) ? 0 : 4) & 0xf];
}
}
}
}
targetMip += w * h;
if (w > 1)
if (w > 1) {
w /= 2;
if (h > 1)
}
if (h > 1) {
h /= 2;
}
}
CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) {
m_booTex = ctx.newStaticTexture(x4_w, x6_h, x8_mips, boo::TextureFormat::RGBA8, boo::TextureClampMode::Repeat,
@ -316,7 +337,7 @@ void CTexture::BuildC4FromGCN(CInputStream& in) {
}
void CTexture::BuildC8FromGCN(CInputStream& in) {
size_t texelCount = ComputeMippedTexelCount();
const size_t texelCount = ComputeMippedTexelCount();
std::unique_ptr<RGBA8[]> buf(new RGBA8[texelCount]);
std::vector<RGBA8> palette = DecodePalette(256, in);
@ -324,27 +345,30 @@ void CTexture::BuildC8FromGCN(CInputStream& in) {
int h = x6_h;
RGBA8* targetMip = buf.get();
for (u32 mip = 0; mip < x8_mips; ++mip) {
int bwidth = (w + 7) / 8;
int bheight = (h + 3) / 4;
const int bwidth = (w + 7) / 8;
const int bheight = (h + 3) / 4;
for (int by = 0; by < bheight; ++by) {
int baseY = by * 4;
const int baseY = by * 4;
for (int bx = 0; bx < bwidth; ++bx) {
int baseX = bx * 8;
const int baseX = bx * 8;
for (int y = 0; y < 4; ++y) {
RGBA8* target = targetMip + (baseY + y) * w + baseX;
u8 source[8];
in.readBytesToBuf(source, 8);
for (int x = 0; x < 8; ++x)
std::array<u8, 8> source;
in.readBytesToBuf(source.data(), source.size());
for (size_t x = 0; x < source.size(); ++x) {
target[x] = palette[source[x]];
}
}
}
}
targetMip += w * h;
if (w > 1)
if (w > 1) {
w /= 2;
if (h > 1)
}
if (h > 1) {
h /= 2;
}
}
CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) {
m_booTex = ctx.newStaticTexture(x4_w, x6_h, x8_mips, boo::TextureFormat::RGBA8, boo::TextureClampMode::Repeat,
@ -357,23 +381,23 @@ void CTexture::BuildC8FromGCN(CInputStream& in) {
void CTexture::BuildC14X2FromGCN(CInputStream& in) {}
void CTexture::BuildRGB565FromGCN(CInputStream& in) {
size_t texelCount = ComputeMippedTexelCount();
const size_t texelCount = ComputeMippedTexelCount();
std::unique_ptr<RGBA8[]> buf(new RGBA8[texelCount]);
int w = x4_w;
int h = x6_h;
RGBA8* targetMip = buf.get();
for (u32 mip = 0; mip < x8_mips; ++mip) {
int bwidth = (w + 3) / 4;
int bheight = (h + 3) / 4;
const int bwidth = (w + 3) / 4;
const int bheight = (h + 3) / 4;
for (int by = 0; by < bheight; ++by) {
int baseY = by * 4;
const int baseY = by * 4;
for (int bx = 0; bx < bwidth; ++bx) {
int baseX = bx * 4;
const int baseX = bx * 4;
for (int y = 0; y < 4; ++y) {
RGBA8* target = targetMip + (baseY + y) * w + baseX;
for (int x = 0; x < 4; ++x) {
u16 texel = in.readUint16Big();
for (size_t x = 0; x < 4; ++x) {
const u16 texel = in.readUint16Big();
target[x].r = Convert5To8(texel >> 11 & 0x1f);
target[x].g = Convert6To8(texel >> 5 & 0x3f);
target[x].b = Convert5To8(texel & 0x1f);
@ -383,11 +407,13 @@ void CTexture::BuildRGB565FromGCN(CInputStream& in) {
}
}
targetMip += w * h;
if (w > 1)
if (w > 1) {
w /= 2;
if (h > 1)
}
if (h > 1) {
h /= 2;
}
}
CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) {
m_booTex = ctx.newStaticTexture(x4_w, x6_h, x8_mips, boo::TextureFormat::RGBA8, boo::TextureClampMode::Repeat,
@ -405,17 +431,17 @@ void CTexture::BuildRGB5A3FromGCN(CInputStream& in) {
int h = x6_h;
RGBA8* targetMip = buf.get();
for (u32 mip = 0; mip < x8_mips; ++mip) {
int bwidth = (w + 3) / 4;
int bheight = (h + 3) / 4;
const int bwidth = (w + 3) / 4;
const int bheight = (h + 3) / 4;
for (int by = 0; by < bheight; ++by) {
int baseY = by * 4;
const int baseY = by * 4;
for (int bx = 0; bx < bwidth; ++bx) {
int baseX = bx * 4;
const int baseX = bx * 4;
for (int y = 0; y < 4; ++y) {
RGBA8* target = targetMip + (baseY + y) * w + baseX;
for (int x = 0; x < 4; ++x) {
u16 texel = in.readUint16Big();
if (texel & 0x8000) {
for (size_t x = 0; x < 4; ++x) {
const u16 texel = in.readUint16Big();
if ((texel & 0x8000) != 0) {
target[x].r = Convert5To8(texel >> 10 & 0x1f);
target[x].g = Convert5To8(texel >> 5 & 0x1f);
target[x].b = Convert5To8(texel & 0x1f);
@ -431,11 +457,13 @@ void CTexture::BuildRGB5A3FromGCN(CInputStream& in) {
}
}
targetMip += w * h;
if (w > 1)
if (w > 1) {
w /= 2;
if (h > 1)
}
if (h > 1) {
h /= 2;
}
}
CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) {
m_booTex = ctx.newStaticTexture(x4_w, x6_h, x8_mips, boo::TextureFormat::RGBA8, boo::TextureClampMode::Repeat,
@ -446,26 +474,26 @@ void CTexture::BuildRGB5A3FromGCN(CInputStream& in) {
}
void CTexture::BuildRGBA8FromGCN(CInputStream& in) {
size_t texelCount = ComputeMippedTexelCount();
const size_t texelCount = ComputeMippedTexelCount();
std::unique_ptr<RGBA8[]> buf(new RGBA8[texelCount]);
int w = x4_w;
int h = x6_h;
RGBA8* targetMip = buf.get();
for (u32 mip = 0; mip < x8_mips; ++mip) {
int bwidth = (w + 3) / 4;
int bheight = (h + 3) / 4;
const int bwidth = (w + 3) / 4;
const int bheight = (h + 3) / 4;
for (int by = 0; by < bheight; ++by) {
int baseY = by * 4;
const int baseY = by * 4;
for (int bx = 0; bx < bwidth; ++bx) {
int baseX = bx * 4;
const int baseX = bx * 4;
for (int c = 0; c < 2; ++c) {
for (int y = 0; y < 4; ++y) {
RGBA8* target = targetMip + (baseY + y) * w + baseX;
u8 source[8];
in.readBytesToBuf(source, 8);
for (int x = 0; x < 4; ++x) {
if (c) {
std::array<u8, 8> source;
in.readBytesToBuf(source.data(), source.size());
for (size_t x = 0; x < 4; ++x) {
if (c != 0) {
target[x].g = source[x * 2];
target[x].b = source[x * 2 + 1];
} else {
@ -478,11 +506,13 @@ void CTexture::BuildRGBA8FromGCN(CInputStream& in) {
}
}
targetMip += w * h;
if (w > 1)
if (w > 1) {
w /= 2;
if (h > 1)
}
if (h > 1) {
h /= 2;
}
}
CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) {
m_booTex = ctx.newStaticTexture(x4_w, x6_h, x8_mips, boo::TextureFormat::RGBA8, boo::TextureClampMode::Repeat,
@ -492,36 +522,30 @@ void CTexture::BuildRGBA8FromGCN(CInputStream& in) {
} BooTrace);
}
struct DXT1Block {
uint16_t color1;
uint16_t color2;
uint8_t lines[4];
};
void CTexture::BuildDXT1FromGCN(CInputStream& in) {
size_t blockCount = ComputeMippedBlockCountDXT1();
const size_t blockCount = ComputeMippedBlockCountDXT1();
std::unique_ptr<DXT1Block[]> buf(new DXT1Block[blockCount]);
int w = x4_w / 4;
int h = x6_h / 4;
DXT1Block* targetMip = buf.get();
for (u32 mip = 0; mip < x8_mips; ++mip) {
int bwidth = (w + 1) / 2;
int bheight = (h + 1) / 2;
const int bwidth = (w + 1) / 2;
const int bheight = (h + 1) / 2;
for (int by = 0; by < bheight; ++by) {
int baseY = by * 2;
const int baseY = by * 2;
for (int bx = 0; bx < bwidth; ++bx) {
int baseX = bx * 2;
const int baseX = bx * 2;
for (int y = 0; y < 2; ++y) {
DXT1Block* target = targetMip + (baseY + y) * w + baseX;
DXT1Block source[2];
in.readBytesToBuf(source, 16);
for (int x = 0; x < 2; ++x) {
std::array<DXT1Block, 2> source;
in.readBytesToBuf(source.data(), sizeof(source));
for (size_t x = 0; x < source.size(); ++x) {
target[x].color1 = hecl::SBig(source[x].color1);
target[x].color2 = hecl::SBig(source[x].color2);
for (u32 i = 0; i < 4; ++i) {
u8 ind[4];
u8 packed = source[x].lines[i];
for (size_t i = 0; i < 4; ++i) {
std::array<u8, 4> ind;
const u8 packed = source[x].lines[i];
ind[3] = packed & 0x3;
ind[2] = (packed >> 2) & 0x3;
ind[1] = (packed >> 4) & 0x3;
@ -534,11 +558,13 @@ void CTexture::BuildDXT1FromGCN(CInputStream& in) {
}
targetMip += w * h;
if (w > 1)
if (w > 1) {
w /= 2;
if (h > 1)
}
if (h > 1) {
h /= 2;
}
}
CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) {
m_booTex = ctx.newStaticTexture(x4_w, x6_h, x8_mips, boo::TextureFormat::DXT1, boo::TextureClampMode::Repeat,
@ -602,10 +628,9 @@ void CTexture::BuildC8Font(const void* data, EFontType ftype) {
break;
}
uint32_t nentries = hecl::SBig(*reinterpret_cast<const uint32_t*>(data));
const uint32_t nentries = hecl::SBig(*reinterpret_cast<const uint32_t*>(data));
const u8* texels = reinterpret_cast<const u8*>(data) + 4 + nentries * 4;
std::unique_ptr<RGBA8[]> buf(new RGBA8[texelCount * layerCount]);
memset(buf.get(), 0, texelCount * layerCount * 4);
auto buf = std::make_unique<RGBA8[]>(texelCount * layerCount);
size_t w = x4_w;
size_t h = x6_h;

View File

@ -204,10 +204,10 @@ CFluidPlaneShader::CFluidPlaneShader(EFluidType type, const TLockedToken<CTextur
, m_envBumpMap(envBumpMap)
, m_lightmap(lightmap)
, m_rippleMap(rippleMap) {
SFluidPlaneShaderInfo shaderInfo(type, m_patternTex1.operator bool(), m_patternTex2.operator bool(),
m_colorTex.operator bool(), m_bumpMap.operator bool(), m_envMap.operator bool(),
m_envBumpMap.operator bool(), m_lightmap.operator bool(),
m_rippleMap.operator bool(), doubleLightmapBlend, additive);
SFluidPlaneShaderInfo shaderInfo(type, m_patternTex1.HasReference(), m_patternTex2.HasReference(),
m_colorTex.HasReference(), m_bumpMap.HasReference(), m_envMap.HasReference(),
m_envBumpMap.HasReference(), m_lightmap.HasReference(), m_rippleMap.operator bool(),
doubleLightmapBlend, additive);
m_pipelines = _cache.GetOrBuildShader(shaderInfo);
PrepareBinding(maxVertCount);
}
@ -216,8 +216,8 @@ CFluidPlaneShader::CFluidPlaneShader(const TLockedToken<CTexture>& patternTex1,
const TLockedToken<CTexture>& patternTex2, const TLockedToken<CTexture>& colorTex,
u32 maxVertCount)
: m_patternTex1(patternTex1), m_patternTex2(patternTex2), m_colorTex(colorTex) {
SFluidPlaneDoorShaderInfo shaderInfo(m_patternTex1.operator bool(), m_patternTex2.operator bool(),
m_colorTex.operator bool());
SFluidPlaneDoorShaderInfo shaderInfo(m_patternTex1.HasReference(), m_patternTex2.HasReference(),
m_colorTex.HasReference());
m_pipelines = _cache.GetOrBuildShader(shaderInfo);
PrepareBinding(maxVertCount);
}

View File

@ -19,8 +19,6 @@ std::array<boo::ObjToken<boo::IShaderPipeline>, 2> CParticleSwooshShaders::m_noT
std::array<boo::ObjToken<boo::IShaderPipeline>, 2> CParticleSwooshShaders::m_noTexAdditiveZWrite;
std::array<boo::ObjToken<boo::IShaderPipeline>, 2> CParticleSwooshShaders::m_noTexAdditiveNoZWrite;
static boo::ObjToken<boo::IShaderPipeline> s_Pipeline;
void CParticleSwooshShaders::Initialize() {
m_texZWrite = {hecl::conv->convert(Shader_CParticleSwooshShaderTexZWrite{}),
hecl::conv->convert(Shader_CParticleSwooshShaderTexZWriteAWrite{})};

View File

@ -289,7 +289,7 @@ void CMFGameLoader::MakeLoadDependencyList() {
static constexpr std::array loadDepPAKs{"TestAnim", "SamusGun", "SamGunFx"};
std::vector<SObjectTag> tags;
for (const auto pak : loadDepPAKs) {
for (const auto* const pak : loadDepPAKs) {
g_ResFactory->GetTagListForFile(pak, tags);
}

View File

@ -1,10 +1,16 @@
#include "Runtime/MP1/CSlideShow.hpp"
#include "Editor/ProjectManager.hpp"
#include <algorithm>
#include "Editor/ProjectManager.hpp"
#include "Runtime/GameGlobalObjects.hpp"
namespace urde {
namespace {
bool AreAllDepsLoaded(const std::vector<TLockedToken<CDependencyGroup>>& deps) {
return std::all_of(deps.cbegin(), deps.cend(), [](const auto& dep) { return dep.IsLoaded(); });
}
} // Anonymous namespace
CSlideShow::CSlideShow() : CIOWin("SlideShow"), x130_(g_tweakSlideShow->GetX54()) {
const SObjectTag* font = g_ResFactory->GetResourceIdByName(g_tweakSlideShow->GetFont());
@ -58,14 +64,6 @@ bool CSlideShow::LoadTXTRDep(std::string_view name) {
return false;
}
bool CSlideShow::AreAllDepsLoaded(const std::vector<TLockedToken<CDependencyGroup>>& deps) {
for (const TLockedToken<CDependencyGroup>& token : deps) {
if (!token.IsLoaded())
return false;
}
return true;
}
CIOWin::EMessageReturn CSlideShow::OnMessage(const CArchitectureMessage& msg, CArchitectureQueue& queue) {
switch (msg.GetType()) {
case EArchMsgType::TimerTick: {

View File

@ -98,7 +98,6 @@ private:
bool x135_24_ : 1 = true;
bool LoadTXTRDep(std::string_view name);
static bool AreAllDepsLoaded(const std::vector<TLockedToken<CDependencyGroup>>& deps);
public:
CSlideShow();

View File

@ -21,9 +21,7 @@
#include <logvisor/logvisor.hpp>
namespace urde {
namespace MP1 {
namespace urde::MP1 {
static logvisor::Module Log("MP1::CTweaks");
@ -136,5 +134,4 @@ void CTweaks::RegisterResourceTweaks(hecl::CVarManager* cvarMgr) {
g_tweakPlayerRes->initCVars(cvarMgr);
}
} // namespace MP1
} // namespace urde
} // namespace urde::MP1

View File

@ -1,5 +1,6 @@
#include "Runtime/MP1/World/CElitePirate.hpp"
#include "Runtime/Camera/CFirstPersonCamera.hpp"
#include "Runtime/Collision/CCollisionActor.hpp"
#include "Runtime/Collision/CCollisionActorManager.hpp"
#include "Runtime/CSimplePool.hpp"
@ -248,10 +249,10 @@ void CElitePirate::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CSta
void CElitePirate::PreRender(CStateManager& mgr, const zeus::CFrustum& frustum) {
CPatterned::PreRender(mgr, frustum);
auto modelData = GetModelData();
auto* modelData = GetModelData();
x6f8_boneTracking.PreRender(mgr, *modelData->GetAnimationData(), GetTransform(), modelData->GetScale(),
*x450_bodyController);
auto numMaterialSets = modelData->GetNumMaterialSets();
const auto numMaterialSets = modelData->GetNumMaterialSets();
xb4_drawFlags.x1_matSetIdx =
numMaterialSets - 1 < x7cc_activeMaterialSet ? numMaterialSets - 1 : x7cc_activeMaterialSet;
}
@ -292,27 +293,22 @@ zeus::CVector3f CElitePirate::GetAimPosition(const CStateManager& mgr, float) co
}
void CElitePirate::DoUserAnimEvent(CStateManager& mgr, const CInt32POINode& node, EUserEventType type, float dt) {
bool handled = false;
switch (type) {
case EUserEventType::Projectile:
if (x772_launcherId != kInvalidUniqueId) {
CEntity* launcher = mgr.ObjectById(x772_launcherId);
mgr.SendScriptMsg(launcher, GetUniqueId(), EScriptObjectMessage::Action);
}
handled = true;
break;
return;
case EUserEventType::DamageOn:
handled = true;
x988_24_damageOn = true;
break;
return;
case EUserEventType::DamageOff:
handled = true;
x988_24_damageOn = false;
break;
return;
case EUserEventType::ScreenShake:
HasWeakPointHead();
handled = true;
break;
ShakeCamera(mgr);
return;
case EUserEventType::BeginAction: {
const zeus::CVector3f origin = GetTranslation();
const zeus::CVector3f front = GetTransform().frontVector();
@ -325,8 +321,7 @@ void CElitePirate::DoUserAnimEvent(CStateManager& mgr, const CInt32POINode& node
mgr.AddObject(new CShockWave(mgr.AllocateUniqueId(), "Shock Wave", {GetAreaIdAlways(), CEntity::NullConnectionList},
xf, GetUniqueId(), GetShockWaveData(), IsElitePirate() ? 2.f : 1.3f,
IsElitePirate() ? 0.4f : 0.5f));
handled = true;
break;
return;
}
case EUserEventType::BecomeShootThrough:
if (HasWeakPointHead()) {
@ -338,14 +333,11 @@ void CElitePirate::DoUserAnimEvent(CStateManager& mgr, const CInt32POINode& node
}
}
}
handled = true;
break;
return;
default:
break;
}
if (!handled) {
CPatterned::DoUserAnimEvent(mgr, node, type, dt);
}
}
const CCollisionPrimitive* CElitePirate::GetCollisionPrimitive() const { return &x738_collisionAabb; }
@ -757,7 +749,7 @@ void CElitePirate::SetupHealthInfo(CStateManager& mgr) {
x7b4_hp = health->GetHP();
if (HasWeakPointHead()) {
if (TCastToPtr<CCollisionActor> actor = mgr.ObjectById(x770_collisionHeadId)) {
auto actHealth = actor->HealthInfo(mgr);
auto* actHealth = actor->HealthInfo(mgr);
actHealth->SetHP(health->GetHP());
actHealth->SetKnockbackResistance(health->GetKnockbackResistance());
actor->SetDamageVulnerability(x56c_vulnerability);
@ -940,21 +932,23 @@ void CElitePirate::CreateEnergyAbsorb(CStateManager& mgr, const zeus::CTransform
void CElitePirate::SetupLauncherHealthInfo(CStateManager& mgr, TUniqueId uid) {
const CHealthInfo* const health = HealthInfo(mgr);
if (uid != kInvalidUniqueId) {
if (TCastToPtr<CCollisionActor> actor = mgr.ObjectById(uid)) {
auto actHealth = actor->HealthInfo(mgr);
if (uid == kInvalidUniqueId) {
return;
}
if (const TCastToPtr<CCollisionActor> actor = mgr.ObjectById(uid)) {
auto* actHealth = actor->HealthInfo(mgr);
actHealth->SetHP(x5d8_data.GetLauncherHP());
actHealth->SetKnockbackResistance(health->GetKnockbackResistance());
actor->SetDamageVulnerability(x56c_vulnerability);
}
}
}
void CElitePirate::SetLauncherActive(CStateManager& mgr, bool val, TUniqueId uid) {
if (uid == kInvalidUniqueId) {
return;
}
if (auto entity = mgr.ObjectById(uid)) {
if (auto* entity = mgr.ObjectById(uid)) {
mgr.SendScriptMsg(entity, GetUniqueId(), val ? EScriptObjectMessage::Start : EScriptObjectMessage::Stop);
}
}
@ -1178,6 +1172,25 @@ bool CElitePirate::IsClosestEnergyAttractor(const CStateManager& mgr,
return true;
}
void CElitePirate::ShakeCamera(CStateManager& mgr) {
CPlayer& player = mgr.GetPlayer();
const float distance = (GetTranslation() - player.GetTranslation()).magnitude();
const float scale = x988_29_shockWaveAnim ? 1.f : 0.25f;
const float magnitude = (scale * GetModelData()->GetScale().magnitude()) - (0.005f * distance);
if (magnitude <= 0.f || player.GetSurfaceRestraint() == CPlayer::ESurfaceRestraints::Air ||
player.IsInWaterMovement()) {
return;
}
if (player.GetMorphballTransitionState() == CPlayer::EPlayerMorphBallState::Morphed) {
const float intensity = x988_29_shockWaveAnim ? 20.f : 10.f;
player.ApplyImpulseWR(player.GetMass() * intensity * zeus::skUp, zeus::CAxisAngle{});
player.SetMoveState(CPlayer::EPlayerMovementState::ApplyJump, mgr);
} else if (mgr.GetCameraManager()->GetCurrentCameraId() ==
mgr.GetCameraManager()->GetFirstPersonCamera()->GetUniqueId()) {
mgr.GetCameraManager()->AddCameraShaker(CCameraShakeData{0.5f, magnitude}, true);
}
}
zeus::CVector3f CElitePirate::SPositionHistory::GetValue(const zeus::CVector3f& pos, const zeus::CVector3f& face) {
while (!x4_values.empty()) {
const zeus::CVector3f v = x4_values.back() - pos;

View File

@ -244,5 +244,6 @@ private:
const zeus::CVector3f& vec) const;
bool IsClosestEnergyAttractor(const CStateManager& mgr, const rstl::reserved_vector<TUniqueId, 1024>& charNearList,
const zeus::CVector3f& projectilePos) const;
void ShakeCamera(CStateManager& mgr);
};
} // namespace urde::MP1

View File

@ -162,9 +162,9 @@ void CPhazonHealingNodule::UpdateParticleElectric(CStateManager& mgr) {
if (!x57c_particleElectric) {
return;
}
if (auto entity = static_cast<const CPatterned*>(mgr.GetObjectById(x56e_connId))) {
auto electricityLctrXf = GetLctrTransform("Electricity_LCTR"sv);
auto actorLctrXf = entity->GetLctrTransform(x58c_actorLctr);
if (const auto* entity = static_cast<const CPatterned*>(mgr.GetObjectById(x56e_connId))) {
const auto electricityLctrXf = GetLctrTransform("Electricity_LCTR"sv);
const auto actorLctrXf = entity->GetLctrTransform(x58c_actorLctr);
x57c_particleElectric->SetOverrideIPos(electricityLctrXf.origin);
x57c_particleElectric->SetOverrideFPos(actorLctrXf.origin);
}

View File

@ -10,9 +10,9 @@
#include "TCastTo.hpp" // Generated file, do not modify include path
#define kTableSize 2048
namespace urde {
constexpr u32 kTableSize = 2048;
CFluidPlaneCPU::CTurbulence::CTurbulence(float speed, float distance, float freqMax, float freqMin, float phaseMax,
float phaseMin, float amplitudeMax, float amplitudeMin)
: x0_speed(speed)
@ -25,27 +25,29 @@ CFluidPlaneCPU::CTurbulence::CTurbulence(float speed, float distance, float freq
, x1c_amplitudeMin(amplitudeMin)
, x2c_ooTurbSpeed(1.f / x0_speed)
, x30_ooTurbDistance(1.f / x4_distance) {
if (x18_amplitudeMax != 0.f || x1c_amplitudeMin != 0.f) {
if (x18_amplitudeMax == 0.f && x1c_amplitudeMin == 0.f) {
return;
}
x24_tableCount = kTableSize;
x28_heightSelPitch = x24_tableCount;
x20_table.reset(new float[x24_tableCount]);
float anglePitch = 2.f * M_PIF / x28_heightSelPitch;
float freqConstant = 0.5f * (x8_freqMax + xc_freqMin);
float freqLinear = 0.5f * (x8_freqMax - xc_freqMin);
float phaseConstant = 0.5f * (x10_phaseMax + x14_phaseMin);
float phaseLinear = 0.5f * (x10_phaseMax - x14_phaseMin);
float amplitudeConstant = 0.5f * (x18_amplitudeMax + x1c_amplitudeMin);
float amplitudeLinear = 0.5f * (x18_amplitudeMax - x1c_amplitudeMin);
const float anglePitch = 2.f * M_PIF / x28_heightSelPitch;
const float freqConstant = 0.5f * (x8_freqMax + xc_freqMin);
const float freqLinear = 0.5f * (x8_freqMax - xc_freqMin);
const float phaseConstant = 0.5f * (x10_phaseMax + x14_phaseMin);
const float phaseLinear = 0.5f * (x10_phaseMax - x14_phaseMin);
const float amplitudeConstant = 0.5f * (x18_amplitudeMax + x1c_amplitudeMin);
const float amplitudeLinear = 0.5f * (x18_amplitudeMax - x1c_amplitudeMin);
float curAng = 0.f;
for (int i = 0; i < x24_tableCount; ++i, curAng += anglePitch) {
float angCos = std::cos(curAng);
for (size_t i = 0; i < x24_tableCount; ++i, curAng += anglePitch) {
const float angCos = std::cos(curAng);
x20_table[i] = (amplitudeLinear * angCos + amplitudeConstant) *
std::sin((freqLinear * angCos + freqConstant) * curAng + (phaseLinear * angCos + phaseConstant));
}
x34_hasTurbulence = true;
}
}
CFluidPlaneCPU::CFluidPlaneCPU(CAssetId texPattern1, CAssetId texPattern2, CAssetId texColor, CAssetId bumpMap,

File diff suppressed because it is too large Load Diff

View File

@ -249,8 +249,8 @@ public:
void ComputeLiftForces(const zeus::CVector3f& controlForce, const zeus::CVector3f& velocity,
const CStateManager& mgr);
float CalculateSurfaceFriction() const;
void ApplyGravity(CStateManager& mgr);
void SpinToSpeed(float holdMag, zeus::CVector3f torque, float mag);
void ApplyGravity(const CStateManager& mgr);
void SpinToSpeed(float holdMag, const zeus::CVector3f& torque, float mag);
float ComputeMaxSpeed() const;
void Touch(CActor& actor, CStateManager& mgr);
bool IsClimbable(const CCollisionInfo& cinfo) const;