Files
BXSSP_Andriod/Plugins/CesiumForUnreal/Source/CesiumRuntime/Private/Tests/CesiumGltfSpecUtility.h

228 lines
8.0 KiB
C++

#pragma once
#include "CesiumGltf/ExtensionExtMeshFeatures.h"
#include "CesiumGltf/ExtensionModelExtStructuralMetadata.h"
#include "CesiumGltf/Model.h"
#include "CesiumGltf/PropertyTypeTraits.h"
#include <glm/glm.hpp>
#include <type_traits>
#include <vector>
/**
* @brief Converts the given vector of values into a std::vector of bytes.
*
* @returns The values as a std::vector of bytes.
*/
template <typename T>
std::vector<std::byte> GetValuesAsBytes(const std::vector<T>& values) {
std::vector<std::byte> bytes(values.size() * sizeof(T));
std::memcpy(bytes.data(), values.data(), bytes.size());
return bytes;
}
/**
* @brief Adds the buffer to the given model, creating a buffer view and
* accessor in the process.
* @returns The index of the accessor.
*/
int32_t AddBufferToModel(
CesiumGltf::Model& model,
const std::string& type,
const int32_t componentType,
const std::vector<std::byte>&& values);
/**
* @brief Creates an attribute on the given primitive, including a buffer,
* buffer view, and accessor for the given values.
*/
template <typename T>
void CreateAttributeForPrimitive(
CesiumGltf::Model& model,
CesiumGltf::MeshPrimitive& primitive,
const std::string& attributeName,
const std::string& type,
const int32_t componentType,
const std::vector<T>& values) {
std::vector<std::byte> data = GetValuesAsBytes(values);
const int32_t accessor =
AddBufferToModel(model, type, componentType, std::move(data));
primitive.attributes.insert({attributeName, accessor});
}
/**
* @brief Creates indices for the given primitive, including a buffer,
* buffer view, and accessor for the given values.
*/
template <typename T>
void CreateIndicesForPrimitive(
CesiumGltf::Model& model,
CesiumGltf::MeshPrimitive& primitive,
const int32_t componentType,
const std::vector<T>& indices) {
std::vector<std::byte> values = GetValuesAsBytes(indices);
const int32_t accessor = AddBufferToModel(
model,
CesiumGltf::AccessorSpec::Type::SCALAR,
componentType,
std::move(values));
primitive.indices = accessor;
}
/**
* @brief Adds the feature IDs to the given primitive as a feature ID attribute
* in EXT_mesh_features. If the primitive doesn't already contain
* EXT_mesh_features, this function adds it.
*
* @returns The newly created feature ID in the primitive extension.
*/
CesiumGltf::FeatureId& AddFeatureIDsAsAttributeToModel(
CesiumGltf::Model& model,
CesiumGltf::MeshPrimitive& primitive,
const std::vector<uint8_t>& featureIDs,
const int64_t featureCount,
const int64_t setIndex);
/**
* @brief Adds the feature IDs to the given primitive as a feature ID texture
* in EXT_mesh_features. This also adds the given texcoords to the primitive as
* a TEXCOORD attribute. If the primitive doesn't already contain
* EXT_mesh_features, this function adds it.
*
* @returns The newly created feature ID in the primitive extension.
*/
CesiumGltf::FeatureId& AddFeatureIDsAsTextureToModel(
CesiumGltf::Model& model,
CesiumGltf::MeshPrimitive& primitive,
const std::vector<uint8_t>& featureIDs,
const int64_t featureCount,
const int32_t imageWidth,
const int32_t imageHeight,
const std::vector<glm::vec2>& texCoords,
const int64_t texcoordSetIndex,
const int32_t samplerWrapS = CesiumGltf::Sampler::WrapS::CLAMP_TO_EDGE,
const int32_t samplerWrapT = CesiumGltf::Sampler::WrapT::CLAMP_TO_EDGE);
/**
* @brief Adds the given values to the given model as a property table property
* in EXT_structural_metadata. This also creates a class property definition for
* the new property in the schema. If the model doesn't already contain
* EXT_structural_metadata, this function adds it.
*
* This assumes the given values are not arrays or strings.
*
* @returns The newly created property table property in the model extension.
*/
template <typename T>
CesiumGltf::PropertyTableProperty& AddPropertyTablePropertyToModel(
CesiumGltf::Model& model,
CesiumGltf::PropertyTable& propertyTable,
const std::string& propertyName,
const std::string& type,
const std::optional<std::string>& componentType,
const std::vector<T>& values) {
CesiumGltf::ExtensionModelExtStructuralMetadata* pExtension =
model.getExtension<CesiumGltf::ExtensionModelExtStructuralMetadata>();
if (pExtension == nullptr) {
pExtension =
&model.addExtension<CesiumGltf::ExtensionModelExtStructuralMetadata>();
}
if (!pExtension->schema) {
pExtension->schema.emplace();
}
CesiumGltf::Schema& schema = *pExtension->schema;
const std::string& className = propertyTable.classProperty;
CesiumGltf::Class& theClass = schema.classes[className];
CesiumGltf::ClassProperty& classProperty = theClass.properties[propertyName];
classProperty.type = type;
classProperty.componentType = componentType;
CesiumGltf::Buffer& buffer = model.buffers.emplace_back();
buffer.cesium.data.resize(values.size() * sizeof(T));
std::memcpy(
buffer.cesium.data.data(),
values.data(),
buffer.cesium.data.size());
buffer.byteLength = buffer.cesium.data.size();
CesiumGltf::BufferView& bufferView = model.bufferViews.emplace_back();
bufferView.buffer = static_cast<int32_t>(model.buffers.size() - 1);
bufferView.byteLength = buffer.byteLength;
bufferView.byteOffset = 0;
CesiumGltf::PropertyTableProperty& property =
propertyTable.properties[propertyName];
property.values = static_cast<int32_t>(model.bufferViews.size() - 1);
return property;
}
/**
* @brief Adds the given values to the given model as a property texture
* property in EXT_structural_metadata. This also creates a class property
* definition for the new property in the schema. If the model doesn't already
* contain EXT_structural_metadata, this function adds it.
*
* This assumes the given values are not arrays or strings. The values will be
* stored in a 2x2 image with the correct number of channels.
*
* @returns The newly created property texture property in the model extension.
*/
template <typename T>
CesiumGltf::PropertyTextureProperty& AddPropertyTexturePropertyToModel(
CesiumGltf::Model& model,
CesiumGltf::PropertyTexture& propertyTexture,
const std::string& propertyName,
const std::string& type,
const std::optional<std::string>& componentType,
const std::array<T, 4>& values,
const std::vector<int64_t>& channels) {
CesiumGltf::ExtensionModelExtStructuralMetadata* pExtension =
model.getExtension<CesiumGltf::ExtensionModelExtStructuralMetadata>();
if (pExtension == nullptr) {
pExtension =
&model.addExtension<CesiumGltf::ExtensionModelExtStructuralMetadata>();
}
if (!pExtension->schema) {
pExtension->schema.emplace();
}
CesiumGltf::Schema& schema = *pExtension->schema;
const std::string& className = propertyTexture.classProperty;
CesiumGltf::Class& theClass = schema.classes[className];
CesiumGltf::ClassProperty& classProperty = theClass.properties[propertyName];
classProperty.type = type;
classProperty.componentType = componentType;
CesiumGltf::Image& image = model.images.emplace_back();
image.pAsset.emplace();
image.pAsset->width = 2;
image.pAsset->height = 2;
image.pAsset->channels = sizeof(T);
image.pAsset->bytesPerChannel = 1;
image.pAsset->pixelData.resize(values.size() * sizeof(T));
std::memcpy(
image.pAsset->pixelData.data(),
values.data(),
image.pAsset->pixelData.size());
CesiumGltf::Sampler& sampler = model.samplers.emplace_back();
sampler.wrapS = CesiumGltf::Sampler::WrapS::CLAMP_TO_EDGE;
sampler.wrapT = CesiumGltf::Sampler::WrapT::CLAMP_TO_EDGE;
CesiumGltf::Texture& texture = model.textures.emplace_back();
texture.sampler = static_cast<int32_t>(model.samplers.size() - 1);
texture.source = static_cast<int32_t>(model.images.size() - 1);
CesiumGltf::PropertyTextureProperty& property =
propertyTexture.properties[propertyName];
property.channels = channels;
property.index = static_cast<int32_t>(model.textures.size() - 1);
return property;
}