Skip to content

fix(view): Change setup of default camera pitch and angle#2546

Open
xezon wants to merge 2 commits intoTheSuperHackers:mainfrom
xezon:xezon/fix-camera-pitch-angle
Open

fix(view): Change setup of default camera pitch and angle#2546
xezon wants to merge 2 commits intoTheSuperHackers:mainfrom
xezon:xezon/fix-camera-pitch-angle

Conversation

@xezon
Copy link
Copy Markdown

@xezon xezon commented Apr 7, 2026

This change decouples the default camera pitch and angle from the camera origin point. The default pitch can be changed with a debug key mapping.

Previously, the user pitch started at 0 which actually refers to a real pitch of 37.5 because that is what TheGlobalData->m_cameraPitch is set to.

TODO

  • Replicate in Generals

@xezon xezon added this to the Camera Improvements milestone Apr 7, 2026
@xezon xezon added Minor Severity: Minor < Major < Critical < Blocker Gen Relates to Generals ZH Relates to Zero Hour Fix Is fixing something, but is not user facing labels Apr 7, 2026
// TheSuperHackers @tweak To preserve the original scripted camera values, offset them by default ones.
constexpr const Real DefaultPitch = DEG_TO_RADF(37.5f);
constexpr const Real DefaultAngle = DEG_TO_RADF(0.0f);
pitch = -pitch + DefaultPitch;
Copy link
Copy Markdown
Author

@xezon xezon Apr 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

-pitch because we changed the axis direction of pitch in a earlier change.

I did not get to test this function however, because I did not find a cutscene where this is called.

@greptile-apps
Copy link
Copy Markdown

greptile-apps bot commented Apr 7, 2026

Greptile Summary

This PR decouples the default camera pitch and angle from the hardcoded origin constants in buildCameraPosition. View::init() now seeds m_defaultPitch/m_defaultAngle from TheGlobalData instead of zero, so the user's pitch value is now an absolute angle rather than a delta from the global default. A debug key binding (Ctrl+Comma) is added to interactively adjust the default pitch at runtime, and a PRESERVE_RETAIL_SCRIPTED_CAMERA guard in doCameraSetDefault back-computes the legacy script pitch convention for compatibility.

Confidence Score: 5/5

Safe to merge; only P2 style findings remain

The logic of decoupling default pitch/angle from the hardcoded camera-origin constants is sound. The buildCameraPosition math is internally consistent (base at 37.5°, rotation applied as delta). The debug-only key binding is properly guarded by RTS_DEBUG. The PRESERVE_RETAIL_SCRIPTED_CAMERA compatibility path is correct. Remaining findings are dead-code style issues that do not affect runtime behaviour.

Core/GameEngine/Source/GameClient/View.cpp — #if 1 dead-code guards in setPitch / setDefaultPitch

Important Files Changed

