diff --git a/src/AcDream.App/Rendering/GameWindow.cs b/src/AcDream.App/Rendering/GameWindow.cs index cb1e218..e5148f1 100644 --- a/src/AcDream.App/Rendering/GameWindow.cs +++ b/src/AcDream.App/Rendering/GameWindow.cs @@ -224,13 +224,15 @@ public sealed class GameWindow : IDisposable playerEntity.Position, pinitCellId & 0xFFFFu, System.Numerics.Vector3.Zero, 100f); // huge step height for initial snap _playerController.SetPosition(initResult.Position, initResult.CellId); - // Derive initial yaw from the entity's server-sent rotation - // rather than hardcoding. Extract yaw from the quaternion. + // Derive initial yaw from the entity's rotation. + // The render loop stores rotation as Yaw - PI/2 (to + // compensate for AC models facing +Y at identity), so + // we add PI/2 back when extracting to get the real yaw. var q = playerEntity.Rotation; - float yaw = MathF.Atan2( + float rawYaw = MathF.Atan2( 2f * (q.W * q.Z + q.X * q.Y), 1f - 2f * (q.Y * q.Y + q.Z * q.Z)); - _playerController.Yaw = yaw; + _playerController.Yaw = rawYaw + MathF.PI / 2f; _chaseCamera = new AcDream.App.Rendering.ChaseCamera { @@ -1756,7 +1758,7 @@ public sealed class GameWindow : IDisposable { var camera = _cameraController.Active; var frustum = AcDream.App.Rendering.FrustumPlanes.FromViewProjection(camera.View * camera.Projection); - _terrain?.Draw(camera, frustum); + // Never cull the landblock the player is currently on. uint? playerLb = null; if (_playerMode && _playerController is not null) @@ -1766,6 +1768,7 @@ public sealed class GameWindow : IDisposable int ply = _liveCenterY + (int)System.Math.Floor(pp.Y / 192f); playerLb = (uint)((plx << 24) | (ply << 16) | 0xFFFF); } + _terrain?.Draw(camera, frustum, neverCullLandblockId: playerLb); _staticMesh?.Draw(camera, _worldState.LandblockEntries, frustum, neverCullLandblockId: playerLb); diff --git a/src/AcDream.App/Rendering/TerrainRenderer.cs b/src/AcDream.App/Rendering/TerrainRenderer.cs index 6c62b76..2705a60 100644 --- a/src/AcDream.App/Rendering/TerrainRenderer.cs +++ b/src/AcDream.App/Rendering/TerrainRenderer.cs @@ -116,7 +116,7 @@ public sealed unsafe class TerrainRenderer : IDisposable _landblocks.Remove(landblockId); } - public void Draw(ICamera camera, FrustumPlanes? frustum = null) + public void Draw(ICamera camera, FrustumPlanes? frustum = null, uint? neverCullLandblockId = null) { _shader.Use(); _shader.SetMatrix4("uView", camera.View); @@ -135,7 +135,7 @@ public sealed unsafe class TerrainRenderer : IDisposable foreach (var lb in _landblocks.Values) { - if (frustum is not null) + if (frustum is not null && lb.LandblockId != neverCullLandblockId) { var aabbMin = new Vector3(lb.WorldOrigin.X, lb.WorldOrigin.Y, lb.MinZ); var aabbMax = new Vector3(lb.WorldOrigin.X + 192f, lb.WorldOrigin.Y + 192f, lb.MaxZ);