Skip to content

Commit edd7bff

Browse files
Decouple the calculations of TurretOffset and HeightShadowScaling (#2137)
When drawing the shadow of an airborne unit, TurretOffset is applied to a transformation matrix that has already been scaled for height, causing the turret shadow's offset to be scaled as well and resulting in a misalignment with the actual turret image position. > [!Note] > Example reproduction steps: > 1. Duplicate a `[DISK]` unit > - It flies in the air while its shadow is on the ground, making it easy to observe. > 2. Set `ShadowIndex=-1` on both to hide the body shadow > - Leaving only the turret shadow visible for clarity. > 3. Apply a `TurretOffset` to one of them to displace the turret by a certain distance > - Preferably a multiple of cell distance, e.g., `512` leptons as in the image below. > 4. Place both units at the same altitude and separate them horizontally by the same amount as the `TurretOffset` value. Check if the two turret shadows overlap. Before: ![Shadow](https://github.com/user-attachments/assets/1f1f9af4-4c2b-4997-894b-5fe0d55adb0c) After: ![Fixed](https://github.com/user-attachments/assets/03ec4bf1-8762-4e2f-a2a4-56eb19d01f02)
1 parent de1819a commit edd7bff

3 files changed

Lines changed: 26 additions & 12 deletions

File tree

docs/Whats-New.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -652,6 +652,7 @@ Phobos fixes:
652652
- `RealTimeTimers` now support independent gamespeed index values for Multiplayer and Skirmish (by RAZER)
653653
- Fixed the bug that the upgrade building's power-enhancing effect depends only on its parent building and is not related to the upgrade building itself (by NetsuNegi)
654654
- Fixed an issue where hover vehicles could not be destroyed after malfunctioning on water surfaces (by FlyStar)
655+
- Fixed an issue where shadow matrix scaling was incorrectly applied to `TurretOffset` causing turret shadow misplacement (by Noble_Fish)
655656
656657
Fixes / interactions with other extensions:
657658
<!-- - Allowed `AuxBuilding` and Ares' `SW.Aux/NegBuildings` to count building upgrades (by Ollerus) -->

docs/locale/zh_CN/LC_MESSAGES/Whats-New.po

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2263,6 +2263,12 @@ msgid ""
22632263
"malfunctioning on water surfaces (by FlyStar)"
22642264
msgstr "修复了悬浮载具在水面上失灵后无法被摧毁的问题(by FlyStar)"
22652265

2266+
msgid ""
2267+
"Fixed an issue where shadow matrix scaling was incorrectly applied to "
2268+
"`TurretOffset` causing turret shadow misplacement (by Noble_Fish)"
2269+
msgstr ""
2270+
"修复了一个影子矩阵缩放错误地应用于 `TurretOffset` 而导致炮塔影子错位的问题(by Noble_Fish)"
2271+
22662272
msgid "Fixes / interactions with other extensions:"
22672273
msgstr "其他扩展引擎相关的修复/交互:"
22682274

src/Ext/TechnoType/Hooks.MatrixOp.cpp

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -273,7 +273,7 @@ DEFINE_HOOK(0x4CF68D, FlyLocomotionClass_DrawMatrix_OnAirport, 0x5)
273273
mat = Matrix3D::VoxelRampMatrix[slope_idx] * mat;
274274
const float ars = pThis->AngleRotatedSideways;
275275
const float arf = pThis->AngleRotatedForwards;
276-
if (std::abs(ars) > 0.005 || std::abs(arf) > 0.005)
276+
if (std::abs(ars) > 0.005f || std::abs(arf) > 0.005f)
277277
{
278278
const auto pType = pThis->Type;
279279
mat.TranslateZ(float(std::abs(Math::sin(ars)) * pType->VoxelScaleX
@@ -315,7 +315,7 @@ static Matrix3D* __stdcall JumpjetLocomotionClass_Draw_Matrix(ILocomotion* iloco
315315
size_t arfFace = 0;
316316
size_t arsFace = 0;
317317

318-
if (std::abs(ars) >= 0.005 || std::abs(arf) >= 0.005)
318+
if (std::abs(ars) >= 0.005f || std::abs(arf) >= 0.005f)
319319
{
320320
if (key)
321321
key->Base.Invalidate();
@@ -447,7 +447,7 @@ static Matrix3D* __stdcall TeleportLocomotionClass_Draw_Matrix(ILocomotion* iloc
447447
const float arf = linked->AngleRotatedForwards;
448448
const float ars = linked->AngleRotatedSideways;
449449

450-
if (std::abs(ars) >= 0.005 || std::abs(arf) >= 0.005)
450+
if (std::abs(ars) >= 0.005f || std::abs(arf) >= 0.005f)
451451
{
452452
if (pIndex)
453453
pIndex->Invalidate();
@@ -564,6 +564,8 @@ DEFINE_HOOK(0x73C47A, UnitClass_DrawAsVXL_Shadow, 0x5)
564564
const auto height = pThis->GetHeight();
565565
const double baseScale_log = RulesExt::Global()->AirShadowBaseScale_log;
566566

567+
double currentScale = 1.0;
568+
567569
if (RulesExt::Global()->HeightShadowScaling && height > 0)
568570
{
569571
const double minScale = RulesExt::Global()->HeightShadowScaling_MinScale;
@@ -573,7 +575,8 @@ DEFINE_HOOK(0x73C47A, UnitClass_DrawAsVXL_Shadow, 0x5)
573575

574576
if (cHeight > 0)
575577
{
576-
shadowMatrix.Scale((float)std::max(Pade2_2(baseScale_log * height / cHeight), minScale));
578+
currentScale = std::max(Pade2_2(baseScale_log * height / cHeight), minScale);
579+
shadowMatrix.Scale((float)currentScale);
577580

578581
if (jjloco->State != JumpjetLocomotionClass::State::Hovering)
579582
vxlIndexKey.Invalidate();
@@ -585,14 +588,16 @@ DEFINE_HOOK(0x73C47A, UnitClass_DrawAsVXL_Shadow, 0x5)
585588

586589
if (cHeight > 0 && height > 208)
587590
{
588-
shadowMatrix.Scale((float)std::max(Pade2_2(baseScale_log * (height - 208) / cHeight), minScale));
591+
currentScale = std::max(Pade2_2(baseScale_log * (height - 208) / cHeight), minScale);
592+
shadowMatrix.Scale((float)currentScale);
589593
vxlIndexKey.Invalidate();
590594
}
591595
}
592596
}
593597
else if (!RulesExt::Global()->HeightShadowScaling && pThis->Type->ConsideredAircraft)
594598
{
595-
shadowMatrix.Scale((float)Pade2_2(baseScale_log));
599+
currentScale = Pade2_2(baseScale_log);
600+
shadowMatrix.Scale((float)currentScale);
596601
}
597602

598603
auto GetMainVoxel = [&]()
@@ -617,7 +622,7 @@ DEFINE_HOOK(0x73C47A, UnitClass_DrawAsVXL_Shadow, 0x5)
617622
float arf = pThis->AngleRotatedForwards;
618623
float ars = pThis->AngleRotatedSideways;
619624
// lazy, don't want to hook inside Shadow_Matrix
620-
if (std::abs(ars) >= 0.005 || std::abs(arf) >= 0.005)
625+
if (std::abs(ars) >= 0.005f || std::abs(arf) >= 0.005f)
621626
{
622627
// index key should have been already invalid, so it won't hurt to invalidate again
623628
vxlIndexKey.Invalidate();
@@ -652,7 +657,7 @@ DEFINE_HOOK(0x73C47A, UnitClass_DrawAsVXL_Shadow, 0x5)
652657
* JumpjetTiltReference::SidewaysBaseTilt), -JumpjetTiltReference::MaxTilt, JumpjetTiltReference::MaxTilt);
653658
}
654659

655-
if (std::abs(ars) >= 0.005 || std::abs(arf) >= 0.005)
660+
if (std::abs(ars) >= 0.005f || std::abs(arf) >= 0.005f)
656661
{
657662
vxlIndexKey.Invalidate();
658663
shadowMatrix.RotateX(ars);
@@ -742,7 +747,8 @@ DEFINE_HOOK(0x73C47A, UnitClass_DrawAsVXL_Shadow, 0x5)
742747
return nullptr;
743748
};
744749

745-
pDrawTypeExt->ApplyTurretOffset(&mtx, Pixel_Per_Lepton);
750+
const double adjustedFactor = Pixel_Per_Lepton / currentScale;
751+
pDrawTypeExt->ApplyTurretOffset(&mtx, adjustedFactor);
746752
mtx.RotateZ(static_cast<float>(pThis->SecondaryFacing.Current().GetRadian<32>() - pThis->PrimaryFacing.Current().GetRadian<32>()));
747753

748754
const bool inRecoil = pDrawType->TurretRecoil && pThis->TurretRecoil.State != RecoilData::RecoilState::Inactive;
@@ -854,12 +860,13 @@ DEFINE_HOOK(0x4147F9, AircraftClass_Draw_Shadow, 0x6)
854860
double arf = pThis->AngleRotatedForwards;
855861
if (flyLoco->CurrentSpeed > pAircraftType->PitchSpeed)
856862
arf += pAircraftType->PitchAngle;
857-
float ars = pThis->AngleRotatedSideways;
858-
if (key.Is_Valid_Key() && (std::abs(arf) > 0.005 || std::abs(ars) > 0.005))
863+
const float newArf = (float)arf;
864+
const float ars = pThis->AngleRotatedSideways;
865+
if (key.Is_Valid_Key() && (std::abs(newArf) > 0.005f || std::abs(ars) > 0.005f))
859866
key.Invalidate();
860867

861868
shadow_mtx.RotateX(ars);
862-
shadow_mtx.RotateY((float)arf);
869+
shadow_mtx.RotateY(newArf);
863870
}
864871
else if (height > 0)
865872
{

0 commit comments

Comments
 (0)