Filename Overview
Core/GameEngine/Source/GameClient/View.cpp Initializes m_defaultAngle/m_defaultPitch from GlobalData instead of 0; adds setDefaultPitch with #if 1 dead-code guard that should be cleaned up
Core/GameEngine/Include/GameClient/View.h Adds getDefaultAngle, setDefaultPitch, getDefaultPitch virtuals and userSetDefaultPitch helper; straightforward interface additions
Core/GameEngineDevice/Source/W3DDevice/GameClient/W3DView.cpp buildCameraPosition now uses local constexpr DefaultPitch/DefaultAngle (37.5°/0°) instead of TheGlobalData values; adds W3DView::setDefaultPitch with proper constraint invalidation
GeneralsMD/Code/GameEngine/Source/GameLogic/ScriptEngine/ScriptActions.cpp Adds PRESERVE_RETAIL_SCRIPTED_CAMERA guard that back-computes pitch offset; angle adjustment is a no-op (DefaultAngle = 0)
GeneralsMD/Code/GameEngine/Source/GameClient/MessageStream/LookAtXlat.cpp Adds debug-only MSG_META_DEMO_BEGIN/END_ADJUST_DEFAULTPITCH handling; adjusts default pitch + syncs current pitch to default on each mouse move frame
GeneralsMD/Code/GameEngine/Include/GameClient/LookAtXlat.h Adds m_isDefaultPitching bool member; clean addition
GeneralsMD/Code/GameEngine/Include/Common/MessageStream.h Adds MSG_META_DEMO_BEGIN/END_ADJUST_DEFAULTPITCH enum values; straightforward addition
GeneralsMD/Code/GameEngine/Source/Common/MessageStream.cpp Adds string-to-enum mapping entries for the two new meta messages; no issues
GeneralsMD/Code/GameEngine/Source/GameClient/MessageStream/MetaEvent.cpp Registers Ctrl+Comma key binding for default-pitch adjustment in debug builds; bindings are guarded by RTS_DEBUG
GeneralsMD/Code/GameEngine/Source/GameClient/InGameUI.cpp Propagates m_isDefaultPitching initialization; minor addition
Core/GameEngineDevice/Include/W3DDevice/GameClient/W3DView.h Declares W3DView::setDefaultPitch override; clean addition

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A["View::init()"] -->|"m_defaultPitch = DEG_TO_RADF(GlobalData.cameraPitch)"| B["m_defaultPitch set"]
    B --> C["W3DView::reset()"]
    C -->|"setPitchToDefault()"| D["m_pitch = m_defaultPitch"]

    E["Debug: Ctrl+Comma held\n(MSG_META_DEMO_BEGIN_ADJUST_DEFAULTPITCH)"] --> F["LookAtTranslator:\nm_isDefaultPitching = true"]
    F --> G["Mouse Y delta x 0.01\n-> userSetDefaultPitch()"]
    G --> H["setDefaultPitch()\n-> m_defaultPitch clamped 0.1 to 89.9 deg"]
    H --> I["userSetPitchToDefault()\n-> m_pitch = m_defaultPitch"]

    J["W3DView::buildCameraPosition()"] -->|"const DefaultPitch = 37.5 deg"| K["Compute sourcePos base\n@ fixed 37.5 deg"]
    K --> L["pitchTransform = m_pitch - 37.5 deg\nangleTransform = m_angle - 0 deg"]
    L --> M["Rotate sourcePos\n-> final camera position"]

    N["ScriptActions::doCameraSetDefault(pitch, angle)"] -->|"PRESERVE_RETAIL_SCRIPTED_CAMERA"| O["pitch = -pitch + 37.5 deg\nangle = angle + 0 deg"]
    O --> P["TheTacticalView->setDefaultView(pitch, angle, maxHeight)"]
Loading
Prompt To Fix All With AI
This is a comment left during a code review.
Path: Core/GameEngine/Source/GameClient/View.cpp
Line: 168-181

Comment:
**Dead code left by `#if 1` guard**

Both `setPitch` and `setDefaultPitch` use an `#if 1 / #else / #endif` toggle, making the `#else` branch (`WWMath::Normalize_Angle`) permanently unreachable dead code. This pattern is typically a temporary WIP device; the disabled branch should be removed before merging to keep the codebase clean.

```suggestion
	m_pitch = clamp(DEG_TO_RADF(0.1f), radians, DEG_TO_RADF(89.9f));
```

And similarly for `setDefaultPitch`:
```cpp
void View::setDefaultPitch( Real radians )
{
	m_defaultPitch = clamp(DEG_TO_RADF(0.1f), radians, DEG_TO_RADF(89.9f));
}
```

How can I resolve this? If you propose a fix, please make it concise.

---

This is a comment left during a code review.
Path: GeneralsMD/Code/GameEngine/Source/GameLogic/ScriptEngine/ScriptActions.cpp
Line: 4611

Comment:
**No-op `angle` adjustment**

`DefaultAngle = DEG_TO_RADF(0.0f)`, so `angle = angle + DefaultAngle` is always `angle = angle + 0`, making this line a no-op. If the intent is symmetric with the pitch offset (to show that angle could also be shifted by a default), that should be commented explicitly; otherwise the line can be removed.

How can I resolve this? If you propose a fix, please make it concise.

Reviews (2): Last reviewed commit: "Revert init" | Re-trigger Greptile

{
map->m_key = MK_COMMA;
map->m_transition = UP;
map->m_modState = CTRL;
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This does not work reliably. When releasing CTRL before Comma, then this action will not trigger. Maybe can be fixed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Fix Is fixing something, but is not user facing Gen Relates to Generals Minor Severity: Minor < Major < Critical < Blocker ZH Relates to Zero Hour

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant