Skip to content

Commit

Permalink
Merge branch 'imagery-refactor-part-2' into tileset-materials
Browse files Browse the repository at this point in the history
  • Loading branch information
lilleyse committed Jul 12, 2023
2 parents 0d20b17 + 80a0502 commit d81ad75
Show file tree
Hide file tree
Showing 33 changed files with 464 additions and 20 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,9 @@ exts/cesium.omniverse/certs/cacert.pem
# Test output
_testoutput

# Test utils header has components generated by CMake
tests/testUtils.h

# Packman user files
*.user

Expand Down
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -425,6 +425,7 @@ find_package(cpr)
find_package(doctest)
find_package(stb)
find_package(ZLIB)
find_package(yaml-cpp)

# So that the installed libraries can find shared libraries in the same directory
set(CMAKE_INSTALL_RPATH $ORIGIN)
Expand Down
9 changes: 9 additions & 0 deletions ThirdParty.extra.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,14 @@
],
"version": "0.15.0",
"url": "https://github.com/CesiumGS/cesium-native"
},
{
"name": "glTF-Asset-Generator",
"license": [
"MIT"
],
"version": "0.6.1",
"url": "https://github.com/KhronosGroup/glTF-Asset-Generator",
"notes": "A selection of test models from this generator are used for testing."
}
]
17 changes: 17 additions & 0 deletions ThirdParty.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,15 @@
"version": "1.9.0",
"url": "https://docs.libcpr.org/"
},
{
"name": "glTF-Asset-Generator",
"license": [
"MIT"
],
"version": "0.6.1",
"url": "https://github.com/KhronosGroup/glTF-Asset-Generator",
"notes": "A selection of test models from this generator are used for testing."
},
{
"name": "libcurl",
"license": [
Expand Down Expand Up @@ -56,6 +65,14 @@
"version": "cci.20220909",
"url": "https://github.com/nothings/stb"
},
{
"name": "yaml-cpp",
"license": [
"MIT"
],
"version": "0.7.0",
"url": "https://github.com/jbeder/yaml-cpp"
},
{
"name": "zlib",
"license": [
Expand Down
1 change: 1 addition & 0 deletions cmake/AddConanDependencies.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ set(REQUIRES
"pybind11/2.10.1@#561736204506dad955276aaab438aab4"
"stb/cci.20220909@#1c47474f095ef8cd9e4959558525b827"
"zlib/1.2.13@#13c96f538b52e1600c40b88994de240f"
"yaml-cpp/0.7.0@#85b409c274a53d226b71f1bdb9cb4f8b"
"libcurl/7.86.0@#88506b3234d553b90af1ceefc3dd1652"
"nasm/2.15.05@#799d63b1672a337584b09635b0f22fc1")

Expand Down
2 changes: 1 addition & 1 deletion src/core/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,11 @@ setup_lib(
CesiumUsdSchemas
CesiumIonClient
Cesium3DTilesSelection
CesiumAsync
CesiumGeospatial
CesiumGeometry
CesiumGltf
CesiumGltfReader
CesiumAsync
CesiumJsonReader
CesiumUtility
async++
Expand Down
3 changes: 1 addition & 2 deletions src/core/src/FabricPrepareRenderResources.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -109,8 +109,7 @@ std::vector<FabricMesh> acquireFabricMeshes(
auto& fabricMesh = fabricMeshes.emplace_back();

const auto& primitive = model.meshes[mesh.meshId].primitives[mesh.primitiveId];
const auto smoothNormals = mesh.smoothNormals;
const auto fabricGeometry = fabricResourceManager.acquireGeometry(model, primitive, smoothNormals);
const auto fabricGeometry = fabricResourceManager.acquireGeometry(model, primitive, mesh.smoothNormals);
fabricMesh.geometry = fabricGeometry;

const auto shouldAcquireMaterial = FabricResourceManager::getInstance().shouldAcquireMaterial(
Expand Down
5 changes: 5 additions & 0 deletions tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@ include(Macros)

glob_files(SOURCES "${CMAKE_CURRENT_LIST_DIR}/*.cpp")

# replace a string in the utils header with the intended working dir for the test executable
set(TEST_WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}")
configure_file("${CMAKE_CURRENT_LIST_DIR}/testUtils.h.in" "${CMAKE_CURRENT_LIST_DIR}/testUtils.h")

# cmake-format: off
setup_app(
TARGET_NAME
Expand All @@ -11,6 +15,7 @@ setup_app(
LIBRARIES
CesiumOmniverseCore
doctest::doctest
yaml-cpp::yaml-cpp
CXX_FLAGS
${CESIUM_OMNI_CXX_FLAGS}
CXX_FLAGS_DEBUG
Expand Down
58 changes: 57 additions & 1 deletion tests/ExampleTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,27 @@
* A collection of simple tests to demonstrate Doctest
*/

#include "doctestUtils.h"
#include "testUtils.h"

#include <doctest/doctest.h>

#include <array>
#include <cstdint>
#include <iostream>
#include <list>
#include <stdexcept>
#include <vector>

#include <yaml-cpp/yaml.h>

const std::string CONFIG_PATH = "tests/configs/exampleConfig.yaml";

// Test Suites are not required, but this sort of grouping makes it possible
// to select which tests do/don't run via command line options
TEST_SUITE("Example Tests") {
// ----------------------------------------------
// Basic Tests
// ----------------------------------------------

TEST_CASE("The most basic test") {
CHECK(1 + 1 == 2);
Expand Down Expand Up @@ -65,6 +75,52 @@ TEST_SUITE("Example Tests") {
CHECK(item > 0);
}

// ----------------------------------------------
// YAML Config Examples
// ----------------------------------------------

std::string transmogrifier(const std::string& s) {
// an example function with differing output for some scenarios
if (s == "scenario2") {
return "bar";
}
return "foo";
}

void checkAgainstExpectedResults(const std::string& scenarioName, const YAML::Node& expectedResults) {

// we have to specify the type of the desired data from the config via as()
CHECK(3.14159 == expectedResults["pi"].as<double>());
CHECK(2 == expectedResults["onlyEvenPrime"].as<int>());

// as() does work for some non-scalar types, such as vectors, lists, and maps
// for adding custom types to the config, see:
// https://github.com/jbeder/yaml-cpp/wiki/Tutorial#converting-tofrom-native-data-types
const auto fib = expectedResults["fibonacciSeq"].as<std::vector<int>>();
CHECK(fib[2] + fib[3] == fib[4]);

// More complicated checks can be done with helper functions that take the scenario as input
CHECK(transmogrifier(scenarioName) == expectedResults["transmogrifierOutput"].as<std::string>());
}

TEST_CASE("Use a config file to detail multiple scenarios") {

YAML::Node configRoot = YAML::LoadFile(CONFIG_PATH);

// The config file has default parameters and
// an override for one or more scenarios
std::vector<std::string> scenarios = {"scenario1", "scenario2", "scenario3"};

for (const auto& s : scenarios) {
ConfigMap conf = getScenarioConfig(s, configRoot);
checkAgainstExpectedResults(s, conf);
}
}

// ----------------------------------------------
// Misc.
// ----------------------------------------------

TEST_CASE("A few other useful macros") {
// The most common test macro is CHECK, but others are available
// Here are just a few
Expand Down
139 changes: 139 additions & 0 deletions tests/GltfTests.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
#include "testUtils.h"

#include "cesium/omniverse/GltfAccessors.h"
#include "cesium/omniverse/GltfUtil.h"

#include <CesiumGltf/Material.h>
#include <CesiumGltf/MeshPrimitive.h>
#include <CesiumGltf/Model.h>
#include <CesiumGltfReader/GltfReader.h>
#include <doctest/doctest.h>

#include <cstddef>
#include <cstdio>
#include <filesystem>
#include <fstream>
#include <iostream>
#include <optional>
#include <stdexcept>
#include <string>
#include <vector>

#include <gsl/span>
#include <yaml-cpp/yaml.h>

using namespace cesium::omniverse;

const std::string ASSET_DIR = "tests/testAssets/gltfs";
const std::string CONFIG_PATH = "tests/configs/gltfConfig.yaml";

// simplifies casting when comparing some material queries to expected output from config
bool operator==(const glm::dvec3& v3, const std::vector<double>& v) {
return v.size() == 3 && v3[0] == v[0] && v3[1] == v[1] && v3[2] == v[2];
}

TEST_SUITE("Test GltfUtil") {
void checkGltfExpectedResults(const std::filesystem::path& gltfFileName, const YAML::Node& expectedResults) {

// --- Load Gltf ---
std::ifstream gltfStream(gltfFileName, std::ifstream::binary);
gltfStream.seekg(0, std::ios::end);
auto gltfFileLength = gltfStream.tellg();
gltfStream.seekg(0, std::ios::beg);

std::vector<std::byte> gltfBuf(gltfFileLength);
gltfStream.read((char*)&gltfBuf[0], gltfFileLength);

CesiumGltfReader::GltfReader reader;
auto gltf = reader.readGltf(gsl::span(reinterpret_cast<const std::byte*>(gltfBuf.data()), gltfFileLength));

if (!gltf.errors.empty()) {
for (const auto& err : gltf.errors) {
std::cerr << err;
}
throw std::runtime_error("failed to parse model");
}

// gltf.model is a std::optional<CesiumGltf::Model>, make sure it exists
if (!(gltf.model && gltf.model->meshes.size() > 0)) {
throw std::runtime_error("test model is empty");
}

// --- Begin checks ---
const auto& prim = gltf.model->meshes[0].primitives[0];
const auto& model = *gltf.model;

CHECK(GltfUtil::hasNormals(model, prim, false) == expectedResults["hasNormals"].as<bool>());
CHECK(GltfUtil::hasTexcoords(model, prim, 0) == expectedResults["hasTexcoords"].as<bool>());
CHECK(GltfUtil::hasImageryTexcoords(model, prim, 0) == expectedResults["hasImageryTexcoords"].as<bool>());
CHECK(GltfUtil::hasVertexColors(model, prim, 0) == expectedResults["hasVertexColors"].as<bool>());
CHECK(GltfUtil::hasMaterial(prim) == expectedResults["hasMaterial"].as<bool>());

// material tests
if (GltfUtil::hasMaterial(prim)) {
const auto& matInfo = GltfUtil::getMaterialInfo(model, prim);
CHECK(matInfo.alphaCutoff == expectedResults["alphaCutoff"].as<double>());
CHECK(matInfo.alphaMode == expectedResults["alphaMode"].as<int32_t>());
CHECK(matInfo.baseAlpha == expectedResults["baseAlpha"].as<double>());
CHECK(matInfo.baseColorFactor == expectedResults["baseColorFactor"].as<std::vector<double>>());
CHECK(matInfo.emissiveFactor == expectedResults["emissiveFactor"].as<std::vector<double>>());
CHECK(matInfo.metallicFactor == expectedResults["metallicFactor"].as<double>());
CHECK(matInfo.roughnessFactor == expectedResults["roughnessFactor"].as<double>());
CHECK(matInfo.doubleSided == expectedResults["doubleSided"].as<bool>());
CHECK(matInfo.hasVertexColors == expectedResults["hasVertexColors"].as<bool>());
}

// Accessor smoke tests
PositionsAccessor positions;
IndicesAccessor indices;
positions = GltfUtil::getPositions(model, prim);
CHECK(positions.size() > 0);
indices = GltfUtil::getIndices(model, prim, positions);
CHECK(indices.size() > 0);
if (GltfUtil::hasNormals(model, prim, false)) {
CHECK(GltfUtil::getNormals(model, prim, positions, indices, false).size() > 0);
}
if (GltfUtil::hasVertexColors(model, prim, 0)) {
CHECK(GltfUtil::getVertexColors(model, prim, 0).size() > 0);
}
if (GltfUtil::hasTexcoords(model, prim, 0)) {
CHECK(GltfUtil::getTexcoords(model, prim, 0).size() > 0);
}
if (GltfUtil::hasImageryTexcoords(model, prim, 0)) {
CHECK(GltfUtil::getImageryTexcoords(model, prim, 0).size() > 0);
}
CHECK(GltfUtil::getExtent(model, prim) != std::nullopt);
}

TEST_CASE("Default getter smoke tests") {
CHECK_NOTHROW(GltfUtil::getDefaultMaterialInfo());
CHECK_NOTHROW(GltfUtil::getDefaultTextureInfo());
}

TEST_CASE("Check helper functions on various models") {

std::vector<std::string> gltfFiles;

// get list of gltf test files
for (auto const& i : std::filesystem::directory_iterator(ASSET_DIR)) {
std::filesystem::path fname = i.path().filename();
if (fname.extension() == ".gltf" || fname.extension() == ".glb") {
gltfFiles.push_back(fname.string());
}
}

// parse test config yaml
const auto configRoot = YAML::LoadFile(CONFIG_PATH);
const auto basePath = std::filesystem::path(ASSET_DIR);

for (auto const& fileName : gltfFiles) {
// attach filename to any failed checks
CAPTURE(fileName);

const auto conf = getScenarioConfig(fileName, configRoot);

// the / operator concatonates file paths
checkGltfExpectedResults(basePath / fileName, conf);
}
}
}
3 changes: 1 addition & 2 deletions tests/ObjectPoolTests.cpp
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
#include "doctestUtils.h"
#include "testUtils.h"

#include <cesium/omniverse/ObjectPool.h>
#include <doctest/doctest.h>
#include <sys/types.h>

#include <algorithm>
#include <cstdint>
Expand Down
29 changes: 29 additions & 0 deletions tests/configs/exampleConfig.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
---


# One way to use the config file is to generate multiple scenarios with
# variations on some known parameters. If most of the scenarios have a
# parameter at one particular value, it can make sense to establish that as
# the default, then we only need to list the changes from that default.
# See the gltf test config for a real use-case
scenarios:
default:
# currently supported data types for the testUtils methods:
# float
pi : 3.14159
# int
onlyEvenPrime : 2
# string
transmogrifierOutput : "foo"
# sequence
fibonacciSeq :
- 1
- 1
- 2
- 3
- 5


# an example override for a given item
scenario2:
transmogrifierOutput : "bar"
Loading

0 comments on commit d81ad75

Please sign in to comment.