feat(O-T4): extract ObjectMeshManager + mesh pipeline closure into AcDream.App.Rendering.Wb

Phase O Task 4: extract the WB mesh pipeline (ObjectMeshManager + 7 support files)
from references/WorldBuilder into src/AcDream.App/Rendering/Wb/ and bridge dat I/O
through our DatCollection via a thin DatCollectionAdapter.

O-D7 adapter path taken: ObjectMeshManager has 26 _dats.X call sites (threshold 20),
so a DatCollectionAdapter : IDatReaderWriter is introduced rather than refactoring
ObjectMeshManager's internal dat access directly.

Files added (verbatim copies, namespace-only changes):
- ObjectMeshManager.cs — mesh pipeline hub; IDatReaderWriter field satisfied by adapter
- GlobalMeshBuffer.cs — single global VAO/VBO/IBO manager
- EdgeLineBuilder.cs — wireframe edge geometry from CellStruct polygons
- ModernRenderData.cs — ModernBatchData + LandblockMdiCommand structs
- TextureAtlasManager.cs — texture array grouping by (Width, Height, Format)
- ParticleBatcher.cs — GPU particle batching; T4 interim uses BaseObjectRenderManager
  static fields from Chorizite.OpenGLSDLBackend.Lib (stays until T7)
- ParticleEmitterRenderer.cs — per-emitter particle lifecycle + rendering
- ActiveParticleEmitter.cs — wrapper holding renderer + part index + local offset
- DatCollectionAdapter.cs — NEW: bridges DatCollection → IDatReaderWriter; implements
  ResolveId() via DatDatabase.TypeFromId + Tree.TryGetFile in HighRes→Portal→Language→Cell
  order matching DefaultDatReaderWriter; DatDatabaseWrapper wraps DatDatabase as IDatDatabase

WbMeshAdapter.cs changes (T4 Step 6):
- _graphicsDevice switched from Chorizite.OpenGLSDLBackend.OpenGLGraphicsDevice to
  extracted AcDream.App.Rendering.Wb.OpenGLGraphicsDevice
- ParticleBatcher = new ParticleBatcher(_graphicsDevice) restored (T3 had null! placeholder)
- ObjectMeshManager now constructed with new DatCollectionAdapter(dats) instead of _wbDats
- _wbDats field + its construction + disposal + [indoor-upload] NULL_RESULT diagnostic block
  left intact — T7 cleanup removes these once WorldBuilder project ref is dropped

EmbeddedResourceReader.cs: replaced assembly manifest lookup (wrong prefix for our assembly)
with disk-based lookup mapping "Shaders.Particle.vert" → Rendering/Shaders/wb_particle.vert;
consistent with all other acdream shaders.

wb_particle.vert / wb_particle.frag: WB particle shaders copied verbatim with wb_ prefix
to distinguish from acdream's own particle.vert.

OpenGLGraphicsDevice.cs: ParticleBatcher property type updated to extracted ParticleBatcher;
setter changed from private to internal so WbMeshAdapter (same assembly) can assign post-ctor.

Build: green (0 errors, 0 warnings in AcDream.App).
Tests: 1147+8 baseline maintained (8 pre-existing failures unchanged).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Erik 2026-05-21 16:37:55 +02:00
parent 4cc38805b5
commit d16d8cd4e5
14 changed files with 3535 additions and 19 deletions

View file

@ -10,6 +10,7 @@ using DatReaderWriter.DBObjs;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using Silk.NET.OpenGL;
using WorldBuilder.Shared.Models;
using WorldBuilder.Shared.Services;
namespace AcDream.App.Rendering.Wb;
@ -28,9 +29,7 @@ namespace AcDream.App.Rendering.Wb;
/// </summary>
public sealed class WbMeshAdapter : IDisposable, IWbMeshAdapter
{
// T3 interim: ObjectMeshManager (T4-to-be-extracted) still expects the WB-original type.
// Will become AcDream.App.Rendering.Wb.OpenGLGraphicsDevice when T4 is done.
private readonly Chorizite.OpenGLSDLBackend.OpenGLGraphicsDevice? _graphicsDevice;
private readonly OpenGLGraphicsDevice? _graphicsDevice;
private readonly DefaultDatReaderWriter? _wbDats;
private readonly ObjectMeshManager? _meshManager;
private readonly DatCollection? _dats;
@ -75,9 +74,8 @@ public sealed class WbMeshAdapter : IDisposable, IWbMeshAdapter
ArgumentNullException.ThrowIfNull(logger);
_dats = dats;
// T3 interim: construct the WB-original device for ObjectMeshManager compatibility.
// Will swap to AcDream.App.Rendering.Wb.OpenGLGraphicsDevice when T4 extracts ObjectMeshManager.
_graphicsDevice = new Chorizite.OpenGLSDLBackend.OpenGLGraphicsDevice(gl, logger, new WorldBuilder.Shared.Models.DebugRenderSettings());
_graphicsDevice = new OpenGLGraphicsDevice(gl, logger, new DebugRenderSettings());
_graphicsDevice.ParticleBatcher = new ParticleBatcher(_graphicsDevice);
_wbDats = new DefaultDatReaderWriter(datDir);
// Phase 2 diagnostic — replace NullLogger with a Console-backed
// logger so WB's internal catch block at ObjectMeshManager.cs:589
@ -86,7 +84,7 @@ public sealed class WbMeshAdapter : IDisposable, IWbMeshAdapter
// so successful operations stay quiet.
_meshManager = new ObjectMeshManager(
_graphicsDevice,
_wbDats,
new DatCollectionAdapter(dats),
new ConsoleErrorLogger<ObjectMeshManager>());
}