载入中...
搜索中...
未找到
GtsTerrainLodPackage.cpp
浏览该文件的文档.
2
5
6#include <algorithm>
7#include <limits>
8
9namespace eve::asset_procgen {
10namespace {
11Value::Array vec3(float x, float y, float z) { return {Value(double(x)), Value(double(y)), Value(double(z))}; }
12}
13
16 const std::string& terrainName, const asset_import::AssetImportLimits& limits) {
17 using namespace asset_import;
18 auto manifest = asset_import::detail::baseManifest(package, "eve.gts-terrain-lod");
19 if (!manifest) return Result<PreparedAssetImport>::failure(manifest.status());
20 auto plan = procgen::planGtsTerrainLodAssets(lods, terrainName, "Meshes");
21 if (!plan) return Result<PreparedAssetImport>::failure(plan.status());
22 if (plan.value().empty()) return Result<PreparedAssetImport>::failure(Diagnostic::error(DiagnosticCode::InvalidArgument, "GTS LOD set has no meshes", {}, {}, "asset.procgen.gts-lod"));
23 if (plan.value().size() > limits.maximumAssets)
24 return Result<PreparedAssetImport>::failure(Diagnostic::error(DiagnosticCode::InvalidArgument, "GTS LOD asset count exceeds limit", {}, {}, "asset.procgen.gts-lod"));
25 PreparedAssetImport result;
26 result.manifest = std::move(manifest).takeValue();
27 std::uint64_t totalBytes = 0;
28 for (const auto& entry : plan.value()) {
29 const auto* tile = lods.tileAt(entry.tileIndex);
30 if (!tile || entry.levelIndex < 0 || entry.levelIndex >= static_cast<int>(tile->levels.size()))
31 return Result<PreparedAssetImport>::failure(Diagnostic::error(DiagnosticCode::InvalidArgument, "GTS LOD plan references a missing mesh", {}, {}, "asset.procgen.gts-lod"));
32 const auto& mesh = tile->levels[static_cast<std::size_t>(entry.levelIndex)];
34 canonical.positions = mesh.positions(); canonical.normals = mesh.normals(); canonical.indices = mesh.indices();
35 if (mesh.hasVertexColors()) canonical.colors = mesh.colors();
36 if (!mesh.uvs().empty()) canonical.texcoords.emplace(0, mesh.uvs());
38 meshLimits.maximumVertices = limits.maximumVerticesPerPrimitive;
39 meshLimits.maximumIndices = limits.maximumIndicesPerPrimitive;
40 meshLimits.maximumDecodedBytes = limits.maximumDecodedBytes;
41 auto blob = asset::encodeCanonicalMesh(canonical, meshLimits);
42 if (!blob) return Result<PreparedAssetImport>::failure(blob.status());
43 if (blob.value().size() > limits.maximumDecodedBytes || totalBytes > limits.maximumDecodedBytes - blob.value().size())
44 return Result<PreparedAssetImport>::failure(Diagnostic::error(DiagnosticCode::InvalidArgument, "GTS LOD package exceeds decoded byte limit", {}, {}, "asset.procgen.gts-lod"));
45 totalBytes += blob.value().size();
46 const auto id = package.packageId.child("gts-terrain:" + std::to_string(entry.tileIndex) + ":lod:" +
47 std::to_string(entry.levelIndex));
48 auto ref = asset_import::detail::assetRef(id);
49 if (!ref) return Result<PreparedAssetImport>::failure(ref.status());
50 const std::string base = "assets/" + id.format() + "/";
51 const std::string definitionPath = base + "asset.json", blobPath = base + "mesh.bin";
52 const auto& positions = mesh.positions();
53 float minX=positions[0], minY=positions[1], minZ=positions[2], maxX=minX, maxY=minY, maxZ=minZ;
54 for (std::size_t i=0;i<positions.size();i+=3) {
55 minX=std::min(minX,positions[i]); minY=std::min(minY,positions[i+1]); minZ=std::min(minZ,positions[i+2]);
56 maxX=std::max(maxX,positions[i]); maxY=std::max(maxY,positions[i+1]); maxZ=std::max(maxZ,positions[i+2]);
57 }
58 Value::Array uvSets; if (!mesh.uvs().empty()) uvSets.emplace_back(int64_t(0));
59 Value definition(Value::Object{{"blob",blobPath},{"boundsMax",vec3(maxX,maxY,maxZ)},
60 {"boundsMin",vec3(minX,minY,minZ)},{"coordinateSystem","right-handed-x-right-y-up-minus-z-forward"},
61 {"colors",mesh.hasVertexColors()},{"frontFace","counter-clockwise"},{"indexCount",int64_t(mesh.getIndexCount())},{"normals",true},
62 {"schema","eve.mesh"},{"schemaVersion",int64_t(3)},{"topology","triangles"},
63 {"texcoordSets",std::move(uvSets)},{"unit","meter"},{"vertexCount",int64_t(mesh.getVertexCount())}});
64 auto json = definition.toJson();
65 if (!json) return Result<PreparedAssetImport>::failure(json.status());
66 std::vector<std::uint8_t> jsonBytes(json.value().begin(),json.value().end());
67 result.manifest.assets.push_back({ref.value(),"eve.mesh",SchemaVersion(3),definitionPath,
68 asset_import::detail::sha256(jsonBytes),{"mesh","terrain","gts-lod",entry.meshName}});
69 result.entries.push_back({definitionPath,std::move(jsonBytes)});
70 result.entries.push_back({blobPath,std::move(blob).takeValue()});
71 const std::string key="tile-"+std::to_string(entry.tileIndex)+"-lod-"+std::to_string(entry.levelIndex);
72 result.manifest.entrypoints.emplace(key,ref.value());
73 if (!result.manifest.entrypoints.contains("default")) result.manifest.entrypoints.emplace("default",ref.value());
74 auto mapping=asset_import::detail::assetRef(id); if(!mapping) return Result<PreparedAssetImport>::failure(mapping.status());
75 result.sourceMappings.push_back({entry.objectName,std::move(mapping).takeValue()});
76 result.findings.push_back({terrainName,entry.objectName,ImportDisposition::Translated,
77 "GTS tile LOD converted to canonical eve.mesh/3 as "+entry.meshName});
78 }
79 auto report=asset_import::detail::finalizeImportReport(result,package,"Unity Pcg Pro GTS","4.2.2",
80 {{"terrainName",terrainName},{"tileCount",int64_t(lods.getTileCount())},{"lodCount",int64_t(lods.getLevelCount())}});
81 if (!report) return Result<PreparedAssetImport>::failure(report.status());
82 auto verified=asset::buildEvaArchive(result.manifest,result.entries);
83 if (!verified) return Result<PreparedAssetImport>::failure(verified.status());
84 return Result<PreparedAssetImport>::success(std::move(result));
85}
86}
float y
Definition AnimClip.cpp:738
float x
Definition AnimClip.cpp:738
float z
Definition AnimClip.cpp:738
std::vector< std::uint8_t > blob
std::uint32_t key
Canonical asset packaging for generated GTS terrain LODs.
std::vector< float > positions
Mesh * mesh
const AssetImportLimits & limits
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
The canonical owning dynamic value used by data-facing protocols.
Definition Value.h:31
std::map< std::string, Value > Object
Definition Value.h:34
std::vector< Value > Array
Definition Value.h:33
Id128 child(std::string_view role) const noexcept
Derives a deterministic child UUID for a hierarchical identity.
Definition Identity.h:192
Owned result of the GTS split-and-sequential-simplify pipeline.
int getTileCount() const
Return the number of tiles, including empty source cells.
const GtsTerrainLodTile * tileAt(int index) const
Return one tile or nullptr for an invalid index. @ownership The LOD set retains ownership; the caller...
int getLevelCount() const
Return the common number of LOD levels per tile.
std::string sha256(std::span< const std::uint8_t > bytes)
Sha 256.
EVENGINE_API_PLATFORM Result< void > finalizeImportReport(PreparedAssetImport &prepared, const ImportPackageIdentity &package, std::string_view sourceEngine, std::string_view sourceVersion, Value::Object options={})
Append the deterministic mandatory import report and bind it from provenance.
Result< asset::EvaManifest > baseManifest(const ImportPackageIdentity &package, std::string_view importer)
Base manifest.
Result< AssetRef > assetRef(PersistentId id)
Asset ref.
Result< asset_import::PreparedAssetImport > prepareGtsTerrainLodPackage(const asset_import::ImportPackageIdentity &package, const procgen::GtsTerrainLodSet &lods, const std::string &terrainName, const asset_import::AssetImportLimits &limits)
Prepare a complete .eva source package containing every non-empty GTS tile LOD as eve....
Result< std::vector< std::uint8_t > > buildEvaArchive(const EvaManifest &manifest, std::vector< EvaArchiveEntry > entries, const EvaArchiveLimits &limits)
Build a deterministic ZIP64 .eva, selecting raw Deflate only when smaller than Store.
EVENGINE_API_FOUNDATION Result< std::vector< std::uint8_t > > encodeCanonicalMesh(const CanonicalMeshData &mesh, const CanonicalMeshLimits &limits={})
Encode an owning snapshot to EVMESH v3, or v2 when no named attributes exist. Borrows input synchrono...
std::variant< std::monostate, std::int64_t, double, std::string, bool > Value
Definition Database.h:26
Result< std::vector< GtsTerrainLodAssetEntry > > planGtsTerrainLodAssets(const GtsTerrainLodSet &lods, const std::string &terrainName, const std::string &meshFolder)
Build the deterministic object and mesh naming plan used by GTS terrain export.
detail::StrongUint64< detail::SchemaVersionTag > SchemaVersion
Persistent data-format version; not a runtime replacement generation.
Owning CPU mesh snapshot; UV arrays are packed ST pairs indexed by source set number....
std::vector< float > colors
std::vector< std::uint32_t > indices
std::vector< float > normals
std::map< std::uint32_t, std::vector< float > > texcoords
std::vector< float > positions
Allocation limits checked before decoding any vertex arrays. UV count is byte-budget bounded.
Parser and allocation budgets applied to untrusted importer inputs.
Common stable package metadata supplied by an import transaction.