载入中...
搜索中...
未找到
EvpackGraphicsLoader.cpp
浏览该文件的文档.
2#include <cmath>
3#include <limits>
4#include <new>
6namespace eve::asset_graphics {
7namespace {}
9 const asset::EvpackCapabilities& capabilities,
11 std::uint32_t texcoordSet, bool preserveAllTexcoords) const {
12 auto payload = reader_.read(asset, "eve.mesh/3", capabilities, limits.maximumDecodedBytes);
13 if (!payload && payload.error()->code() == DiagnosticCode::TypeMismatch)
14 payload = reader_.read(asset, "eve.mesh/2", capabilities, limits.maximumDecodedBytes);
15 if (!payload && payload.error()->code() == DiagnosticCode::TypeMismatch)
16 payload = reader_.read(asset, "eve.mesh/1", capabilities, limits.maximumDecodedBytes);
18 const asset::RuntimeAssetChunk* bulk = nullptr;
19 for (const auto& chunk : payload.value().chunks) {
20 if (chunk.kind != asset::EvpackChunkKind::Bulk) continue;
21 if (bulk)
23 DiagnosticCode::ParseError, "eve.mesh must contain exactly one bulk chunk", {}, {}, "asset.graphics"));
24 bulk = &chunk;
25 }
26 if (!bulk)
28 Diagnostic::error(DiagnosticCode::NotFound, "eve.mesh bulk chunk is missing", {}, {}, "asset.graphics"));
29 auto staging = asset::decodeCanonicalMesh(
30 bulk->bytes, {limits.maximumVertices, limits.maximumIndices, limits.maximumDecodedBytes});
31 if (!staging) return Result<LoadedGraphicsMesh>::failure(staging.status());
32 if (staging.value().positions.size() / 3 > size_t(std::numeric_limits<int>::max()) ||
33 staging.value().indices.size() > size_t(std::numeric_limits<int>::max()))
35 DiagnosticCode::InvalidArgument, "mesh exceeds backend count range", {}, {}, "asset.graphics"));
36 const auto uv = staging.value().texcoords.find(texcoordSet);
37 if (uv == staging.value().texcoords.end() && (texcoordSet != 0 || !staging.value().texcoords.empty()))
39 DiagnosticCode::NotFound, "requested UV set is absent; no remapping performed", {}, {}, "asset.graphics"));
40 auto uploaded = staging.value().colors.empty()
41 ? factory_.uploadMesh(staging.value().positions.data(),
42 staging.value().normals.empty() ? nullptr : staging.value().normals.data(),
43 uv == staging.value().texcoords.end() ? nullptr : uv->second.data(),
44 static_cast<int>(staging.value().positions.size() / 3), staging.value().indices.data(),
45 static_cast<int>(staging.value().indices.size()))
46 : factory_.uploadMeshColored(staging.value().positions.data(),
47 staging.value().normals.empty() ? nullptr : staging.value().normals.data(),
48 uv == staging.value().texcoords.end() ? nullptr : uv->second.data(),
49 staging.value().colors.data(),
50 static_cast<int>(staging.value().positions.size() / 3), staging.value().indices.data(),
51 static_cast<int>(staging.value().indices.size()));
52 if (!uploaded) return Result<LoadedGraphicsMesh>::failure(uploaded.status());
53 if (const auto authored = staging.value().attributes.find("TANGENT");
54 authored != staging.value().attributes.end()) {
55 const auto count = staging.value().positions.size() / 3;
56 const auto& a = authored->second;
57 auto attach = [&]() -> Result<void> {
58 try {
59 if (a.components != 4 || a.values.size() != count * 4 || staging.value().normals.size() != count * 3)
61 Diagnostic::error(DiagnosticCode::InvalidArgument, "invalid canonical tangent frame"));
62 std::vector<float> tangents(count * 3), bitangents(count * 3);
63 for (size_t i = 0; i < count; ++i) {
64 const auto& normals = staging.value().normals;
65 const float w = a.values[i * 4 + 3];
66 if (w != 1.f && w != -1.f)
68 "tangent handedness must be signed unit"));
69 for (unsigned c = 0; c < 3; ++c) {
70 tangents[i * 3 + c] = a.values[i * 4 + c];
71 const unsigned j = (c + 1) % 3, k = (c + 2) % 3;
72 bitangents[i * 3 + c] =
73 (normals[i * 3 + j] * a.values[i * 4 + k] - normals[i * 3 + k] * a.values[i * 4 + j]) * w;
74 if (!std::isfinite(bitangents[i * 3 + c]))
76 Diagnostic::error(DiagnosticCode::InvalidArgument, "nonfinite canonical bitangent"));
77 }
78 }
79 return factory_.setMeshTangentFrame(uploaded.value(), tangents, bitangents);
80 } catch (const std::bad_alloc&) {
82 Diagnostic::error(DiagnosticCode::Failed, "canonical tangent allocation failed"));
83 }
84 };
85 auto attached = attach();
86 if (!attached) {
87 auto released = factory_.releaseMesh(uploaded.value());
88 if (!released) return Result<LoadedGraphicsMesh>::failure(released.status());
89 return Result<LoadedGraphicsMesh>::failure(attached.status());
90 }
91 }
92 if (preserveAllTexcoords)
93 for (const auto& [set, values] : staging.value().texcoords) {
94 if (set == texcoordSet) continue;
95 auto attached = factory_.setMeshTexcoords(uploaded.value(), set, values);
96 if (!attached) {
97 auto released = factory_.releaseMesh(uploaded.value());
98 if (!released) return Result<LoadedGraphicsMesh>::failure(released.status());
99 return Result<LoadedGraphicsMesh>::failure(attached.status());
100 }
101 }
102 std::vector<uint32_t> available;
103 for (const auto& [set, values] : staging.value().texcoords) available.push_back(set);
104 return Result<LoadedGraphicsMesh>::success({asset, uploaded.value(), std::move(payload).takeValue().variant,
105 texcoordSet, std::move(available),
106 std::move(staging.value().attributes)});
107}
108
109} // namespace eve::asset_graphics
Value::Object payload
float w
Definition AnimClip.cpp:738
std::string variant
float uv
std::map< std::string, Var > values
Transactional graphics consumers for canonical runtime assets.
std::vector< float > normals
std::int32_t c
MeleePoint3 a
Definition MeleeHit.cpp:40
std::uint32_t count
const AssetImportLimits & limits
Stable asset identity backed by PersistentId.
Definition ResourceRef.h:53
static Diagnostic error(DiagnosticCode code, std::string message, std::string path={}, DiagnosticDetails details={}, std::string source={})
Construct an error diagnostic with the standard error severity.
Definition Diagnostic.h:125
Move-only operation result carrying either a value or Status.
Definition Result.h:155
static Result success(T value)
Construct a successful result owning value.
Definition Result.h:164
static Result failure(Status status)
Construct a failed result from a structured status.
Definition Result.h:175
Result< RuntimeAssetPayload > read(const AssetRef &asset, std::string_view expectedType, const EvpackCapabilities &capabilities, std::uint64_t maximumDecodedBytes) const
Resolve, type-check, variant-select and decode a canonical runtime asset.
Result< LoadedGraphicsMesh > loadMesh(const AssetRef &asset, const asset::EvpackCapabilities &capabilities, const GraphicsAssetLoadLimits &limits={}, std::uint32_t texcoordSet=0, bool preserveAllTexcoords=false) const
Validate and upload one canonical mesh v3 (or compatibility v1/v2) atomically.
virtual Result< void > setMeshTangentFrame(Mesh *, std::span< const float >, std::span< const float >)
Attach authored XYZ tangent and bitangent streams before mesh publication.
virtual Result< void > releaseMesh(Mesh *mesh)=0
Release a mesh previously returned by this factory.
virtual Result< void > setMeshTexcoords(Mesh *, std::uint32_t, std::span< const float >)
Attach an owning UV stream to an uploaded mesh before publication. @thread Graphics thread; input is ...
virtual Result< Mesh * > uploadMesh(const float *posXYZ, const float *nrmXYZ, const float *uvST, int vertexCount, const std::uint32_t *indices, int indexCount)=0
Upload validated, tightly packed mesh arrays.
virtual Result< Mesh * > uploadMeshColored(const float *, const float *, const float *, const float *, int, const std::uint32_t *, int)
Upload a mesh with a tightly packed linear RGBA vertex-color stream.
Result< CanonicalMeshData > decodeCanonicalMesh(std::span< const std::uint8_t > bytes, const CanonicalMeshLimits &limits)
Decode canonical EVMESH binary v1, v2 or v3 into independently owned arrays.
@ TypeMismatch
A stable reference resolved to a different canonical domain type.
Actual runtime device capabilities used for variant selection.
Definition Evpack.h:92
One decoded runtime chunk with its admitted semantic metadata.
std::vector< std::uint8_t > bytes
Bounds applied before allocating canonical mesh staging arrays.