Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#pragma once

#include "GltfConverterResult.h"

#include <Cesium3DTilesContent/GltfConverters.h> // Include for AssetFetcher definition
#include <CesiumAsync/Future.h>
#include <CesiumGltf/Model.h>
#include <CesiumGltfReader/GltfReader.h>

#include <optional>
#include <span>

namespace Cesium3DTilesContent {

/**
* @brief Converts a vctr (Vector) file to a glTF.
*
* For more information on the vctr format, see
* https://github.com/CesiumGS/3d-tiles/blob/main/specification/TileFormats/VectorData/README.md
*/
struct VctrToGltfConverter {
/**
* @brief Converts a vctr binary file to a glTF model.
*
* @param vctrBinary The bytes loaded for the vctr model.
* @param options Options for how the glTF should be loaded.
* @param assetFetcher The \ref AssetFetcher containing information used by
* loaded assets.
* @returns A future that resolves to a \ref GltfConverterResult.
*/
static CesiumAsync::Future<GltfConverterResult> convert(
const std::span<const std::byte>& vctrBinary,
const CesiumGltfReader::GltfReaderOptions& options,
const AssetFetcher& assetFetcher);
};
} // namespace Cesium3DTilesContent
99 changes: 98 additions & 1 deletion Cesium3DTilesContent/src/BatchTableToGltfStructuralMetadata.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#include "BatchTableToGltfStructuralMetadata.h"
#include "BatchTableToGltfStructuralMetadata.h"

#include "BatchTableHierarchyPropertyValues.h"
#include "MetadataProperty.h"
Expand Down Expand Up @@ -2251,4 +2251,101 @@ ErrorList BatchTableToGltfStructuralMetadata::convertFromI3dm(
}
return result;
}
ErrorList BatchTableToGltfStructuralMetadata::convertFromVctr(
const rapidjson::Document& featureTableJson,
const rapidjson::Document& batchTableJson,
const std::span<const std::byte>& batchTableBinaryData,
CesiumGltf::Model& gltf) {

// Check to make sure a char of rapidjson is 1 byte
static_assert(
sizeof(rapidjson::Value::Ch) == 1,
"RapidJson::Value::Ch is not 1 byte");

ErrorList result;

// for calcuate total feature count
int64_t totalFeatureCount = 0;

// Check for POINTS_LENGTH
const auto pointsLengthIt = featureTableJson.FindMember("POINTS_LENGTH");
if (pointsLengthIt != featureTableJson.MemberEnd() &&
pointsLengthIt->value.IsInt64() && pointsLengthIt->value.GetInt64() > 0) {
totalFeatureCount += pointsLengthIt->value.GetInt64();
}

// Check for POLYLINES_LENGTH
const auto polylinesLengthIt =
featureTableJson.FindMember("POLYLINES_LENGTH");
if (polylinesLengthIt != featureTableJson.MemberEnd() &&
polylinesLengthIt->value.IsInt64() &&
polylinesLengthIt->value.GetInt64() > 0) {
totalFeatureCount += polylinesLengthIt->value.GetInt64();
}

// Check for POLYGONS_LENGTH
const auto polygonsLengthIt = featureTableJson.FindMember("POLYGONS_LENGTH");
if (polygonsLengthIt != featureTableJson.MemberEnd() &&
polygonsLengthIt->value.IsInt64() &&
polygonsLengthIt->value.GetInt64() > 0) {
totalFeatureCount += polygonsLengthIt->value.GetInt64();
}

// if there is no valid feature, then output a warning and return.
if (totalFeatureCount == 0) {
result.emplaceWarning(
"The VCTR has a batch table, but it is being ignored because there "
"are no valid geometry features in the feature table.");
return result;
}

// convert batch table
convertBatchTableToGltfStructuralMetadataExtension(
batchTableJson,
batchTableBinaryData,
gltf,
totalFeatureCount,
result);

// Create an EXT_mesh_features extension for each primitive with a _BATCHID
// attribute.
for (Mesh& mesh : gltf.meshes) {
for (MeshPrimitive& primitive : mesh.primitives) {
auto batchIDIt = primitive.attributes.find("_BATCHID");
if (batchIDIt == primitive.attributes.end()) {
// This primitive has no batch ID, ignore it.
continue;
}

// Rename the _BATCHID attribute to _FEATURE_ID_0
primitive.attributes["_FEATURE_ID_0"] = batchIDIt->second;
primitive.attributes.erase("_BATCHID");

// Also rename the attribute in the Draco extension, if it exists.
ExtensionKhrDracoMeshCompression* pDraco =
primitive.getExtension<ExtensionKhrDracoMeshCompression>();
if (pDraco) {
auto dracoIt = pDraco->attributes.find("_BATCHID");
if (dracoIt != pDraco->attributes.end()) {
pDraco->attributes["_FEATURE_ID_0"] = dracoIt->second;
pDraco->attributes.erase("_BATCHID");
}
}

ExtensionExtMeshFeatures& extension =
primitive.addExtension<ExtensionExtMeshFeatures>();
gltf.addExtensionUsed(ExtensionExtMeshFeatures::ExtensionName);

FeatureId& featureID = extension.featureIds.emplace_back();

// Use the total feature count for VCTR
featureID.featureCount = totalFeatureCount;
featureID.attribute = 0;
featureID.label = "_FEATURE_ID_0";
featureID.propertyTable = 0;
}
}

return result;
}
} // namespace Cesium3DTilesContent
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#pragma once
#pragma once

#include <CesiumGltf/Model.h>
#include <CesiumUtility/ErrorList.h>
Expand Down Expand Up @@ -28,5 +28,11 @@ struct BatchTableToGltfStructuralMetadata {
const std::span<const std::byte>& featureTableJsonData,
const std::span<const std::byte>& batchTableBinaryData,
CesiumGltf::Model& gltf);

static CesiumUtility::ErrorList convertFromVctr(
const rapidjson::Document& featureTableJson,
const rapidjson::Document& batchTableJson,
const std::span<const std::byte>& batchTableBinaryData,
CesiumGltf::Model& gltf);
};
} // namespace Cesium3DTilesContent
Loading