USD/Ctest: Add basic USD-Imaging test.

This adds a basic unit test to check USD has been correctly
build with imaging components to support building both with
the old and new libs, it automatically adds the test when it
detects a library with imaging enabled. (platform devs will
have to pay attention it runs the test to validate the libs
build correctly)

For future use in the code it also defines a USD_HAS_IMAGING
define one could check if we're building against an USD lib
that has it (just because we build/ship with it, doesn't
mean downstream builds will ship with it, so we'll have
to be a little pro-active there)

Reviewed By: sybren

Differential Revision:https://developer.blender.org/D14456
This commit is contained in:
Michael Kowalski 2022-04-16 15:32:48 -06:00 committed by Ray Molenkamp
parent 98eb111568
commit b9f1b64801
5 changed files with 169 additions and 14 deletions

View File

@ -16,6 +16,24 @@ add_definitions(-DPXR_STATIC)
# USD headers use deprecated TBB headers, silence warning.
add_definitions(-DTBB_SUPPRESS_DEPRECATED_MESSAGES=1)
# Check if USD has the imaging headers available, if they are
# add a USD_HAS_IMAGING define so code can dynamically detect this.
# Cleanup of this variable is done at the end of the file since
# test code further down uses it to add imaging tests.
FIND_FILE(USD_IMAGING_HEADERS
NAMES
capsuleAdapter.h
PATHS
${USD_INCLUDE_DIRS}
PATH_SUFFIXES
pxr/usdImaging/usdImaging/
NO_DEFAULT_PATH
)
if(USD_IMAGING_HEADERS)
add_definitions(-DUSD_HAS_IMAGING)
endif()
set(INC
.
../common
@ -129,7 +147,13 @@ target_link_libraries(bf_usd INTERFACE ${TBB_LIBRARIES})
if(WITH_GTESTS)
set(TEST_SRC
tests/usd_stage_creation_test.cc
tests/usd_tests_common.cc
tests/usd_tests_common.h
)
if(USD_IMAGING_HEADERS)
LIST(APPEND TEST_SRC tests/usd_imaging_test.cc)
endif()
set(TEST_INC
)
set(TEST_LIB
@ -137,3 +161,7 @@ if(WITH_GTESTS)
include(GTestTesting)
blender_add_test_lib(bf_io_usd_tests "${TEST_SRC}" "${INC};${TEST_INC}" "${INC_SYS}" "${LIB};${TEST_LIB}")
endif()
# In cmake version 3.21 and up, we can instead use the NO_CACHE option for
# find_file so we don't need to clear it from the cache here.
unset(USD_IMAGING_HEADERS CACHE)

View File

@ -0,0 +1,71 @@
/* SPDX-License-Identifier: GPL-2.0-or-later
* Copyright 2022 Blender Foundation. All rights reserved. */
#include "testing/testing.h"
#include "usd_tests_common.h"
#include <pxr/usd/usd/stage.h>
#include <pxr/usd/usdGeom/capsule.h>
#include <pxr/usdImaging/usdImaging/capsuleAdapter.h>
namespace blender::io::usd {
class USDImagingTest : public testing::Test {
};
TEST_F(USDImagingTest, CapsuleAdapterTest)
{
/* A simple test to exercise the UsdImagingGprimAdapter API to
* ensure the code compiles, links and returns reasonable results.
* We create a capsule shape on an in-memory stage and attempt
* to access the shape's points and topology. */
/* We must register USD plugin paths before creating the stage
* to avoid a crash in the USD asset resolver initialization code. */
if (register_usd_plugins_for_tests().empty()) {
FAIL();
return;
}
pxr::UsdStageRefPtr stage = pxr::UsdStage::CreateInMemory();
if (!stage) {
FAIL() << "Couldn't create in-memory stage.";
return;
}
pxr::UsdGeomCapsule capsule = pxr::UsdGeomCapsule::Define(stage, pxr::SdfPath("/Capsule"));
if (!capsule) {
FAIL() << "Couldn't create UsdGeomCapsule.";
return;
}
pxr::UsdImagingCapsuleAdapter capsule_adapter;
pxr::VtValue points_value = capsule_adapter.GetMeshPoints(capsule.GetPrim(),
pxr::UsdTimeCode::Default());
if (!points_value.IsHolding<pxr::VtArray<pxr::GfVec3f>>()) {
FAIL() << "Mesh points value holding unexpected type.";
return;
}
pxr::VtArray<pxr::GfVec3f> points = points_value.Get<pxr::VtArray<pxr::GfVec3f>>();
EXPECT_FALSE(points.empty());
pxr::VtValue topology_value = capsule_adapter.GetMeshTopology();
if (!topology_value.IsHolding<pxr::HdMeshTopology>()) {
FAIL() << "Mesh topology value holding unexpected type.";
return;
}
pxr::HdMeshTopology topology = topology_value.Get<pxr::HdMeshTopology>();
pxr::VtArray<int> vertex_counts = topology.GetFaceVertexCounts();
EXPECT_FALSE(vertex_counts.empty());
pxr::VtArray<int> vertex_indices = topology.GetFaceVertexIndices();
EXPECT_FALSE(vertex_indices.empty());
}
} // namespace blender::io::usd

View File

@ -2,6 +2,8 @@
* Copyright 2019 Blender Foundation. All rights reserved. */
#include "testing/testing.h"
#include "usd_tests_common.h"
#include <pxr/base/plug/registry.h>
#include <pxr/usd/usd/stage.h>
@ -19,23 +21,12 @@ class USDStageCreationTest : public testing::Test {
TEST_F(USDStageCreationTest, JSONFileLoadingTest)
{
const std::string &release_dir = blender::tests::flags_test_release_dir();
if (release_dir.empty()) {
std::string usd_datafiles_dir = register_usd_plugins_for_tests();
if (usd_datafiles_dir.empty()) {
FAIL();
return;
}
char usd_datafiles_dir[FILE_MAX];
const size_t path_len = BLI_path_join(
usd_datafiles_dir, FILE_MAX, release_dir.c_str(), "datafiles", "usd", nullptr);
/* #BLI_path_join removes trailing slashes, but the USD library requires one in order to
* recognize the path as directory. */
BLI_assert(path_len + 1 < FILE_MAX);
usd_datafiles_dir[path_len] = '/';
usd_datafiles_dir[path_len + 1] = '\0';
pxr::PlugRegistry::GetInstance().RegisterPlugins(usd_datafiles_dir);
/* Simply the ability to create a USD Stage for a specific filename means that the extension
* has been recognized by the USD library, and that a USD plugin has been loaded to write such
* files. Practically, this is a test to see whether the USD JSON files can be found and

View File

@ -0,0 +1,45 @@
/* SPDX-License-Identifier: GPL-2.0-or-later
* Copyright 2022 Blender Foundation. All rights reserved. */
#include "usd_tests_common.h"
#include "testing/testing.h"
#include <pxr/base/plug/registry.h>
#include "BLI_path_util.h"
#include "BLI_utildefines.h"
#include "BKE_appdir.h"
namespace blender::io::usd {
std::string register_usd_plugins_for_tests()
{
static char usd_datafiles_dir[FILE_MAX] = {'\0'};
static bool plugin_path_registered = false;
if (plugin_path_registered) {
return usd_datafiles_dir;
}
plugin_path_registered = true;
const std::string &release_dir = blender::tests::flags_test_release_dir();
if (release_dir.empty()) {
return "";
}
const size_t path_len = BLI_path_join(
usd_datafiles_dir, FILE_MAX, release_dir.c_str(), "datafiles", "usd", nullptr);
/* #BLI_path_join removes trailing slashes, but the USD library requires one in order to
* recognize the path as directory. */
BLI_assert(path_len + 1 < FILE_MAX);
usd_datafiles_dir[path_len] = '/';
usd_datafiles_dir[path_len + 1] = '\0';
pxr::PlugRegistry::GetInstance().RegisterPlugins(usd_datafiles_dir);
return usd_datafiles_dir;
}
} // namespace blender::io::usd

View File

@ -0,0 +1,20 @@
/* SPDX-License-Identifier: GPL-2.0-or-later
* Copyright 2022 Blender Foundation. All rights reserved. */
#pragma once
#include <string>
namespace blender::io::usd {
/* Calls the function to load the USD plugins from the
* USD data directory under the Blender bin directory
* that was supplied as the --test-release-dir flag to ctest.
* Thus function must be called before instantiating a USD
* stage to avoid errors. The returned string is the path to
* the USD data files directory from which the plugins were
* loaded. If the USD data files directory can't be determined,
* plugin registration is skipped and the empty string is
* returned. */
std::string register_usd_plugins_for_tests();
} // namespace blender::io::usd