Skip to content

Add authored rotation to audio emitters + directional stretch audio#7

Open
ccp-zoetrope wants to merge 4 commits into
mainfrom
audemitter-rotation
Open

Add authored rotation to audio emitters + directional stretch audio#7
ccp-zoetrope wants to merge 4 commits into
mainfrom
audemitter-rotation

Conversation

@ccp-zoetrope

Copy link
Copy Markdown
Member

Today an emitter can only face whatever direction its parent placement supplies. There's no way for a designer to aim an emitter relative to its parent which matters for sounds that utilize cone attenuation. This PR adds an authored orientation offset, plus visualization and allows stretch audio to utilize this.

What this PR adds

Authored rotation on emitters

A new editable rotation field (quaternion) applied on top of the parent placement's orientation. The parent still drives position and base facing; the authored rotation then steers the emitter further. Identity (the default) is a no-op, so existing content is unaffected.

  • Blue attribute rotation on the AudEmitter blue interface.
  • Read-only front / top properties reporting the effective orientation sent to Wwise after the rotation is applied

Directional stretch audio

StretchAudio emitters now face the direction the stretch points by default.

Emitter direction debug view

A new "Audio Emitter Direction" debug toggle draws a distance-scaled arrow along each emitter's effective front vector. Debug rendering is organized into three independent passes (attenuation sphere, direction arrow, name label) behind a single culled/enabled guard.

image

How orientation resolves

Placement is applied in two explicit stages so it's clear where the authored rotation enters:

  1. SetPlacementFromParent(front, top, position) records the parent's orientation.
  2. That orientation is rotated by the authored quaternion into an effective orientation, which ApplyEffectivePlacement orthonormalizes and pushes to Wwise (with the usual RH→LH conversion).

API / behavior changes vs. current

  • Blue method rename: emitters now expose SetPlacement(front, top, position) where they previously exposed SetPosition. This is deliberate because an emitter shouldn't offer a transform-style SetPosition, since its position comes from the parent placement. The listener keeps SetPosition unchanged since it is actively used client code at the moment.
  • Default emitter facing is now front=(0,0,1) where it used to be (1,0,0), matching the placement convention used elsewhere.

Testing

  • Expanded test_audemitter_exposure.py to cover the new rotation and placement behavior.
  • Verified in-client: authored emitter rotation, the direction arrow, and stretch-audio direction behave as expected.

ccp-zoetrope and others added 4 commits July 8, 2026 15:48
…ering

* Allow AudEmitter instances to carry an authored local rotation that is applied on top of their parent/source placement. Store parent orientation separately from the effective Wwise orientation so repeated placement updates do not compound rotation, and preserve the effective orientation across wake for sound prioritization.
* Expose emitter placement in Blue/Python as SetPlacement because Graphite automatically introspects whether an object has a SetEmitter method and causes errors when rotating that object.
* Add ability to show the direction an audio emitter is pointing using a separate debug rendering option called "Audio Emitter Direction".
* Refactor debug rendering for audio emitter's to allow for toggling multiple types of rendering options.
* Remove clickable radius from audio emitter debug rendering because it never really fulfilled it's intended purpose and just made things look uglier and more confusing..
* Add tests to cover rotation and SetPlacement.

Testing:
* Tested in Graphite and client on a scanning effect that was the original catalyst for this change to begin with.
* Made sure that the engine audio emitter was continuing to point the correct direction as it has always been the only audio emitter in Frontier/EVE that has had cone attenuation to begin with.
* I verified that no python code actually called "SetPosition" in the first place so changing to SetPlacement will not cause unintended consequences. The only place in python that uses SetPosition is the Listener which defines its own function for this anyway.

https://fenriscreations.atlassian.net/browse/EF-14176

Co-authored-by: Copilot <copilot@github.com>
Use the current source-to-destination vector for StretchAudio emitter placement
instead of always using a fixed orientation. This keeps authored emitter rotation
as a local offset from the actual stretch direction.

Also let authored emitter rotation update before parent placement arrives.

This particular commit fixes https://fenriscreations.atlassian.net/browse/EF-14176 and the previous commit did not fully fix this because StretchAudio needed to be updated to update rotation in relation to the world transform of the effect while in the client.
Follow-up cleanup on the authored-emitter-rotation work. No behavior
change.

- Rename SetPositionHelper -> SetPlacementFromParent and SetEffectivePositionHelper -> ApplyEffectivePlacement to make the "record parent orientation, resolve authored rotation, apply" split read clearly. AudListener and its Blue exposure follow the rename.
- Replace hand-rolled quaternion normalization and rotation with the canonical carbon-math helpers (Normalize, IdentityQuaternion, XMVector3Rotate)
- Extract AudGameObjResource::Orthonormalize() and share it between the emitter base and the listener, removing the duplicated orientation normalization of geometry that previously lived in both paths.
- Name the debug-render tuning values as locally scoped constexpr instead of inline literals.
@ccp-zoetrope ccp-zoetrope requested a review from phevosccp July 9, 2026 11:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant