refactor(pipeline): MP1a - ObjectMeshData family moved to AcDream.Content
This commit is contained in:
parent
d778930853
commit
e3376d4734
5 changed files with 135 additions and 112 deletions
|
|
@ -1,3 +1,4 @@
|
||||||
|
using AcDream.Content;
|
||||||
using Chorizite.Core.Render.Enums;
|
using Chorizite.Core.Render.Enums;
|
||||||
using Silk.NET.OpenGL;
|
using Silk.NET.OpenGL;
|
||||||
using System;
|
using System;
|
||||||
|
|
|
||||||
|
|
@ -26,118 +26,6 @@ using SixLabors.ImageSharp;
|
||||||
using SixLabors.ImageSharp.PixelFormats;
|
using SixLabors.ImageSharp.PixelFormats;
|
||||||
|
|
||||||
namespace AcDream.App.Rendering.Wb {
|
namespace AcDream.App.Rendering.Wb {
|
||||||
/// <summary>
|
|
||||||
/// Vertex format for scenery mesh rendering: position, normal, UV.
|
|
||||||
/// </summary>
|
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
|
||||||
public struct VertexPositionNormalTexture {
|
|
||||||
public Vector3 Position;
|
|
||||||
public Vector3 Normal;
|
|
||||||
public Vector2 UV;
|
|
||||||
|
|
||||||
public static int Size => 8 * sizeof(float); // 3+3+2 = 8 floats = 32 bytes
|
|
||||||
|
|
||||||
public VertexPositionNormalTexture(Vector3 position, Vector3 normal, Vector2 uv) {
|
|
||||||
Position = position;
|
|
||||||
Normal = normal;
|
|
||||||
UV = uv;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Staged data for a particle emitter to be created on the GL thread.
|
|
||||||
/// </summary>
|
|
||||||
public struct StagedEmitter {
|
|
||||||
public ParticleEmitter Emitter;
|
|
||||||
public uint PartIndex;
|
|
||||||
public Matrix4x4 Offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// CPU-side mesh data prepared on a background thread.
|
|
||||||
/// Contains vertex data and per-batch index/texture info, but NO GPU resources.
|
|
||||||
/// </summary>
|
|
||||||
public class ObjectMeshData {
|
|
||||||
public ulong ObjectId { get; set; }
|
|
||||||
public bool IsSetup { get; set; }
|
|
||||||
public VertexPositionNormalTexture[] Vertices { get; set; } = Array.Empty<VertexPositionNormalTexture>();
|
|
||||||
public List<MeshBatchData> Batches { get; set; } = new();
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// #125 (2026-06-12): GL upload-retry counter. A failed
|
|
||||||
/// <see cref="ObjectMeshManager.UploadMeshData"/> (returns null from its
|
|
||||||
/// catch) used to be dropped permanently — the staged item was consumed,
|
|
||||||
/// no render data was produced, and the prepared data lingered in the CPU
|
|
||||||
/// cache where <c>PrepareMeshDataAsync</c>'s cache-hit short-circuit
|
|
||||||
/// returned it without ever re-staging it for upload (session-sticky
|
|
||||||
/// invisible mesh, one [wb-error] line). The drain loop now re-stages a
|
|
||||||
/// failed upload for the NEXT frame up to <see cref="ObjectMeshManager.
|
|
||||||
/// MaxUploadRetries"/> times. The counter lives on the mesh-data object so
|
|
||||||
/// it resets to 0 naturally whenever the id is re-prepared (fresh object),
|
|
||||||
/// and bounds a deterministic GL failure to a few loud lines instead of a
|
|
||||||
/// silent permanent drop OR an unbounded per-frame retry storm. Retail
|
|
||||||
/// loads content synchronously and has no such failure mode — this
|
|
||||||
/// converges our async pipeline toward that guarantee.
|
|
||||||
/// </summary>
|
|
||||||
public int UploadAttempts;
|
|
||||||
|
|
||||||
/// <summary>For EnvCell: the geometry of the cell itself.</summary>
|
|
||||||
public ObjectMeshData? EnvCellGeometry { get; set; }
|
|
||||||
|
|
||||||
/// <summary>For Setup objects: parts with their local transforms.</summary>
|
|
||||||
public List<(ulong GfxObjId, Matrix4x4 Transform)> SetupParts { get; set; } = new();
|
|
||||||
|
|
||||||
/// <summary>Particle emitters from physics scripts.</summary>
|
|
||||||
public List<StagedEmitter> ParticleEmitters { get; set; } = new();
|
|
||||||
|
|
||||||
/// <summary>Per-format texture atlas data (to be uploaded to GPU on main thread).</summary>
|
|
||||||
public Dictionary<(int Width, int Height, TextureFormat Format), List<TextureBatchData>> TextureBatches { get; set; } = new();
|
|
||||||
|
|
||||||
/// <summary>Local bounding box.</summary>
|
|
||||||
public BoundingBox BoundingBox { get; set; }
|
|
||||||
|
|
||||||
/// <summary>Approximate center point used for depth sorting / transparency ordering.</summary>
|
|
||||||
public Vector3 SortCenter { get; set; }
|
|
||||||
|
|
||||||
/// <summary>DataID of a simpler GfxObj to use at long distance / low quality, or GfxObjDegradeInfo.</summary>
|
|
||||||
public uint DIDDegrade { get; set; }
|
|
||||||
|
|
||||||
/// <summary>Sphere used for mouse selection.</summary>
|
|
||||||
public Sphere? SelectionSphere { get; set; }
|
|
||||||
|
|
||||||
/// <summary>Edge line vertices for Environment wireframe rendering.</summary>
|
|
||||||
public Vector3[] EdgeLines { get; set; } = Array.Empty<Vector3>();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// CPU-side data for a single rendering batch (indices + texture reference).
|
|
||||||
/// </summary>
|
|
||||||
public class MeshBatchData {
|
|
||||||
public ushort[] Indices { get; set; } = Array.Empty<ushort>();
|
|
||||||
public (int Width, int Height, TextureFormat Format) TextureFormat { get; set; }
|
|
||||||
public TextureKey TextureKey { get; set; }
|
|
||||||
public int TextureIndex { get; set; }
|
|
||||||
public byte[] TextureData { get; set; } = Array.Empty<byte>();
|
|
||||||
public PixelFormat? UploadPixelFormat { get; set; }
|
|
||||||
public PixelType? UploadPixelType { get; set; }
|
|
||||||
public DatReaderWriter.Enums.CullMode CullMode { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// CPU-side texture info for deduplication during background preparation.
|
|
||||||
/// </summary>
|
|
||||||
public class TextureBatchData {
|
|
||||||
public TextureKey Key { get; set; }
|
|
||||||
public byte[] TextureData { get; set; } = Array.Empty<byte>();
|
|
||||||
public PixelFormat? UploadPixelFormat { get; set; }
|
|
||||||
public PixelType? UploadPixelType { get; set; }
|
|
||||||
public List<ushort> Indices { get; set; } = new();
|
|
||||||
public DatReaderWriter.Enums.CullMode CullMode { get; set; }
|
|
||||||
public bool IsTransparent { get; set; }
|
|
||||||
public bool IsAdditive { get; set; }
|
|
||||||
public bool HasWrappingUVs { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// GPU-side render data created on the main thread.
|
/// GPU-side render data created on the main thread.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using AcDream.Content;
|
||||||
using AcDream.Core.Meshing;
|
using AcDream.Core.Meshing;
|
||||||
using AcDream.Core.Rendering;
|
using AcDream.Core.Rendering;
|
||||||
using DatReaderWriter;
|
using DatReaderWriter;
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,14 @@
|
||||||
exact versions (mirror AcDream.App.csproj — keep in lockstep). -->
|
exact versions (mirror AcDream.App.csproj — keep in lockstep). -->
|
||||||
<PackageReference Include="BCnEncoder.Net.ImageSharp" Version="1.1.2" />
|
<PackageReference Include="BCnEncoder.Net.ImageSharp" Version="1.1.2" />
|
||||||
<PackageReference Include="SixLabors.ImageSharp" Version="3.1.12" />
|
<PackageReference Include="SixLabors.ImageSharp" Version="3.1.12" />
|
||||||
|
<!-- MP1a (Task 3, compiler-demanded): MeshBatchData/TextureBatchData carry
|
||||||
|
Silk.NET.OpenGL.PixelFormat?/PixelType? upload-format hints computed
|
||||||
|
during CPU extraction (which format to hand the eventual GL upload).
|
||||||
|
These are plain enums with no GL context/device/unsafe surface — the
|
||||||
|
plan's own boundary survey says the only GL-DOMAIN reference in the
|
||||||
|
Prepare* region is TextureAtlasManager.TextureKey; this is the same
|
||||||
|
class of dependency (a data-only enum), not a functional GL call. -->
|
||||||
|
<PackageReference Include="Silk.NET.OpenGL" Version="2.23.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
|
||||||
125
src/AcDream.Content/ObjectMeshData.cs
Normal file
125
src/AcDream.Content/ObjectMeshData.cs
Normal file
|
|
@ -0,0 +1,125 @@
|
||||||
|
using Chorizite.Core.Lib;
|
||||||
|
using Chorizite.Core.Render.Enums;
|
||||||
|
using DatReaderWriter.DBObjs;
|
||||||
|
using DatReaderWriter.Types;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Numerics;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using BoundingBox = Chorizite.Core.Lib.BoundingBox;
|
||||||
|
using PixelFormat = Silk.NET.OpenGL.PixelFormat;
|
||||||
|
using PixelType = Silk.NET.OpenGL.PixelType;
|
||||||
|
|
||||||
|
namespace AcDream.Content;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Vertex format for scenery mesh rendering: position, normal, UV.
|
||||||
|
/// </summary>
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
public struct VertexPositionNormalTexture {
|
||||||
|
public Vector3 Position;
|
||||||
|
public Vector3 Normal;
|
||||||
|
public Vector2 UV;
|
||||||
|
|
||||||
|
public static int Size => 8 * sizeof(float); // 3+3+2 = 8 floats = 32 bytes
|
||||||
|
|
||||||
|
public VertexPositionNormalTexture(Vector3 position, Vector3 normal, Vector2 uv) {
|
||||||
|
Position = position;
|
||||||
|
Normal = normal;
|
||||||
|
UV = uv;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Staged data for a particle emitter to be created on the GL thread.
|
||||||
|
/// </summary>
|
||||||
|
public struct StagedEmitter {
|
||||||
|
public ParticleEmitter Emitter;
|
||||||
|
public uint PartIndex;
|
||||||
|
public Matrix4x4 Offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// CPU-side mesh data prepared on a background thread.
|
||||||
|
/// Contains vertex data and per-batch index/texture info, but NO GPU resources.
|
||||||
|
/// </summary>
|
||||||
|
public class ObjectMeshData {
|
||||||
|
public ulong ObjectId { get; set; }
|
||||||
|
public bool IsSetup { get; set; }
|
||||||
|
public VertexPositionNormalTexture[] Vertices { get; set; } = Array.Empty<VertexPositionNormalTexture>();
|
||||||
|
public List<MeshBatchData> Batches { get; set; } = new();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// #125 (2026-06-12): GL upload-retry counter. A failed
|
||||||
|
/// <see cref="ObjectMeshManager.UploadMeshData"/> (returns null from its
|
||||||
|
/// catch) used to be dropped permanently — the staged item was consumed,
|
||||||
|
/// no render data was produced, and the prepared data lingered in the CPU
|
||||||
|
/// cache where <c>PrepareMeshDataAsync</c>'s cache-hit short-circuit
|
||||||
|
/// returned it without ever re-staging it for upload (session-sticky
|
||||||
|
/// invisible mesh, one [wb-error] line). The drain loop now re-stages a
|
||||||
|
/// failed upload for the NEXT frame up to <see cref="ObjectMeshManager.
|
||||||
|
/// MaxUploadRetries"/> times. The counter lives on the mesh-data object so
|
||||||
|
/// it resets to 0 naturally whenever the id is re-prepared (fresh object),
|
||||||
|
/// and bounds a deterministic GL failure to a few loud lines instead of a
|
||||||
|
/// silent permanent drop OR an unbounded per-frame retry storm. Retail
|
||||||
|
/// loads content synchronously and has no such failure mode — this
|
||||||
|
/// converges our async pipeline toward that guarantee.
|
||||||
|
/// </summary>
|
||||||
|
public int UploadAttempts;
|
||||||
|
|
||||||
|
/// <summary>For EnvCell: the geometry of the cell itself.</summary>
|
||||||
|
public ObjectMeshData? EnvCellGeometry { get; set; }
|
||||||
|
|
||||||
|
/// <summary>For Setup objects: parts with their local transforms.</summary>
|
||||||
|
public List<(ulong GfxObjId, Matrix4x4 Transform)> SetupParts { get; set; } = new();
|
||||||
|
|
||||||
|
/// <summary>Particle emitters from physics scripts.</summary>
|
||||||
|
public List<StagedEmitter> ParticleEmitters { get; set; } = new();
|
||||||
|
|
||||||
|
/// <summary>Per-format texture atlas data (to be uploaded to GPU on main thread).</summary>
|
||||||
|
public Dictionary<(int Width, int Height, TextureFormat Format), List<TextureBatchData>> TextureBatches { get; set; } = new();
|
||||||
|
|
||||||
|
/// <summary>Local bounding box.</summary>
|
||||||
|
public BoundingBox BoundingBox { get; set; }
|
||||||
|
|
||||||
|
/// <summary>Approximate center point used for depth sorting / transparency ordering.</summary>
|
||||||
|
public Vector3 SortCenter { get; set; }
|
||||||
|
|
||||||
|
/// <summary>DataID of a simpler GfxObj to use at long distance / low quality, or GfxObjDegradeInfo.</summary>
|
||||||
|
public uint DIDDegrade { get; set; }
|
||||||
|
|
||||||
|
/// <summary>Sphere used for mouse selection.</summary>
|
||||||
|
public Sphere? SelectionSphere { get; set; }
|
||||||
|
|
||||||
|
/// <summary>Edge line vertices for Environment wireframe rendering.</summary>
|
||||||
|
public Vector3[] EdgeLines { get; set; } = Array.Empty<Vector3>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// CPU-side data for a single rendering batch (indices + texture reference).
|
||||||
|
/// </summary>
|
||||||
|
public class MeshBatchData {
|
||||||
|
public ushort[] Indices { get; set; } = Array.Empty<ushort>();
|
||||||
|
public (int Width, int Height, TextureFormat Format) TextureFormat { get; set; }
|
||||||
|
public TextureKey TextureKey { get; set; }
|
||||||
|
public int TextureIndex { get; set; }
|
||||||
|
public byte[] TextureData { get; set; } = Array.Empty<byte>();
|
||||||
|
public PixelFormat? UploadPixelFormat { get; set; }
|
||||||
|
public PixelType? UploadPixelType { get; set; }
|
||||||
|
public DatReaderWriter.Enums.CullMode CullMode { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// CPU-side texture info for deduplication during background preparation.
|
||||||
|
/// </summary>
|
||||||
|
public class TextureBatchData {
|
||||||
|
public TextureKey Key { get; set; }
|
||||||
|
public byte[] TextureData { get; set; } = Array.Empty<byte>();
|
||||||
|
public PixelFormat? UploadPixelFormat { get; set; }
|
||||||
|
public PixelType? UploadPixelType { get; set; }
|
||||||
|
public List<ushort> Indices { get; set; } = new();
|
||||||
|
public DatReaderWriter.Enums.CullMode CullMode { get; set; }
|
||||||
|
public bool IsTransparent { get; set; }
|
||||||
|
public bool IsAdditive { get; set; }
|
||||||
|
public bool HasWrappingUVs { get; set; }
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue