fix(app): scale order for live entities + FlyCamera speed tune (Phase 5c-fix)
User-reported visuals after Phase 5c ObjScale landed:
- Nullified Statue is bigger but "distorted" and half-sunken into the
foundry
- WASD/Space/Ctrl camera speed too fast
Fixes:
1. Scale multiplication order. Phase 5c used `scaleMat * PartTransform`,
which in C# row-vector Matrix4x4 semantics means "scale first (in
mesh-local space), then apply PartTransform." For multi-part meshes
where each part has an attachment translation, this scales the mesh
but leaves the attachment offset un-scaled — so child parts drift
relative to each other and the base anchor ends up below the ground.
Offline scenery hydration has always used the opposite order:
`PartTransform * scaleMat`, meaning "transform first, then scale the
resulting position." Matching that order fixes both distortion and
sinking in one change, and makes live entities consistent with
scenery's proven path.
2. FlyCamera.MoveSpeed 100 → 35. 100 world units/sec is ~half a landblock
per second at AC scale — fine for terrain-scouting but too aggressive
for inspecting specific entities like the foundry statue. 35 is a
little faster than walk pace and feels right for visual iteration.
This commit is contained in:
parent
f67f7851e6
commit
e4a5b8a51a
2 changed files with 11 additions and 4 deletions
|
|
@ -11,7 +11,7 @@ public sealed class FlyCamera : ICamera
|
|||
public float FovY { get; set; } = MathF.PI / 3f;
|
||||
public float Aspect { get; set; } = 16f / 9f;
|
||||
|
||||
public float MoveSpeed { get; set; } = 100f; // world units per second
|
||||
public float MoveSpeed { get; set; } = 35f; // world units per second (AC cell size = 24)
|
||||
public float MouseSensitivity { get; set; } = 0.003f;
|
||||
|
||||
private const float PitchLimit = 1.5533f; // ~89 degrees
|
||||
|
|
|
|||
|
|
@ -705,9 +705,16 @@ public sealed class GameWindow : IDisposable
|
|||
if (resolvedOverridesByPart is not null && resolvedOverridesByPart.TryGetValue(partIdx, out var partOverrides))
|
||||
surfaceOverrides = partOverrides;
|
||||
|
||||
// Pre-multiply scale so it happens FIRST (local mesh coords) before
|
||||
// the part-local transform and the entity-root transform.
|
||||
var transform = scale == 1.0f ? mr.PartTransform : scaleMat * mr.PartTransform;
|
||||
// Multiplication order matches offline scenery hydration:
|
||||
// `PartTransform * scaleMat`. In row-vector semantics this means
|
||||
// "apply PartTransform first (which includes the part-attachment
|
||||
// translation), then scale in the resulting space." Using the
|
||||
// opposite order (`scaleMat * PartTransform`) scales in mesh-local
|
||||
// space first, which leaves the part-attachment offset unscaled —
|
||||
// for multi-part entities like the Nullified Statue that causes
|
||||
// the parts to drift relative to each other ("distorted") and the
|
||||
// base anchor to end up below the ground ("sinks into foundry").
|
||||
var transform = scale == 1.0f ? mr.PartTransform : mr.PartTransform * scaleMat;
|
||||
|
||||
meshRefs.Add(new AcDream.Core.World.MeshRef(mr.GfxObjId, transform)
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue