Commit 77af3f0e authored by Jack Andersen's avatar Jack Andersen

CPuddleToadGamma and animation system fixes

parent 9ccc4227
......@@ -35,21 +35,21 @@ size_t ComputeBitstreamSize(size_t keyFrameCount, const std::vector<Channel>& ch
}
static inline QuantizedRot QuantizeRotation(const Value& quat, atUint32 div) {
float q = M_PIF / 2.0f / float(div);
float q = float(div) / (M_PIF / 2.0f);
zeus::simd_floats f(quat.simd);
assert(std::abs(f[1]) <= 1.f && "Out of range quat X component");
assert(std::abs(f[2]) <= 1.f && "Out of range quat Y component");
assert(std::abs(f[3]) <= 1.f && "Out of range quat Z component");
return {{
atInt32(std::asin(f[1]) / q),
atInt32(std::asin(f[2]) / q),
atInt32(std::asin(f[3]) / q),
atInt32(std::asin(f[1]) * q),
atInt32(std::asin(f[2]) * q),
atInt32(std::asin(f[3]) * q),
},
(f[0] < 0.f)};
}
static inline Value DequantizeRotation(const QuantizedRot& v, atUint32 div) {
float q = M_PIF / 2.0f / float(div);
float q = (M_PIF / 2.0f) / float(div);
athena::simd_floats f = {
0.0f,
std::sin(v.v[0] * q),
......@@ -259,6 +259,7 @@ void BitstreamWriter::quantize(atUint8* data, atUint8 q, atInt32 val) {
atUint32 bitRem = m_bitCur % 32;
atUint32 masked = val & ((1 << q) - 1);
assert(((((val >> 31) & 0x1) == 0x1) || (((masked >> (q - 1)) & 0x1) == 0)) && "Twos compliment fail");
/* Fill 32 bit buffer with region containing bits */
/* Make them least significant */
......@@ -317,8 +318,8 @@ std::unique_ptr<atUint8[]> BitstreamWriter::write(const std::vector<std::vector<
}
++kit;
}
transMultOut = std::max(maxTransDelta / quantRangeF, FLT_EPSILON);
scaleMultOut = std::max(maxScaleDelta / quantRangeF, FLT_EPSILON);
transMultOut = maxTransDelta / quantRangeF + FLT_EPSILON;
scaleMultOut = maxScaleDelta / quantRangeF + FLT_EPSILON;
/* Output channel inits */
std::vector<QuantizedValue> initVals;
......@@ -404,11 +405,11 @@ std::unique_ptr<atUint8[]> BitstreamWriter::write(const std::vector<std::vector<
memset(newData.get(), 0, sizeOut);
lastVals = initVals;
for (size_t f = 0; f < keyFrameCount; ++f) {
for (size_t frame = 0; frame < keyFrameCount; ++frame) {
kit = chanKeys.begin();
vit = lastVals.begin();
for (const Channel& chan : channels) {
const Value& val = (*kit++)[f + 1];
const Value& val = (*kit++)[frame + 1];
QuantizedValue& last = *vit++;
switch (chan.type) {
case Channel::Type::Rotation: {
......
......@@ -20,10 +20,13 @@ struct QuantizedValue {
atInt32 operator[](size_t idx) const { return v[idx]; }
int qFrom(const QuantizedValue& other, size_t idx) const {
atInt32 delta = std::abs(v[idx] - other.v[idx]);
if (delta == 0)
atInt32 delta = v[idx] - other.v[idx];
atInt32 absDelta = std::abs(delta);
if (absDelta == 0)
return 1;
int ret = int(std::ceil(std::log2(delta))) + 1;
int ret = int(std::ceil(std::log2(absDelta))) + 1;
if (delta > 0 && (delta >> (ret - 1)))
++ret;
assert(ret <= 24 && "Bad q value");
return ret;
}
......
......@@ -618,7 +618,8 @@ ANIM::ANIM(const BlenderAction& act, const std::unordered_map<std::string, atInt
}
}
newAnim.mainInterval = act.interval;
/* Retro's original data uses microsecond precision */
newAnim.mainInterval = std::trunc(act.interval * 1000000.0) / 1000000.0;
}
} // namespace DataSpec::DNAMP1
......@@ -9,20 +9,20 @@ struct PuddleToadGamma : IScriptObject {
AT_DECL_DNA_YAML
AT_DECL_DNAV
String<-1> name;
Value<atUint32> unknown1;
Value<atUint32> flavor;
Value<atVec3f> location;
Value<atVec3f> orientation;
Value<atVec3f> scale;
PatternedInfo patternedInfo;
ActorParameters actorParameters;
Value<float> unknown2;
Value<float> unknown3;
Value<float> unknown4;
Value<atVec3f> unknown5;
Value<float> unknown6;
Value<float> unknown7;
Value<float> unknown8;
DamageInfo damageInfo1;
Value<float> suckForceMultiplier;
Value<float> suckAngle;
Value<float> playerSuckRange;
Value<atVec3f> localShootDir;
Value<float> playerShootSpeed;
Value<float> shouldAttackWaitTime;
Value<float> spotPlayerWaitTime;
DamageInfo playerShootDamage;
DamageInfo damageInfo2;
UniqueID32 dcln;
......
......@@ -8,7 +8,7 @@ Everything else is much too experimental to make portable/stable release builds
### Platform Support
* Windows 7+ (64-bit support only)
* macOS 10.9+
* macOS 10.11+
* Linux
* Arch is known to function with [`glx` vendor setup instructions](https://wiki.archlinux.org/index.php/Category:Graphics) *(main development/testing OS)*
* **[WIP]** Vulkan loader detection is also integrated into the cmake for Linux
......@@ -16,12 +16,12 @@ Everything else is much too experimental to make portable/stable release builds
* Much multimedia functionality is in place, but not fully tested
### Build Prerequisites:
* [CMake 3.10+](https://cmake.org)
* [CMake 3.13+](https://cmake.org)
* [Python 3+](https://python.org)
* LLVM development package *(headers and libs)*
* [Specialized Windows Package](https://axiodl.com/LLVM-9.0.0svn-win64.exe)
* [macOS Package](http://releases.llvm.org/7.0.0/clang+llvm-7.0.0-x86_64-apple-darwin.tar.xz)
* **[Windows]** [Visual Studio 2017 and Windows SDK](https://www.visualstudio.com/en-us/products/visual-studio-community-vs.aspx)
* **[Windows]** [Visual Studio 2017/2019 and Windows SDK](https://www.visualstudio.com/en-us/products/visual-studio-community-vs.aspx)
* **[macOS]** [Xcode Tools](https://developer.apple.com/xcode/download/)
* **[Linux]** recent development packages of `udev`, `x11`, `xcb`, `xinput`, `glx`, `asound`
......
......@@ -924,7 +924,7 @@ void CStateManager::DrawActorCubeFaces(CActor& actor, int& cubeInst) const {
SetupFogForArea(area);
g_Renderer->EnablePVS(pvsArr[i], area.x4_selfIdx);
g_Renderer->SetWorldLightFadeLevel(area.GetPostConstructed()->x1128_worldLightingLevel);
g_Renderer->UpdateAreaUniforms(area.x4_selfIdx, false, true, cubeInst * 6 + f);
g_Renderer->UpdateAreaUniforms(area.x4_selfIdx, EWorldShadowMode::None, true, cubeInst * 6 + f);
g_Renderer->DrawUnsortedGeometry(area.x4_selfIdx, 0x2, 0x0);
}
......
......@@ -555,7 +555,8 @@ void CBooRenderer::GenerateSphereRampTex(boo::IGraphicsDataFactory::Context& ctx
}
}
x220_sphereRamp = ctx.newStaticTexture(SPHERE_RAMP_RES, SPHERE_RAMP_RES, 1, boo::TextureFormat::I8,
boo::TextureClampMode::Repeat, data[0], SPHERE_RAMP_RES * SPHERE_RAMP_RES);
boo::TextureClampMode::ClampToEdge, data[0],
SPHERE_RAMP_RES * SPHERE_RAMP_RES);
}
void CBooRenderer::GenerateScanLinesVBO(boo::IGraphicsDataFactory::Context& ctx) {
......@@ -617,8 +618,10 @@ void CBooRenderer::LoadThermoPalette() {
void CBooRenderer::LoadBallFade() {
m_ballFadeTex = xc_store.GetObj("TXTR_BallFade");
CTexture* ballFadeTexObj = m_ballFadeTex.GetObj();
if (ballFadeTexObj)
if (ballFadeTexObj) {
m_ballFade = ballFadeTexObj->GetBooTexture();
m_ballFade->setClampMode(boo::TextureClampMode::ClampToEdge);
}
}
CBooRenderer::CBooRenderer(IObjectStore& store, IFactory& resFac)
......@@ -703,18 +706,25 @@ void CBooRenderer::EnablePVS(const CPVSVisSet& set, u32 areaIdx) {
void CBooRenderer::DisablePVS() { xc8_pvs = std::nullopt; }
void CBooRenderer::UpdateAreaUniforms(int areaIdx, bool shadowRender, bool activateLights, int cubeFace) {
void CBooRenderer::UpdateAreaUniforms(int areaIdx, EWorldShadowMode shadowMode, bool activateLights, int cubeFace,
const CModelFlags* ballShadowFlags) {
SetupRendererStates();
CModelFlags flags;
int bufIdx;
if (shadowRender) {
if (shadowMode == EWorldShadowMode::WorldOnActorShadow) {
flags.m_extendedShader = EExtendedShader::SolidColor;
flags.x4_color = zeus::skBlack;
bufIdx = 1;
} else if (shadowMode == EWorldShadowMode::BallOnWorldShadow) {
flags = *ballShadowFlags;
bufIdx = 2;
} else if (shadowMode == EWorldShadowMode::BallOnWorldIds) {
flags.m_extendedShader = EExtendedShader::SolidColor;
bufIdx = 3;
} else {
flags.m_extendedShader = EExtendedShader::Lighting;
bufIdx = cubeFace == -1 ? 0 : 2 + cubeFace;
bufIdx = cubeFace == -1 ? 0 : 4 + cubeFace;
}
for (CAreaListItem& item : x1c_areaListItems) {
......@@ -724,6 +734,9 @@ void CBooRenderer::UpdateAreaUniforms(int areaIdx, bool shadowRender, bool activ
item.m_shaderSet->m_geomLayout->Update(flags, nullptr, nullptr, &item.m_shaderSet->m_matSet,
item.m_shaderSet->m_geomLayout->GetSharedBuffer(bufIdx), nullptr);
if (shadowMode == EWorldShadowMode::BallOnWorldShadow || shadowMode == EWorldShadowMode::BallOnWorldIds)
continue;
for (auto it = item.x10_models.begin(); it != item.x10_models.end(); ++it) {
CBooModel* model = *it;
if (model->TryLockTextures()) {
......@@ -1239,9 +1252,9 @@ void CBooRenderer::FindOverlappingWorldModels(std::vector<u32>& modelBits, const
}
int CBooRenderer::DrawOverlappingWorldModelIDs(int alphaVal, const std::vector<u32>& modelBits,
const zeus::CAABox& aabb) const {
const zeus::CAABox& aabb) {
SetupRendererStates();
const_cast<CBooRenderer&>(*this).UpdateAreaUniforms(-1, false, false);
UpdateAreaUniforms(-1, EWorldShadowMode::BallOnWorldIds, false);
CModelFlags flags;
flags.m_extendedShader = EExtendedShader::SolidColor; // Do solid color draw
......@@ -1263,6 +1276,7 @@ int CBooRenderer::DrawOverlappingWorldModelIDs(int alphaVal, const std::vector<u
flags.x4_color.a() = alphaVal / 255.f;
const CBooModel& model = *item.x10_models[wordModel + j];
const_cast<CBooModel&>(model).UpdateUniformData(flags, nullptr, nullptr, 3);
const_cast<CBooModel&>(model).VerifyCurrentShader(0);
for (const CBooSurface* surf = model.x38_firstUnsortedSurface; surf; surf = surf->m_next)
if (surf->GetBounds().intersects(aabb))
......@@ -1279,10 +1293,13 @@ int CBooRenderer::DrawOverlappingWorldModelIDs(int alphaVal, const std::vector<u
}
void CBooRenderer::DrawOverlappingWorldModelShadows(int alphaVal, const std::vector<u32>& modelBits,
const zeus::CAABox& aabb, float alpha) const {
const zeus::CAABox& aabb, float alpha) {
CModelFlags flags;
flags.x4_color.a() = alpha;
flags.m_extendedShader = EExtendedShader::MorphBallShadow; // Do shadow draw
flags.mbShadowBox = aabb;
UpdateAreaUniforms(-1, EWorldShadowMode::BallOnWorldShadow, false, -1, &flags);
u32 curWord = 0;
for (const CAreaListItem& item : x1c_areaListItems) {
......@@ -1301,6 +1318,7 @@ void CBooRenderer::DrawOverlappingWorldModelShadows(int alphaVal, const std::vec
flags.x4_color.r() = alphaVal / 255.f;
const CBooModel& model = *item.x10_models[wordModel + j];
const_cast<CBooModel&>(model).UpdateUniformData(flags, nullptr, nullptr, 2);
const_cast<CBooModel&>(model).VerifyCurrentShader(0);
for (const CBooSurface* surf = model.x38_firstUnsortedSurface; surf; surf = surf->m_next)
if (surf->GetBounds().intersects(aabb))
......
......@@ -47,6 +47,14 @@ public:
static void Init();
};
enum class EWorldShadowMode {
None,
WorldOnActorShadow,
BallOnWorldShadow,
BallOnWorldIds,
MAX
};
class CBooRenderer final : public IRenderer {
friend class CBooModel;
friend class CModel;
......@@ -201,7 +209,8 @@ public:
const SShader* shaderSet);
void EnablePVS(const CPVSVisSet&, u32);
void DisablePVS();
void UpdateAreaUniforms(int areaIdx, bool shadowRender = false, bool activateLights = true, int cubeFace = -1);
void UpdateAreaUniforms(int areaIdx, EWorldShadowMode shadowMode = EWorldShadowMode::None,
bool activateLights = true, int cubeFace = -1, const CModelFlags* ballShadowFlags = nullptr);
void RemoveStaticGeometry(const std::vector<CMetroidModelInstance>*);
void DrawAreaGeometry(int areaIdx, int mask, int targetMask);
void DrawUnsortedGeometry(int areaIdx, int mask, int targetMask, bool shadowRender = false);
......@@ -293,9 +302,9 @@ public:
}
void FindOverlappingWorldModels(std::vector<u32>& modelBits, const zeus::CAABox& aabb) const;
int DrawOverlappingWorldModelIDs(int alphaVal, const std::vector<u32>& modelBits, const zeus::CAABox& aabb) const;
int DrawOverlappingWorldModelIDs(int alphaVal, const std::vector<u32>& modelBits, const zeus::CAABox& aabb);
void DrawOverlappingWorldModelShadows(int alphaVal, const std::vector<u32>& modelBits, const zeus::CAABox& aabb,
float alpha) const;
float alpha);
bool IsThermalVisorActive() const { return x318_29_thermalVisor; }
bool IsThermalVisorHotPass() const { return m_thermalHotPass; }
......
......@@ -164,6 +164,7 @@ private:
boo::ObjToken<boo::IGraphicsBuffer> GetBooVBO(const CBooModel& model, boo::IGraphicsDataFactory::Context& ctx);
};
std::vector<ModelInstance> m_instances;
ModelInstance m_ballShadowInstance;
boo::ObjToken<boo::IGraphicsBufferS> m_staticVbo;
boo::ObjToken<boo::IGraphicsBufferS> m_staticIbo;
......
......@@ -456,6 +456,19 @@ bool CBooModel::TryLockTextures() const {
allLoad = false;
}
if (allLoad) {
for (auto& pipeline : *m_pipelines) {
for (auto& subpipeline : *pipeline.second) {
if (!subpipeline->isReady()) {
allLoad = false;
break;
}
}
if (!allLoad)
break;
}
}
const_cast<CBooModel*>(this)->x40_24_texturesLoaded = allLoad;
}
......@@ -730,8 +743,10 @@ void CBooModel::UVAnimationBuffer::PadOutBuffer(u8*& bufStart, u8*& bufOut) {
bufOut = bufStart + ROUND_UP_256(bufOut - bufStart);
}
static const zeus::CMatrix4f MBShadowPost0(1.f, 0.f, 0.f, 0.f, 0.f, -1.f, 0.f, 1.f, 0.f, 0.f, 0.f, 1.f, 0.f, 0.f, 0.f,
1.f);
static const zeus::CMatrix4f MBShadowPost0(1.f, 0.f, 0.f, 0.f,
0.f, -1.f, 0.f, 1.f,
0.f, 0.f, 0.f, 1.f,
0.f, 0.f, 0.f, 1.f);
static const zeus::CMatrix4f MBShadowPost1(0.f, 0.f, 0.f, 1.f, 0.f, 0.f, 1.f, -0.0625f, 0.f, 0.f, 0.f, 1.f, 0.f, 0.f,
0.f, 1.f);
......@@ -746,7 +761,7 @@ void CBooModel::UVAnimationBuffer::Update(u8*& bufOut, const MaterialSet* matSet
if (flags.m_extendedShader == EExtendedShader::MorphBallShadow) {
/* Special matrices for MorphBall shadow rendering */
zeus::CMatrix4f texMtx = (zeus::CTransform::Scale(1.f / (flags.mbShadowBox.max - flags.mbShadowBox.min)) *
zeus::CTransform::Translate(-flags.mbShadowBox.min) * CGraphics::g_GXModelView)
zeus::CTransform::Translate(-flags.mbShadowBox.min) * CGraphics::g_GXModelMatrix)
.toMatrix4f();
for (const MaterialSet::Material& mat : matSet->materials) {
(void)mat;
......@@ -1007,7 +1022,7 @@ boo::ObjToken<boo::IGraphicsBufferD> CBooModel::UpdateUniformData(const CModelFl
} else if (flags.m_extendedShader == EExtendedShader::MorphBallShadow) /* MorphBall shadow render */
{
CModelShaders::MBShadowUniform& shadowOut = *reinterpret_cast<CModelShaders::MBShadowUniform*>(dataCur);
shadowOut.shadowUp = CGraphics::g_GXModelView * zeus::skUp;
shadowOut.shadowUp = CGraphics::g_GXModelView.rotate(zeus::skUp);
shadowOut.shadowUp.w() = flags.x4_color.a();
shadowOut.shadowId = flags.x4_color.r();
} else if (flags.m_extendedShader == EExtendedShader::Disintegrate) {
......
......@@ -119,10 +119,10 @@ void CFluidPlaneShader::Cache::Clear() {
p.reset();
}
void CFluidPlaneShader::PrepareBinding(const ShaderPair& pipeline, u32 maxVertCount) {
void CFluidPlaneShader::PrepareBinding(u32 maxVertCount) {
CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) {
m_vbo = ctx.newDynamicBuffer(boo::BufferUse::Vertex, sizeof(Vertex), maxVertCount);
if (pipeline.m_tessellation)
if (m_pipelines.m_tessellation)
m_pvbo = ctx.newDynamicBuffer(boo::BufferUse::Vertex, sizeof(PatchVertex), maxVertCount);
m_uniBuf = ctx.newDynamicBuffer(boo::BufferUse::Uniform, sizeof(Uniform), 1);
......@@ -147,12 +147,12 @@ void CFluidPlaneShader::PrepareBinding(const ShaderPair& pipeline, u32 maxVertCo
texs[texCount++] = m_envBumpMap->GetBooTexture();
if (m_lightmap)
texs[texCount++] = m_lightmap->GetBooTexture();
auto regular = ctx.newShaderDataBinding(pipeline.m_regular, m_vbo.get(), nullptr, nullptr, 3, ubufs, ubufStages,
auto regular = ctx.newShaderDataBinding(m_pipelines.m_regular, m_vbo.get(), nullptr, nullptr, 3, ubufs, ubufStages,
ubufOffs, ubufSizes, texCount, texs, nullptr, nullptr);
boo::ObjToken<boo::IShaderDataBinding> tessellation;
if (pipeline.m_tessellation) {
if (m_pipelines.m_tessellation) {
texs[texCount++] = m_rippleMap.get();
tessellation = ctx.newShaderDataBinding(pipeline.m_tessellation, m_pvbo.get(), nullptr, nullptr, 3, ubufs,
tessellation = ctx.newShaderDataBinding(m_pipelines.m_tessellation, m_pvbo.get(), nullptr, nullptr, 3, ubufs,
ubufStages, ubufOffs, ubufSizes, texCount, texs, nullptr, nullptr);
}
m_dataBind = {regular, tessellation};
......@@ -180,8 +180,8 @@ CFluidPlaneShader::CFluidPlaneShader(EFluidType type, const TLockedToken<CTextur
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);
ShaderPair pipeline = _cache.GetOrBuildShader(shaderInfo);
PrepareBinding(pipeline, maxVertCount);
m_pipelines = _cache.GetOrBuildShader(shaderInfo);
PrepareBinding(maxVertCount);
}
CFluidPlaneShader::CFluidPlaneShader(const TLockedToken<CTexture>& patternTex1,
......@@ -190,8 +190,8 @@ CFluidPlaneShader::CFluidPlaneShader(const TLockedToken<CTexture>& patternTex1,
: m_patternTex1(patternTex1), m_patternTex2(patternTex2), m_colorTex(colorTex) {
SFluidPlaneDoorShaderInfo shaderInfo(m_patternTex1.operator bool(), m_patternTex2.operator bool(),
m_colorTex.operator bool());
ShaderPair pipeline = _cache.GetOrBuildShader(shaderInfo);
PrepareBinding(pipeline, maxVertCount);
m_pipelines = _cache.GetOrBuildShader(shaderInfo);
PrepareBinding(maxVertCount);
}
void CFluidPlaneShader::prepareDraw(const RenderSetupInfo& info) {
......
......@@ -102,6 +102,7 @@ private:
boo::ObjToken<boo::IGraphicsBufferD> m_vbo;
boo::ObjToken<boo::IGraphicsBufferD> m_pvbo;
boo::ObjToken<boo::IGraphicsBufferD> m_uniBuf;
ShaderPair m_pipelines;
BindingPair m_dataBind;
int m_lastBind = -1;
......@@ -129,7 +130,7 @@ private:
template <class F>
static void _Shutdown();
void PrepareBinding(const ShaderPair& pipeline, u32 maxVertCount);
void PrepareBinding(u32 maxVertCount);
public:
CFluidPlaneShader(EFluidType type, const TLockedToken<CTexture>& patternTex1,
......@@ -158,6 +159,10 @@ public:
}
void doneDrawing() { m_lastBind = -1; }
void loadVerts(const std::vector<Vertex>& verts, const std::vector<PatchVertex>& pVerts);
bool isReady() const {
return m_pipelines.m_regular->isReady() &&
(!m_pipelines.m_tessellation || m_pipelines.m_tessellation->isReady());
}
static void Shutdown();
};
......
......@@ -339,6 +339,9 @@ CIOWin::EMessageReturn CMFGameLoader::OnMessage(const CArchitectureMessage& msg,
x1c_loadList.clear();
if (!CGraphics::g_BooFactory->areShadersReady())
return EMessageReturn::Exit;
wtMgr->StartTextFadeOut();
x2c_25_transitionFinished = wtMgr->IsTransitionFinished();
return EMessageReturn::Exit;
......
This diff is collapsed.
......@@ -9,23 +9,23 @@ class CPuddleToadGamma final : public CPatterned {
static constexpr std::string_view mMouthLocatorName = "MOUTH_LCTR_SDK"sv;
static constexpr std::string_view mBellyLocatorName = "SAMUS_POS_LCTR_SDK"sv;
static const zeus::CVector3f skBellyOffset;
u32 x568_ = 0;
float x56c_ = 0.f;
CDamageInfo x570_;
u32 x568_stateProg = 0;
float x56c_waitTimer = 0.f;
CDamageInfo x570_playerShootDamage;
CDamageInfo x58c_;
float x5a8_;
float x5ac_;
float x5b0_;
zeus::CVector3f x5b4_;
float x5c0_;
float x5c4_;
float x5c8_;
zeus::CVector3f x5cc_;
zeus::CVector3f x5d8_;
float x5a8_suckForceMultiplier;
float x5ac_minSuckAngleProj;
float x5b0_playerSuckRange;
zeus::CVector3f x5b4_localShootDir;
float x5c0_playerShootSpeed;
float x5c4_shouldAttackWaitTime;
float x5c8_spotPlayerWaitTime;
zeus::CVector3f x5cc_suckPoint;
zeus::CVector3f x5d8_damageablePoint;
std::unique_ptr<CCollidableOBBTreeGroup> x5e4_collisionTreePrim;
bool x5e8_24_ : 1;
bool x5e8_25_ : 1;
bool x5e8_26_ : 1;
bool x5e8_24_playerInside : 1;
bool x5e8_25_waitTimerActive : 1;
bool x5e8_26_shotPlayer : 1;
void SetSolid(CStateManager&, bool);
......@@ -40,8 +40,10 @@ public:
CPuddleToadGamma(TUniqueId uid, std::string_view name, EFlavorType flavor, const CEntityInfo& info,
const zeus::CTransform& xf, CModelData&& mData, const CPatternedInfo& pInfo,
const CActorParameters& aParms, float f1, float f2, float f3, const zeus::CVector3f& v1, float f4,
float f5, float f6, const CDamageInfo& dInfo1, const CDamageInfo& dInfo2, CAssetId dcln);
const CActorParameters& aParms, float suckForceMultiplier, float suckAngle, float playerSuckRange,
const zeus::CVector3f& localShootDir, float playerShootSpeed, float shouldAttackWaitTime,
float spotPlayerWaitTime, const CDamageInfo& playerShootDamage, const CDamageInfo& dInfo2,
CAssetId dcln);
void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&);
void Think(float dt, CStateManager& mgr);
......
......@@ -87,12 +87,12 @@ void CBomb::Think(float dt, urde::CStateManager& mgr) {
if (x190_24_isNotDetonated) {
if (x164_.magSquared() > 0.f)
x158_ += dt * x164_;
if (x164_acceleration.magSquared() > 0.f)
x158_velocity += dt * x164_acceleration;
if (x158_.magSquared() > 0.f) {
if (x158_velocity.magSquared() > 0.f) {
x170_prevLocation = GetTranslation();
CActor::SetTranslation((dt * x158_) + GetTranslation());
CActor::SetTranslation((dt * x158_velocity) + GetTranslation());
zeus::CVector3f diffVec = (GetTranslation() - x170_prevLocation);
float diffMag = diffVec.magnitude();
......
......@@ -8,8 +8,8 @@ namespace urde {
class CElementGen;
class CBomb : public CWeapon {
zeus::CVector3f x158_;
zeus::CVector3f x164_;
zeus::CVector3f x158_velocity;
zeus::CVector3f x164_acceleration;
zeus::CVector3f x170_prevLocation;
float x17c_fuseTime;
std::unique_ptr<CElementGen> x180_particle1;
......@@ -33,6 +33,8 @@ public:
void Explode(const zeus::CVector3f&, CStateManager&);
void UpdateLight(float, CStateManager&);
std::optional<zeus::CAABox> GetTouchBounds() const;
void SetVelocityWR(const zeus::CVector3f& vel) { x158_velocity = vel; }
void SetConstantAccelerationWR(const zeus::CVector3f& acc) { x164_acceleration = acc; }
};
} // namespace urde
......@@ -14,7 +14,6 @@
#include "CTimeProvider.hpp"
#include "Graphics/CSkinnedModel.hpp"
#include "hecl/CVarManager.hpp"
#include "zeus/CEulerAngles.hpp"
namespace urde {
static CMaterialList MakeActorMaterialList(const CMaterialList& materialList, const CActorParameters& params) {
......@@ -494,8 +493,6 @@ void CActor::SetTransform(const zeus::CTransform& tr) {
xe4_27_notInSortedLists = true;
xe4_28_transformDirty = true;
xe4_29_actorLightsDirty = true;
//if (TCastToPtr<MP1::CActorContraption>(this))
// printf("ACC %f\n", zeus::radToDeg(zeus::CEulerAngles(tr).z()));
}
void CActor::SetAddedToken(u32 tok) { xcc_addedToken = tok; }
......
......@@ -742,6 +742,9 @@ void CFluidPlaneCPU::Render(const CStateManager& mgr, float alpha, const zeus::C
TCastToConstPtr<CScriptWater> water = mgr.GetObjectById(waterId);
CFluidPlaneShader::RenderSetupInfo setupInfo = RenderSetup(mgr, alpha, xf, areaXf, aabb, water.GetPtr());
if (!m_shader->isReady())
return;
CFluidPlaneRender::NormalMode normalMode;
if (xb0_bumpMap && kEnableWaterBumpMaps)
normalMode = CFluidPlaneRender::NormalMode::NBT;
......
......@@ -63,6 +63,10 @@ void CFluidPlaneDoor::Render(const CStateManager& mgr, float alpha, const zeus::
const bool* gridFlags, u32 gridDimX, u32 gridDimY,
const zeus::CVector3f& areaCenter) const {
CFluidPlaneShader::RenderSetupInfo setupInfo = RenderSetup(mgr, alpha, xf, aabb, noNormals);
if (!m_shader->isReady())
return;
CFluidPlaneRender::numSubdivisionsInTile = xa4_tileSubdivisions;
CFluidPlaneRender::numTilesInHField = 42 / xa4_tileSubdivisions;
CFluidPlaneRender::numSubdivisionsInHField = CFluidPlaneRender::numTilesInHField * xa4_tileSubdivisions;
......
......@@ -996,6 +996,10 @@ void CGameArea::PostConstructArea() {
x12c_postConstructed->x10c0_areaObjs.reset(new CAreaObjectList(x4_selfIdx));
x12c_postConstructed->x10c4_areaFog.reset(new CAreaFog());
/* URDE addition: preemptively fill in area models so shaders may be polled for completion */
if (!x12c_postConstructed->x1108_25_modelsConstructed)
FillInStaticGeometry();
xf0_24_postConstructed = true;
/* Resolve layer pointers */
......@@ -1036,7 +1040,7 @@ void CGameArea::FillInStaticGeometry(bool textures) {
CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) {
/* Reserve extra buffers for 16 cubemaps and shadow rendering */
matSet.m_geomLayout->ReserveSharedBuffers(ctx, 98);
matSet.m_geomLayout->ReserveSharedBuffers(ctx, 96 + int(EWorldShadowMode::MAX));
/* Models */
for (CMetroidModelInstance& inst : x12c_postConstructed->x4c_insts) {
......
......@@ -118,6 +118,7 @@ void CMorphBallShadow::Render(const CStateManager& mgr, float alpha) {
CModelFlags flags;
flags.x4_color.a() = alpha;
flags.m_extendedShader = EExtendedShader::MorphBallShadow;
flags.mbShadowBox = xb8_shadowVolume;
int alphaVal = 4;
for (const CActor* actor : x0_actors) {
......
......@@ -258,7 +258,7 @@ public:
void Accept(IVisitor&);
void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&);
void PreThink(float, CStateManager& mgr) { CEntity::Think(x500_preThinkDt, mgr); }
void PreThink(float dt, CStateManager& mgr) { x500_preThinkDt = dt; CEntity::Think(x500_preThinkDt, mgr); }
void Think(float, CStateManager&);
void PreRender(CStateManager&, const zeus::CFrustum&);
void AddToRenderer(const zeus::CFrustum&, const CStateManager&) const;
......
#include "CPhysicsActor.hpp"
#include "TCastTo.hpp"
#include "MP1/World/CActorContraption.hpp"
#include "zeus/CEulerAngles.hpp"
namespace urde {
......@@ -93,10 +91,8 @@ void CPhysicsActor::AddMotionState(const CMotionState& mst) {
zeus::CNUQuaternion q{x34_transform.buildMatrix3f()};
q += mst.xc_orientation;
zeus::CQuaternion quat = zeus::CQuaternion::fromNUQuaternion(q);
//if (TCastToPtr<MP1::CActorContraption>(this)) {
// float a1 = zeus::radToDeg(zeus::CEulerAngles(zeus::CQuaternion(x34_transform.buildMatrix3f())).z());
// float a2 = zeus::radToDeg(zeus::CEulerAngles(quat).z());
// printf("ADD %f\n", a2 - a1);
//if (TCastToPtr<CPlayer>(this)) {
// printf("ADD %f %f %f\n", float(mst.x0_translation.x()), float(mst.x0_translation.y()), float(mst.x0_translation.z()));
//}
SetTransform(zeus::CTransform(quat, x34_transform.origin));
......
......@@ -5284,7 +5284,7 @@ void CPlayer::SetMorphBallState(EPlayerMorphBallState state, CStateManager& mgr)
}
bool CPlayer::CanLeaveMorphBallState(CStateManager& mgr, zeus::CVector3f& pos) const {
if (x768_morphball->IsProjectile() || !x590_ ||
if (x768_morphball->IsProjectile() || !x590_leaveMorphballAllowed ||
(IsUnderBetaMetroidAttack(mgr) && x2f8_morphBallState == EPlayerMorphBallState::Morphed))
return false;
if (!x9c4_28_canLeaveMorphBall)
......
......@@ -233,7 +233,7 @@ private:
int x584_ballTransitionAnim = -1;
float x588_alpha = 1.f;
float x58c_transitionVel = 0.f;
bool x590_ = true;
bool x590_leaveMorphballAllowed = true;
TReservedAverage<zeus::CTransform, 4> x594_transisionBeamXfs;
TReservedAverage<zeus::CTransform, 4> x658_transitionModelXfs;
TReservedAverage<float, 4> x71c_transitionModelAlphas;
......@@ -611,7 +611,7 @@ public:
EPlayerOrbitRequest GetOrbitRequest() const { return x30c_orbitRequest; }
bool IsShowingCrosshairs() const { return x9c4_25_showCrosshairs; }
bool IsSidewaysDashing() const { return x37c_sidewaysDashing; }
void Set_X590(bool b) { x590_ = b; }
void SetLeaveMorphBallAllowed(bool b) { x590_leaveMorphballAllowed = b; }
const zeus::CVector3f& GetOrbitPoint() const { return x314_orbitPoint; }
float GetAverageSpeed() const;
bool IsInWaterMovement() const { return x9c4_31_inWaterMovement; }
......
......@@ -81,16 +81,17 @@ void CScriptDoor::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStat
case EScriptObjectMessage::Action: {
if (x27c_partner1 != kInvalidUniqueId) {
if (TCastToPtr<CScriptDoor> door = mgr.ObjectById(x27c_partner1)) {
if (!x2a8_26_isOpen)
return;
x2a8_30_doClose = true;
mgr.SendScriptMsg(door, GetUniqueId(), EScriptObjectMessage::Close);
if (door->x2a8_26_isOpen) {
x2a8_30_doClose = true;
mgr.SendScriptMsg(door, GetUniqueId(), EScriptObjectMessage::Close);
door->x2a8_30_doClose = true;
}
}
} else if (x2a8_26_isOpen) {
x2a8_30_doClose = true;
if (TCastToPtr<CScriptDoor> door = mgr.ObjectById(x27e_partner2)) {
mgr.SendScriptMsg(door, GetUniqueId(), EScriptObjectMessage::Close);
x2a8_30_doClose = true;
door->x2a8_30_doClose = true;
}
x2a8_26_isOpen = false;
SetDoorAnimation(EDoorAnimType::Close);
......@@ -102,13 +103,14 @@ void CScriptDoor::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStat
if (!GetActive() || x2a8_26_isOpen)
return;
u32 doorCond = TCastToConstPtr<CScriptDoor>(mgr.GetObjectById(uid)) ? 2 : GetDoorOpenCondition(mgr);