2053 lines
57 KiB
C++
2053 lines
57 KiB
C++
#include "CesiumGltf/KhrTextureTransform.h"
|
|
#include "CesiumGltf/PropertyTexturePropertyView.h"
|
|
#include "CesiumUtility/Math.h"
|
|
|
|
#include <catch2/catch.hpp>
|
|
#include <gsl/span>
|
|
|
|
#include <climits>
|
|
#include <cstddef>
|
|
#include <vector>
|
|
|
|
using namespace CesiumGltf;
|
|
using namespace CesiumUtility;
|
|
|
|
namespace {
|
|
template <typename T>
|
|
void checkTextureValues(
|
|
const std::vector<uint8_t>& data,
|
|
const std::vector<T>& expected) {
|
|
PropertyTextureProperty property;
|
|
ClassProperty classProperty;
|
|
classProperty.type =
|
|
convertPropertyTypeToString(TypeToPropertyType<T>::value);
|
|
|
|
PropertyComponentType componentType = TypeToPropertyType<T>::component;
|
|
classProperty.componentType =
|
|
convertPropertyComponentTypeToString(componentType);
|
|
|
|
Sampler sampler;
|
|
ImageCesium image;
|
|
image.width = 2;
|
|
image.height = 2;
|
|
image.channels = static_cast<int32_t>(sizeof(T));
|
|
image.bytesPerChannel = 1;
|
|
|
|
std::vector<std::byte>& imageData = image.pixelData;
|
|
imageData.resize(data.size());
|
|
std::memcpy(imageData.data(), data.data(), data.size());
|
|
|
|
property.channels.resize(static_cast<size_t>(image.channels));
|
|
for (size_t i = 0; i < property.channels.size(); i++) {
|
|
property.channels[i] = static_cast<int64_t>(i);
|
|
}
|
|
|
|
PropertyTexturePropertyView<T> view(property, classProperty, sampler, image);
|
|
switch (sizeof(T)) {
|
|
case 1:
|
|
CHECK(view.getSwizzle() == "r");
|
|
break;
|
|
case 2:
|
|
CHECK(view.getSwizzle() == "rg");
|
|
break;
|
|
case 3:
|
|
CHECK(view.getSwizzle() == "rgb");
|
|
break;
|
|
case 4:
|
|
CHECK(view.getSwizzle() == "rgba");
|
|
break;
|
|
default:
|
|
FAIL("Invalid property texture property view type");
|
|
}
|
|
|
|
REQUIRE(!view.normalized());
|
|
|
|
std::vector<glm::dvec2> texCoords{
|
|
glm::dvec2(0, 0),
|
|
glm::dvec2(0.5, 0),
|
|
glm::dvec2(0, 0.5),
|
|
glm::dvec2(0.5, 0.5)};
|
|
|
|
for (size_t i = 0; i < texCoords.size(); i++) {
|
|
glm::dvec2 uv = texCoords[i];
|
|
REQUIRE(view.getRaw(uv[0], uv[1]) == expected[i]);
|
|
REQUIRE(view.get(uv[0], uv[1]) == expected[i]);
|
|
}
|
|
}
|
|
|
|
template <typename T>
|
|
void checkTextureValues(
|
|
const std::vector<uint8_t>& data,
|
|
const std::vector<T>& expectedRaw,
|
|
const std::vector<std::optional<T>>& expectedTransformed,
|
|
const std::optional<JsonValue> offset = std::nullopt,
|
|
const std::optional<JsonValue> scale = std::nullopt,
|
|
const std::optional<JsonValue> noData = std::nullopt,
|
|
const std::optional<JsonValue> defaultValue = std::nullopt) {
|
|
PropertyTextureProperty property;
|
|
ClassProperty classProperty;
|
|
classProperty.type =
|
|
convertPropertyTypeToString(TypeToPropertyType<T>::value);
|
|
|
|
PropertyComponentType componentType = TypeToPropertyType<T>::component;
|
|
classProperty.componentType =
|
|
convertPropertyComponentTypeToString(componentType);
|
|
|
|
classProperty.offset = offset;
|
|
classProperty.scale = scale;
|
|
classProperty.noData = noData;
|
|
classProperty.defaultProperty = defaultValue;
|
|
|
|
Sampler sampler;
|
|
ImageCesium image;
|
|
image.width = 2;
|
|
image.height = 2;
|
|
image.channels = static_cast<int32_t>(sizeof(T));
|
|
image.bytesPerChannel = 1;
|
|
|
|
std::vector<std::byte>& imageData = image.pixelData;
|
|
imageData.resize(data.size());
|
|
std::memcpy(imageData.data(), data.data(), data.size());
|
|
|
|
property.channels.resize(static_cast<size_t>(image.channels));
|
|
for (size_t i = 0; i < property.channels.size(); i++) {
|
|
property.channels[i] = static_cast<int64_t>(i);
|
|
}
|
|
|
|
PropertyTexturePropertyView<T> view(property, classProperty, sampler, image);
|
|
switch (sizeof(T)) {
|
|
case 1:
|
|
CHECK(view.getSwizzle() == "r");
|
|
break;
|
|
case 2:
|
|
CHECK(view.getSwizzle() == "rg");
|
|
break;
|
|
case 3:
|
|
CHECK(view.getSwizzle() == "rgb");
|
|
break;
|
|
case 4:
|
|
CHECK(view.getSwizzle() == "rgba");
|
|
break;
|
|
default:
|
|
FAIL("Invalid property texture property view type");
|
|
}
|
|
|
|
REQUIRE(!view.normalized());
|
|
|
|
std::vector<glm::dvec2> texCoords{
|
|
glm::dvec2(0, 0),
|
|
glm::dvec2(0.5, 0),
|
|
glm::dvec2(0, 0.5),
|
|
glm::dvec2(0.5, 0.5)};
|
|
|
|
for (size_t i = 0; i < texCoords.size(); i++) {
|
|
glm::dvec2 uv = texCoords[i];
|
|
REQUIRE(view.getRaw(uv[0], uv[1]) == expectedRaw[i]);
|
|
REQUIRE(view.get(uv[0], uv[1]) == expectedTransformed[i]);
|
|
}
|
|
}
|
|
|
|
template <typename T, typename D = typename TypeToNormalizedType<T>::type>
|
|
void checkNormalizedTextureValues(
|
|
const std::vector<uint8_t>& data,
|
|
const std::vector<T>& expectedRaw,
|
|
const std::vector<std::optional<D>>& expectedTransformed,
|
|
const std::optional<JsonValue> offset = std::nullopt,
|
|
const std::optional<JsonValue> scale = std::nullopt,
|
|
const std::optional<JsonValue> noData = std::nullopt,
|
|
const std::optional<JsonValue> defaultValue = std::nullopt) {
|
|
PropertyTextureProperty property;
|
|
ClassProperty classProperty;
|
|
classProperty.type =
|
|
convertPropertyTypeToString(TypeToPropertyType<T>::value);
|
|
|
|
PropertyComponentType componentType = TypeToPropertyType<T>::component;
|
|
classProperty.componentType =
|
|
convertPropertyComponentTypeToString(componentType);
|
|
|
|
classProperty.normalized = true;
|
|
|
|
classProperty.offset = offset;
|
|
classProperty.scale = scale;
|
|
classProperty.noData = noData;
|
|
classProperty.defaultProperty = defaultValue;
|
|
|
|
Sampler sampler;
|
|
ImageCesium image;
|
|
image.width = 2;
|
|
image.height = 2;
|
|
image.channels = static_cast<int32_t>(sizeof(T));
|
|
image.bytesPerChannel = 1;
|
|
|
|
std::vector<std::byte>& imageData = image.pixelData;
|
|
imageData.resize(data.size());
|
|
std::memcpy(imageData.data(), data.data(), data.size());
|
|
|
|
property.channels.resize(static_cast<size_t>(image.channels));
|
|
for (size_t i = 0; i < property.channels.size(); i++) {
|
|
property.channels[i] = static_cast<int64_t>(i);
|
|
}
|
|
|
|
PropertyTexturePropertyView<T, true> view(
|
|
property,
|
|
classProperty,
|
|
sampler,
|
|
image);
|
|
switch (sizeof(T)) {
|
|
case 1:
|
|
CHECK(view.getSwizzle() == "r");
|
|
break;
|
|
case 2:
|
|
CHECK(view.getSwizzle() == "rg");
|
|
break;
|
|
case 3:
|
|
CHECK(view.getSwizzle() == "rgb");
|
|
break;
|
|
case 4:
|
|
CHECK(view.getSwizzle() == "rgba");
|
|
break;
|
|
default:
|
|
FAIL("Invalid property texture property view type");
|
|
}
|
|
|
|
REQUIRE(view.normalized());
|
|
|
|
std::vector<glm::dvec2> texCoords{
|
|
glm::dvec2(0, 0),
|
|
glm::dvec2(0.5, 0),
|
|
glm::dvec2(0, 0.5),
|
|
glm::dvec2(0.5, 0.5)};
|
|
|
|
for (size_t i = 0; i < texCoords.size(); i++) {
|
|
glm::dvec2 uv = texCoords[i];
|
|
REQUIRE(view.getRaw(uv[0], uv[1]) == expectedRaw[i]);
|
|
REQUIRE(view.get(uv[0], uv[1]) == expectedTransformed[i]);
|
|
}
|
|
}
|
|
|
|
template <typename T>
|
|
void checkTextureArrayValues(
|
|
const std::vector<uint8_t>& data,
|
|
const int64_t count,
|
|
const std::vector<std::vector<T>>& expected) {
|
|
PropertyTextureProperty property;
|
|
ClassProperty classProperty;
|
|
classProperty.type =
|
|
convertPropertyTypeToString(TypeToPropertyType<T>::value);
|
|
|
|
PropertyComponentType componentType = TypeToPropertyType<T>::component;
|
|
classProperty.componentType =
|
|
convertPropertyComponentTypeToString(componentType);
|
|
|
|
classProperty.array = true;
|
|
classProperty.count = count;
|
|
|
|
Sampler sampler;
|
|
ImageCesium image;
|
|
image.width = 2;
|
|
image.height = 2;
|
|
image.channels =
|
|
static_cast<int32_t>(count) * static_cast<int32_t>(sizeof(T));
|
|
image.bytesPerChannel = 1;
|
|
|
|
std::vector<std::byte>& imageData = image.pixelData;
|
|
imageData.resize(data.size());
|
|
std::memcpy(imageData.data(), data.data(), data.size());
|
|
|
|
property.channels.resize(static_cast<size_t>(image.channels));
|
|
for (size_t i = 0; i < property.channels.size(); i++) {
|
|
property.channels[i] = static_cast<int64_t>(i);
|
|
}
|
|
|
|
PropertyTexturePropertyView<PropertyArrayView<T>> view(
|
|
property,
|
|
classProperty,
|
|
sampler,
|
|
image);
|
|
switch (image.channels) {
|
|
case 1:
|
|
CHECK(view.getSwizzle() == "r");
|
|
break;
|
|
case 2:
|
|
CHECK(view.getSwizzle() == "rg");
|
|
break;
|
|
case 3:
|
|
CHECK(view.getSwizzle() == "rgb");
|
|
break;
|
|
case 4:
|
|
CHECK(view.getSwizzle() == "rgba");
|
|
break;
|
|
default:
|
|
FAIL("Unsupported count value");
|
|
}
|
|
|
|
REQUIRE(!view.normalized());
|
|
|
|
std::vector<glm::dvec2> texCoords{
|
|
glm::dvec2(0, 0),
|
|
glm::dvec2(0.5, 0),
|
|
glm::dvec2(0, 0.5),
|
|
glm::dvec2(0.5, 0.5)};
|
|
|
|
for (size_t i = 0; i < texCoords.size(); i++) {
|
|
const std::vector<T>& expectedValue = expected[i];
|
|
glm::dvec2 uv = texCoords[i];
|
|
|
|
auto value = view.getRaw(uv[0], uv[1]);
|
|
REQUIRE(static_cast<size_t>(value.size()) == expectedValue.size());
|
|
|
|
auto maybeValue = view.get(uv[0], uv[1]);
|
|
REQUIRE(maybeValue);
|
|
REQUIRE(maybeValue->size() == value.size());
|
|
for (int64_t j = 0; j < value.size(); j++) {
|
|
REQUIRE(value[j] == expectedValue[static_cast<size_t>(j)]);
|
|
REQUIRE((*maybeValue)[j] == value[j]);
|
|
}
|
|
}
|
|
}
|
|
|
|
template <typename T>
|
|
void checkTextureArrayValues(
|
|
const std::vector<uint8_t>& data,
|
|
const int64_t count,
|
|
const std::vector<std::vector<T>>& expectedRaw,
|
|
const std::vector<std::optional<std::vector<T>>>& expectedTransformed,
|
|
const std::optional<JsonValue> noData = std::nullopt,
|
|
const std::optional<JsonValue> defaultValue = std::nullopt) {
|
|
PropertyTextureProperty property;
|
|
ClassProperty classProperty;
|
|
classProperty.type =
|
|
convertPropertyTypeToString(TypeToPropertyType<T>::value);
|
|
|
|
PropertyComponentType componentType = TypeToPropertyType<T>::component;
|
|
classProperty.componentType =
|
|
convertPropertyComponentTypeToString(componentType);
|
|
|
|
classProperty.array = true;
|
|
classProperty.count = count;
|
|
classProperty.noData = noData;
|
|
classProperty.defaultProperty = defaultValue;
|
|
|
|
Sampler sampler;
|
|
ImageCesium image;
|
|
image.width = 2;
|
|
image.height = 2;
|
|
image.channels =
|
|
static_cast<int32_t>(count) * static_cast<int32_t>(sizeof(T));
|
|
image.bytesPerChannel = 1;
|
|
|
|
std::vector<std::byte>& imageData = image.pixelData;
|
|
imageData.resize(data.size());
|
|
std::memcpy(imageData.data(), data.data(), data.size());
|
|
|
|
property.channels.resize(static_cast<size_t>(image.channels));
|
|
for (size_t i = 0; i < property.channels.size(); i++) {
|
|
property.channels[i] = static_cast<int64_t>(i);
|
|
}
|
|
|
|
PropertyTexturePropertyView<PropertyArrayView<T>> view(
|
|
property,
|
|
classProperty,
|
|
sampler,
|
|
image);
|
|
switch (count) {
|
|
case 1:
|
|
CHECK(view.getSwizzle() == "r");
|
|
break;
|
|
case 2:
|
|
CHECK(view.getSwizzle() == "rg");
|
|
break;
|
|
case 3:
|
|
CHECK(view.getSwizzle() == "rgb");
|
|
break;
|
|
case 4:
|
|
CHECK(view.getSwizzle() == "rgba");
|
|
break;
|
|
default:
|
|
FAIL("Unsupported count value");
|
|
}
|
|
|
|
REQUIRE(!view.normalized());
|
|
|
|
std::vector<glm::dvec2> texCoords{
|
|
glm::dvec2(0, 0),
|
|
glm::dvec2(0.5, 0),
|
|
glm::dvec2(0, 0.5),
|
|
glm::dvec2(0.5, 0.5)};
|
|
|
|
for (size_t i = 0; i < texCoords.size(); i++) {
|
|
auto expectedRawValue = expectedRaw[i];
|
|
glm::dvec2 uv = texCoords[i];
|
|
|
|
// Check raw values first
|
|
auto rawValue = view.getRaw(uv[0], uv[1]);
|
|
REQUIRE(static_cast<size_t>(rawValue.size()) == expectedRawValue.size());
|
|
for (int64_t j = 0; j < rawValue.size(); j++) {
|
|
REQUIRE(rawValue[j] == expectedRawValue[static_cast<size_t>(j)]);
|
|
}
|
|
|
|
// Check transformed values
|
|
auto maybeValue = view.get(uv[0], uv[1]);
|
|
if (!maybeValue) {
|
|
REQUIRE(!expectedTransformed[i]);
|
|
continue;
|
|
}
|
|
|
|
auto expectedValue = *(expectedTransformed[i]);
|
|
REQUIRE(maybeValue->size() == static_cast<int64_t>(expectedValue.size()));
|
|
for (int64_t j = 0; j < maybeValue->size(); j++) {
|
|
REQUIRE((*maybeValue)[j] == expectedValue[static_cast<size_t>(j)]);
|
|
}
|
|
}
|
|
}
|
|
|
|
template <typename T, typename D = typename TypeToNormalizedType<T>::type>
|
|
void checkNormalizedTextureArrayValues(
|
|
const std::vector<uint8_t>& data,
|
|
const int64_t count,
|
|
const std::vector<std::vector<T>>& expectedRaw,
|
|
const std::vector<std::optional<std::vector<D>>>& expectedTransformed,
|
|
const std::optional<JsonValue> offset = std::nullopt,
|
|
const std::optional<JsonValue> scale = std::nullopt,
|
|
const std::optional<JsonValue> noData = std::nullopt,
|
|
const std::optional<JsonValue> defaultValue = std::nullopt) {
|
|
PropertyTextureProperty property;
|
|
ClassProperty classProperty;
|
|
classProperty.type =
|
|
convertPropertyTypeToString(TypeToPropertyType<T>::value);
|
|
|
|
PropertyComponentType componentType = TypeToPropertyType<T>::component;
|
|
classProperty.componentType =
|
|
convertPropertyComponentTypeToString(componentType);
|
|
|
|
classProperty.array = true;
|
|
classProperty.count = count;
|
|
classProperty.normalized = true;
|
|
classProperty.offset = offset;
|
|
classProperty.scale = scale;
|
|
classProperty.noData = noData;
|
|
classProperty.defaultProperty = defaultValue;
|
|
|
|
Sampler sampler;
|
|
ImageCesium image;
|
|
image.width = 2;
|
|
image.height = 2;
|
|
image.channels =
|
|
static_cast<int32_t>(count) * static_cast<int32_t>(sizeof(T));
|
|
image.bytesPerChannel = 1;
|
|
|
|
std::vector<std::byte>& imageData = image.pixelData;
|
|
imageData.resize(data.size());
|
|
std::memcpy(imageData.data(), data.data(), data.size());
|
|
|
|
property.channels.resize(static_cast<size_t>(image.channels));
|
|
for (size_t i = 0; i < property.channels.size(); i++) {
|
|
property.channels[i] = static_cast<int64_t>(i);
|
|
}
|
|
|
|
PropertyTexturePropertyView<PropertyArrayView<T>, true> view(
|
|
property,
|
|
classProperty,
|
|
sampler,
|
|
image);
|
|
switch (image.channels) {
|
|
case 1:
|
|
CHECK(view.getSwizzle() == "r");
|
|
break;
|
|
case 2:
|
|
CHECK(view.getSwizzle() == "rg");
|
|
break;
|
|
case 3:
|
|
CHECK(view.getSwizzle() == "rgb");
|
|
break;
|
|
case 4:
|
|
CHECK(view.getSwizzle() == "rgba");
|
|
break;
|
|
default:
|
|
FAIL("Unsupported count value");
|
|
}
|
|
|
|
REQUIRE(view.normalized());
|
|
|
|
std::vector<glm::dvec2> texCoords{
|
|
glm::dvec2(0, 0),
|
|
glm::dvec2(0.5, 0),
|
|
glm::dvec2(0, 0.5),
|
|
glm::dvec2(0.5, 0.5)};
|
|
|
|
for (size_t i = 0; i < texCoords.size(); i++) {
|
|
auto expectedRawValue = expectedRaw[i];
|
|
glm::dvec2 uv = texCoords[i];
|
|
|
|
// Check raw values first
|
|
auto rawValue = view.getRaw(uv[0], uv[1]);
|
|
REQUIRE(static_cast<size_t>(rawValue.size()) == expectedRawValue.size());
|
|
for (int64_t j = 0; j < rawValue.size(); j++) {
|
|
REQUIRE(rawValue[j] == expectedRawValue[static_cast<size_t>(j)]);
|
|
}
|
|
|
|
// Check transformed values
|
|
auto maybeValue = view.get(uv[0], uv[1]);
|
|
if (!maybeValue) {
|
|
REQUIRE(!expectedTransformed[i]);
|
|
continue;
|
|
}
|
|
|
|
auto expectedValue = *(expectedTransformed[i]);
|
|
REQUIRE(maybeValue->size() == static_cast<int64_t>(expectedValue.size()));
|
|
for (int64_t j = 0; j < maybeValue->size(); j++) {
|
|
REQUIRE((*maybeValue)[j] == expectedValue[static_cast<size_t>(j)]);
|
|
}
|
|
}
|
|
}
|
|
} // namespace
|
|
|
|
TEST_CASE("Check scalar PropertyTexturePropertyView") {
|
|
SECTION("uint8_t") {
|
|
std::vector<uint8_t> data{12, 33, 56, 67};
|
|
checkTextureValues(data, data);
|
|
}
|
|
|
|
SECTION("int8_t") {
|
|
std::vector<uint8_t> data{255, 0, 223, 67};
|
|
std::vector<int8_t> expected{-1, 0, -33, 67};
|
|
checkTextureValues(data, expected);
|
|
}
|
|
|
|
SECTION("uint16_t") {
|
|
// clang-format off
|
|
std::vector<uint8_t> data{
|
|
28, 0,
|
|
1, 1,
|
|
0, 3,
|
|
182, 1};
|
|
// clang-format on
|
|
std::vector<uint16_t> expected{28, 257, 768, 438};
|
|
checkTextureValues(data, expected);
|
|
}
|
|
|
|
SECTION("int16_t") {
|
|
// clang-format off
|
|
std::vector<uint8_t> data{
|
|
255, 255,
|
|
1, 129,
|
|
0, 3,
|
|
182, 1};
|
|
// clang-format on
|
|
std::vector<int16_t> expected{-1, -32511, 768, 438};
|
|
checkTextureValues(data, expected);
|
|
}
|
|
|
|
SECTION("uint32_t") {
|
|
// clang-format off
|
|
std::vector<uint8_t> data{
|
|
0, 0, 0, 1,
|
|
9, 0, 1, 0,
|
|
20, 2, 2, 0,
|
|
8, 1, 0, 1};
|
|
// clang-format on
|
|
std::vector<uint32_t> expected{16777216, 65545, 131604, 16777480};
|
|
checkTextureValues(data, expected);
|
|
}
|
|
|
|
SECTION("int32_t") {
|
|
// clang-format off
|
|
std::vector<uint8_t> data{
|
|
255, 255, 255, 255,
|
|
9, 0, 1, 0,
|
|
20, 2, 2, 255,
|
|
8, 1, 0, 1};
|
|
// clang-format on
|
|
std::vector<int32_t> expected{-1, 65545, -16645612, 16777480};
|
|
checkTextureValues(data, expected);
|
|
}
|
|
|
|
SECTION("float") {
|
|
// clang-format off
|
|
std::vector<uint8_t> data{
|
|
0, 0, 0, 1,
|
|
9, 0, 1, 0,
|
|
20, 2, 2, 0,
|
|
8, 1, 0, 1};
|
|
// clang-format on
|
|
|
|
std::vector<uint32_t> expectedUint{16777216, 65545, 131604, 16777480};
|
|
std::vector<float> expected(expectedUint.size());
|
|
for (size_t i = 0; i < expectedUint.size(); i++) {
|
|
float value = *reinterpret_cast<float*>(&expectedUint[i]);
|
|
expected[i] = value;
|
|
}
|
|
|
|
checkTextureValues(data, expected);
|
|
}
|
|
|
|
SECTION("float with offset / scale") {
|
|
// clang-format off
|
|
std::vector<uint8_t> data{
|
|
0, 0, 0, 1,
|
|
9, 0, 1, 0,
|
|
20, 2, 2, 0,
|
|
8, 1, 0, 1};
|
|
// clang-format on
|
|
|
|
std::vector<uint32_t> expectedUint{16777216, 65545, 131604, 16777480};
|
|
std::vector<float> expectedRaw(expectedUint.size());
|
|
std::vector<std::optional<float>> expectedTransformed(expectedUint.size());
|
|
|
|
const float offset = 1.0f;
|
|
const float scale = 2.0f;
|
|
|
|
for (size_t i = 0; i < expectedUint.size(); i++) {
|
|
float value = *reinterpret_cast<float*>(&expectedUint[i]);
|
|
expectedRaw[i] = value;
|
|
expectedTransformed[i] = value * scale + offset;
|
|
}
|
|
|
|
checkTextureValues(data, expectedRaw, expectedTransformed, offset, scale);
|
|
}
|
|
|
|
SECTION("uint8_t with noData") {
|
|
std::vector<uint8_t> data{12, 33, 0, 128, 0, 56, 67};
|
|
const uint8_t noData = 0;
|
|
std::vector<std::optional<uint8_t>> expected{
|
|
data[0],
|
|
data[1],
|
|
std::nullopt,
|
|
data[3],
|
|
std::nullopt,
|
|
data[5],
|
|
data[6]};
|
|
checkTextureValues(
|
|
data,
|
|
data,
|
|
expected,
|
|
std::nullopt,
|
|
std::nullopt,
|
|
noData);
|
|
}
|
|
|
|
SECTION("uint8_t with noData and defaultValue") {
|
|
std::vector<uint8_t> data{12, 33, 0, 128, 0, 56, 67};
|
|
const uint8_t noData = 0;
|
|
const uint8_t defaultValue = 255;
|
|
std::vector<std::optional<uint8_t>> expected{
|
|
data[0],
|
|
data[1],
|
|
defaultValue,
|
|
data[3],
|
|
defaultValue,
|
|
data[5],
|
|
data[6]};
|
|
checkTextureValues(
|
|
data,
|
|
data,
|
|
expected,
|
|
std::nullopt,
|
|
std::nullopt,
|
|
noData,
|
|
defaultValue);
|
|
}
|
|
}
|
|
|
|
TEST_CASE("Check scalar PropertyTexturePropertyView (normalized)") {
|
|
SECTION("uint8_t") {
|
|
std::vector<uint8_t> data{12, 33, 56, 67};
|
|
std::vector<std::optional<double>> expected{
|
|
12.0 / 255.0,
|
|
33 / 255.0,
|
|
56 / 255.0,
|
|
67 / 255.0};
|
|
checkNormalizedTextureValues(data, data, expected);
|
|
}
|
|
|
|
SECTION("int16_t") {
|
|
// clang-format off
|
|
std::vector<uint8_t> data{
|
|
255, 255,
|
|
1, 129,
|
|
0, 3,
|
|
182, 1};
|
|
// clang-format on
|
|
std::vector<int16_t> expectedRaw{-1, -32511, 768, 438};
|
|
std::vector<std::optional<double>> expectedTransformed{
|
|
normalize(expectedRaw[0]),
|
|
normalize(expectedRaw[1]),
|
|
normalize(expectedRaw[2]),
|
|
normalize(expectedRaw[3])};
|
|
checkNormalizedTextureValues(data, expectedRaw, expectedTransformed);
|
|
}
|
|
|
|
SECTION("uint32_t") {
|
|
// clang-format off
|
|
std::vector<uint8_t> data{
|
|
0, 0, 0, 1,
|
|
9, 0, 1, 0,
|
|
20, 2, 2, 0,
|
|
8, 1, 0, 1};
|
|
// clang-format on
|
|
std::vector<uint32_t> expectedRaw{16777216, 65545, 131604, 16777480};
|
|
std::vector<std::optional<double>> expectedTransformed{
|
|
normalize(expectedRaw[0]),
|
|
normalize(expectedRaw[1]),
|
|
normalize(expectedRaw[2]),
|
|
normalize(expectedRaw[3])};
|
|
checkNormalizedTextureValues(data, expectedRaw, expectedTransformed);
|
|
}
|
|
|
|
SECTION("uint8_t with offset / scale") {
|
|
std::vector<uint8_t> data{12, 33, 56, 67};
|
|
const double offset = 1.0;
|
|
const double scale = 2.0;
|
|
std::vector<std::optional<double>> expected{
|
|
normalize(data[0]) * scale + offset,
|
|
normalize(data[1]) * scale + offset,
|
|
normalize(data[2]) * scale + offset,
|
|
normalize(data[3]) * scale + offset,
|
|
};
|
|
checkNormalizedTextureValues(data, data, expected, offset, scale);
|
|
}
|
|
|
|
SECTION("uint8_t with all properties") {
|
|
std::vector<uint8_t> data{12, 33, 56, 0};
|
|
const double offset = 1.0;
|
|
const double scale = 2.0;
|
|
const uint8_t noData = 0;
|
|
const double defaultValue = 10.0;
|
|
std::vector<std::optional<double>> expected{
|
|
normalize(data[0]) * scale + offset,
|
|
normalize(data[1]) * scale + offset,
|
|
normalize(data[2]) * scale + offset,
|
|
10.0,
|
|
};
|
|
checkNormalizedTextureValues(
|
|
data,
|
|
data,
|
|
expected,
|
|
offset,
|
|
scale,
|
|
noData,
|
|
defaultValue);
|
|
}
|
|
}
|
|
|
|
TEST_CASE("Check vecN PropertyTexturePropertyView") {
|
|
SECTION("glm::u8vec2") {
|
|
// clang-format off
|
|
std::vector<uint8_t> data{
|
|
28, 0,
|
|
1, 1,
|
|
0, 3,
|
|
182, 1};
|
|
// clang-format on
|
|
std::vector<glm::u8vec2> expected{
|
|
glm::u8vec2(28, 0),
|
|
glm::u8vec2(1, 1),
|
|
glm::u8vec2(0, 3),
|
|
glm::u8vec2(182, 1)};
|
|
checkTextureValues(data, expected);
|
|
}
|
|
|
|
SECTION("glm::i8vec2") {
|
|
// clang-format off
|
|
std::vector<uint8_t> data{
|
|
28, 255,
|
|
254, 1,
|
|
0, 3,
|
|
182, 1};
|
|
// clang-format on
|
|
std::vector<glm::i8vec2> expected{
|
|
glm::i8vec2(28, -1),
|
|
glm::i8vec2(-2, 1),
|
|
glm::i8vec2(0, 3),
|
|
glm::i8vec2(-74, 1)};
|
|
checkTextureValues(data, expected);
|
|
}
|
|
|
|
SECTION("glm::u8vec3") {
|
|
// clang-format off
|
|
std::vector<uint8_t> data{
|
|
1, 2, 3,
|
|
4, 5, 6,
|
|
7, 8, 9,
|
|
0, 5, 2};
|
|
// clang-format on
|
|
std::vector<glm::u8vec3> expected{
|
|
glm::u8vec3(1, 2, 3),
|
|
glm::u8vec3(4, 5, 6),
|
|
glm::u8vec3(7, 8, 9),
|
|
glm::u8vec3(0, 5, 2)};
|
|
checkTextureValues(data, expected);
|
|
}
|
|
|
|
SECTION("glm::i8vec3") {
|
|
// clang-format off
|
|
std::vector<uint8_t> data{
|
|
255, 2, 3,
|
|
4, 254, 6,
|
|
7, 8, 159,
|
|
0, 5, 2};
|
|
// clang-format on
|
|
std::vector<glm::i8vec3> expected{
|
|
glm::i8vec3(-1, 2, 3),
|
|
glm::i8vec3(4, -2, 6),
|
|
glm::i8vec3(7, 8, -97),
|
|
glm::i8vec3(0, 5, 2)};
|
|
checkTextureValues(data, expected);
|
|
}
|
|
|
|
SECTION("glm::u8vec4") {
|
|
// clang-format off
|
|
std::vector<uint8_t> data{
|
|
1, 2, 3, 0,
|
|
4, 5, 6, 11,
|
|
7, 8, 9, 3,
|
|
0, 5, 2, 27};
|
|
// clang-format on
|
|
std::vector<glm::u8vec4> expected{
|
|
glm::u8vec4(1, 2, 3, 0),
|
|
glm::u8vec4(4, 5, 6, 11),
|
|
glm::u8vec4(7, 8, 9, 3),
|
|
glm::u8vec4(0, 5, 2, 27)};
|
|
checkTextureValues(data, expected);
|
|
}
|
|
|
|
SECTION("glm::i8vec4") {
|
|
// clang-format off
|
|
std::vector<uint8_t> data{
|
|
1, 200, 3, 0,
|
|
4, 5, 6, 251,
|
|
129, 8, 9, 3,
|
|
0, 155, 2, 27};
|
|
// clang-format on
|
|
std::vector<glm::i8vec4> expected{
|
|
glm::i8vec4(1, -56, 3, 0),
|
|
glm::i8vec4(4, 5, 6, -5),
|
|
glm::i8vec4(-127, 8, 9, 3),
|
|
glm::i8vec4(0, -101, 2, 27)};
|
|
checkTextureValues(data, expected);
|
|
}
|
|
|
|
SECTION("glm::u16vec2") {
|
|
// clang-format off
|
|
std::vector<uint8_t> data{
|
|
0, 0, 0, 1,
|
|
9, 0, 1, 0,
|
|
20, 2, 2, 0,
|
|
8, 1, 0, 1};
|
|
// clang-format on
|
|
std::vector<glm::u16vec2> expected{
|
|
glm::u16vec2(0, 256),
|
|
glm::u16vec2(9, 1),
|
|
glm::u16vec2(532, 2),
|
|
glm::u16vec2(264, 256)};
|
|
checkTextureValues(data, expected);
|
|
}
|
|
|
|
SECTION("glm::i16vec2") {
|
|
// clang-format off
|
|
std::vector<uint8_t> data{
|
|
255, 255, 0, 1,
|
|
9, 0, 146, 195,
|
|
20, 2, 2, 0,
|
|
8, 1, 255, 1};
|
|
// clang-format on
|
|
std::vector<glm::i16vec2> expected{
|
|
glm::i16vec2(-1, 256),
|
|
glm::i16vec2(9, -15470),
|
|
glm::i16vec2(532, 2),
|
|
glm::i16vec2(264, 511)};
|
|
checkTextureValues(data, expected);
|
|
}
|
|
|
|
SECTION("glm::i8vec2 with noData") {
|
|
// clang-format off
|
|
std::vector<uint8_t> data{
|
|
28, 255,
|
|
254, 1,
|
|
0, 3,
|
|
0, 0,
|
|
182, 1};
|
|
// clang-format on
|
|
JsonValue::Array noData{0, 0};
|
|
std::vector<glm::i8vec2> expectedRaw{
|
|
glm::i8vec2(28, -1),
|
|
glm::i8vec2(-2, 1),
|
|
glm::i8vec2(0, 3),
|
|
glm::i8vec2(0),
|
|
glm::i8vec2(-74, 1)};
|
|
std::vector<std::optional<glm::i8vec2>> expectedTransformed{
|
|
glm::i8vec2(28, -1),
|
|
glm::i8vec2(-2, 1),
|
|
glm::i8vec2(0, 3),
|
|
std::nullopt,
|
|
glm::i8vec2(-74, 1)};
|
|
checkTextureValues(
|
|
data,
|
|
expectedRaw,
|
|
expectedTransformed,
|
|
std::nullopt,
|
|
std::nullopt,
|
|
noData);
|
|
}
|
|
|
|
SECTION("glm::i8vec2 with defaultValue") {
|
|
// clang-format off
|
|
std::vector<uint8_t> data{
|
|
28, 255,
|
|
254, 1,
|
|
0, 3,
|
|
0, 0,
|
|
182, 1};
|
|
// clang-format on
|
|
JsonValue::Array noData{0, 0};
|
|
JsonValue::Array defaultValue{127, 127};
|
|
std::vector<glm::i8vec2> expectedRaw{
|
|
glm::i8vec2(28, -1),
|
|
glm::i8vec2(-2, 1),
|
|
glm::i8vec2(0, 3),
|
|
glm::i8vec2(0, 0),
|
|
glm::i8vec2(-74, 1)};
|
|
std::vector<std::optional<glm::i8vec2>> expectedTransformed{
|
|
glm::i8vec2(28, -1),
|
|
glm::i8vec2(-2, 1),
|
|
glm::i8vec2(0, 3),
|
|
glm::i8vec2(127, 127),
|
|
glm::i8vec2(-74, 1)};
|
|
checkTextureValues(
|
|
data,
|
|
expectedRaw,
|
|
expectedTransformed,
|
|
std::nullopt,
|
|
std::nullopt,
|
|
noData,
|
|
defaultValue);
|
|
}
|
|
}
|
|
|
|
TEST_CASE("Check vecN PropertyTexturePropertyView (normalized)") {
|
|
SECTION("glm::i8vec2") {
|
|
// clang-format off
|
|
std::vector<uint8_t> data{
|
|
28, 255,
|
|
254, 1,
|
|
0, 3,
|
|
182, 1};
|
|
// clang-format on
|
|
std::vector<glm::i8vec2> expectedRaw{
|
|
glm::i8vec2(28, -1),
|
|
glm::i8vec2(-2, 1),
|
|
glm::i8vec2(0, 3),
|
|
glm::i8vec2(-74, 1)};
|
|
std::vector<std::optional<glm::dvec2>> expectedTransformed{
|
|
normalize(expectedRaw[0]),
|
|
normalize(expectedRaw[1]),
|
|
normalize(expectedRaw[2]),
|
|
normalize(expectedRaw[3])};
|
|
checkNormalizedTextureValues(data, expectedRaw, expectedTransformed);
|
|
}
|
|
|
|
SECTION("glm::u8vec3") {
|
|
// clang-format off
|
|
std::vector<uint8_t> data{
|
|
1, 2, 3,
|
|
4, 5, 6,
|
|
7, 8, 9,
|
|
0, 5, 2};
|
|
// clang-format on
|
|
std::vector<glm::u8vec3> expectedRaw{
|
|
glm::u8vec3(1, 2, 3),
|
|
glm::u8vec3(4, 5, 6),
|
|
glm::u8vec3(7, 8, 9),
|
|
glm::u8vec3(0, 5, 2)};
|
|
std::vector<std::optional<glm::dvec3>> expectedTransformed{
|
|
normalize(expectedRaw[0]),
|
|
normalize(expectedRaw[1]),
|
|
normalize(expectedRaw[2]),
|
|
normalize(expectedRaw[3])};
|
|
checkNormalizedTextureValues(data, expectedRaw, expectedTransformed);
|
|
}
|
|
|
|
SECTION("glm::u8vec4") {
|
|
// clang-format off
|
|
std::vector<uint8_t> data{
|
|
1, 2, 3, 0,
|
|
4, 5, 6, 11,
|
|
7, 8, 9, 3,
|
|
0, 5, 2, 27};
|
|
// clang-format on
|
|
std::vector<glm::u8vec4> expectedRaw{
|
|
glm::u8vec4(1, 2, 3, 0),
|
|
glm::u8vec4(4, 5, 6, 11),
|
|
glm::u8vec4(7, 8, 9, 3),
|
|
glm::u8vec4(0, 5, 2, 27)};
|
|
std::vector<std::optional<glm::dvec4>> expectedTransformed{
|
|
normalize(expectedRaw[0]),
|
|
normalize(expectedRaw[1]),
|
|
normalize(expectedRaw[2]),
|
|
normalize(expectedRaw[3])};
|
|
checkNormalizedTextureValues(data, expectedRaw, expectedTransformed);
|
|
}
|
|
|
|
SECTION("glm::i16vec2") {
|
|
// clang-format off
|
|
std::vector<uint8_t> data{
|
|
255, 255, 0, 1,
|
|
9, 0, 146, 195,
|
|
20, 2, 2, 0,
|
|
8, 1, 255, 1};
|
|
// clang-format on
|
|
std::vector<glm::i16vec2> expectedRaw{
|
|
glm::i16vec2(-1, 256),
|
|
glm::i16vec2(9, -15470),
|
|
glm::i16vec2(532, 2),
|
|
glm::i16vec2(264, 511)};
|
|
std::vector<std::optional<glm::dvec2>> expectedTransformed{
|
|
normalize(expectedRaw[0]),
|
|
normalize(expectedRaw[1]),
|
|
normalize(expectedRaw[2]),
|
|
normalize(expectedRaw[3])};
|
|
checkNormalizedTextureValues(data, expectedRaw, expectedTransformed);
|
|
}
|
|
|
|
SECTION("glm::i8vec2 with offset / scale") {
|
|
// clang-format off
|
|
std::vector<uint8_t> data{
|
|
28, 255,
|
|
254, 1,
|
|
0, 3,
|
|
0, 0,
|
|
182, 1};
|
|
// clang-format on
|
|
const glm::dvec2 offset(-1.0, 4.0);
|
|
const glm::dvec2 scale(2.0, 1.0);
|
|
|
|
std::vector<glm::i8vec2> expectedRaw{
|
|
glm::i8vec2(28, -1),
|
|
glm::i8vec2(-2, 1),
|
|
glm::i8vec2(0, 3),
|
|
glm::i8vec2(0),
|
|
glm::i8vec2(-74, 1)};
|
|
std::vector<std::optional<glm::dvec2>> expectedTransformed{
|
|
normalize(expectedRaw[0]) * scale + offset,
|
|
normalize(expectedRaw[1]) * scale + offset,
|
|
normalize(expectedRaw[2]) * scale + offset,
|
|
normalize(expectedRaw[3]) * scale + offset,
|
|
normalize(expectedRaw[4]) * scale + offset,
|
|
};
|
|
checkNormalizedTextureValues(
|
|
data,
|
|
expectedRaw,
|
|
expectedTransformed,
|
|
JsonValue::Array{offset[0], offset[1]},
|
|
JsonValue::Array{scale[0], scale[1]});
|
|
}
|
|
|
|
SECTION("glm::i8vec2 with all properties") {
|
|
// clang-format off
|
|
std::vector<uint8_t> data{
|
|
28, 255,
|
|
254, 1,
|
|
0, 3,
|
|
0, 0,
|
|
182, 1};
|
|
// clang-format on
|
|
const glm::dvec2 offset(-1.0, 4.0);
|
|
const glm::dvec2 scale(2.0, 1.0);
|
|
const glm::i8vec2 noData(0);
|
|
const glm::dvec2 defaultValue(100.0, 5.5);
|
|
|
|
std::vector<glm::i8vec2> expectedRaw{
|
|
glm::i8vec2(28, -1),
|
|
glm::i8vec2(-2, 1),
|
|
glm::i8vec2(0, 3),
|
|
glm::i8vec2(0),
|
|
glm::i8vec2(-74, 1)};
|
|
std::vector<std::optional<glm::dvec2>> expectedTransformed{
|
|
normalize(expectedRaw[0]) * scale + offset,
|
|
normalize(expectedRaw[1]) * scale + offset,
|
|
normalize(expectedRaw[2]) * scale + offset,
|
|
defaultValue,
|
|
normalize(expectedRaw[4]) * scale + offset,
|
|
};
|
|
checkNormalizedTextureValues(
|
|
data,
|
|
expectedRaw,
|
|
expectedTransformed,
|
|
JsonValue::Array{offset[0], offset[1]},
|
|
JsonValue::Array{scale[0], scale[1]},
|
|
JsonValue::Array{noData[0], noData[1]},
|
|
JsonValue::Array{defaultValue[0], defaultValue[1]});
|
|
}
|
|
}
|
|
|
|
TEST_CASE("Check array PropertyTexturePropertyView") {
|
|
SECTION("uint8_t array") {
|
|
// clang-format off
|
|
std::vector<uint8_t> data{
|
|
1, 2, 3, 0,
|
|
4, 5, 6, 11,
|
|
7, 8, 9, 3,
|
|
0, 5, 2, 27};
|
|
// clang-format on
|
|
|
|
std::vector<std::vector<uint8_t>> expected{
|
|
{1, 2, 3, 0},
|
|
{4, 5, 6, 11},
|
|
{7, 8, 9, 3},
|
|
{0, 5, 2, 27}};
|
|
checkTextureArrayValues(data, 4, expected);
|
|
}
|
|
|
|
SECTION("int8_t array") {
|
|
// clang-format off
|
|
std::vector<uint8_t> data{
|
|
1, 200, 3, 0,
|
|
4, 5, 6, 251,
|
|
129, 8, 9, 3,
|
|
0, 155, 2, 27};
|
|
// clang-format on
|
|
std::vector<std::vector<int8_t>> expected{
|
|
{1, -56, 3, 0},
|
|
{4, 5, 6, -5},
|
|
{-127, 8, 9, 3},
|
|
{0, -101, 2, 27}};
|
|
checkTextureArrayValues(data, 4, expected);
|
|
}
|
|
|
|
SECTION("uint16_t array") {
|
|
// clang-format off
|
|
std::vector<uint8_t> data{
|
|
0, 0, 0, 1,
|
|
9, 0, 1, 0,
|
|
20, 2, 2, 0,
|
|
8, 1, 0, 1};
|
|
// clang-format on
|
|
std::vector<std::vector<uint16_t>> expected{
|
|
{0, 256},
|
|
{9, 1},
|
|
{532, 2},
|
|
{264, 256}};
|
|
checkTextureArrayValues(data, 2, expected);
|
|
}
|
|
|
|
SECTION("int16_t array") {
|
|
// clang-format off
|
|
std::vector<uint8_t> data{
|
|
255, 255, 0, 1,
|
|
9, 0, 146, 195,
|
|
20, 2, 2, 0,
|
|
8, 255, 0, 1};
|
|
// clang-format on
|
|
std::vector<std::vector<int16_t>> expected{
|
|
{-1, 256},
|
|
{9, -15470},
|
|
{532, 2},
|
|
{-248, 256}};
|
|
checkTextureArrayValues(data, 2, expected);
|
|
}
|
|
|
|
SECTION("uint8_t array with noData") {
|
|
// clang-format off
|
|
std::vector<uint8_t> data{
|
|
1, 2, 3, 0,
|
|
4, 5, 6, 11,
|
|
7, 8, 9, 3,
|
|
0, 0, 0, 0,};
|
|
// clang-format on
|
|
|
|
JsonValue::Array noData{0, 0, 0, 0};
|
|
std::vector<std::vector<uint8_t>> expectedRaw{
|
|
{1, 2, 3, 0},
|
|
{4, 5, 6, 11},
|
|
{7, 8, 9, 3},
|
|
{0, 0, 0, 0}};
|
|
std::vector<std::optional<std::vector<uint8_t>>> expectedTransformed{
|
|
std::vector<uint8_t>{1, 2, 3, 0},
|
|
std::vector<uint8_t>{4, 5, 6, 11},
|
|
std::vector<uint8_t>{7, 8, 9, 3},
|
|
std::nullopt};
|
|
checkTextureArrayValues(data, 4, expectedRaw, expectedTransformed, noData);
|
|
}
|
|
|
|
SECTION("uint8_t array with noData and defaultValue") {
|
|
// clang-format off
|
|
std::vector<uint8_t> data{
|
|
1, 2, 3, 0,
|
|
4, 5, 6, 11,
|
|
7, 8, 9, 3,
|
|
0, 0, 0, 0,};
|
|
// clang-format on
|
|
|
|
JsonValue::Array noData{0, 0, 0, 0};
|
|
JsonValue::Array defaultValue{255, 8, 12, 5};
|
|
std::vector<std::vector<uint8_t>> expectedRaw{
|
|
{1, 2, 3, 0},
|
|
{4, 5, 6, 11},
|
|
{7, 8, 9, 3},
|
|
{0, 0, 0, 0}};
|
|
std::vector<std::optional<std::vector<uint8_t>>> expectedTransformed{
|
|
std::vector<uint8_t>{1, 2, 3, 0},
|
|
std::vector<uint8_t>{4, 5, 6, 11},
|
|
std::vector<uint8_t>{7, 8, 9, 3},
|
|
std::vector<uint8_t>{255, 8, 12, 5}};
|
|
checkTextureArrayValues(
|
|
data,
|
|
4,
|
|
expectedRaw,
|
|
expectedTransformed,
|
|
noData,
|
|
defaultValue);
|
|
}
|
|
}
|
|
|
|
TEST_CASE("Check array PropertyTexturePropertyView (normalized)") {
|
|
SECTION("uint8_t array") {
|
|
// clang-format off
|
|
std::vector<uint8_t> data{
|
|
1, 2, 3, 0,
|
|
4, 5, 6, 11,
|
|
7, 8, 9, 3,
|
|
0, 5, 2, 27};
|
|
// clang-format on
|
|
std::vector<std::vector<uint8_t>> expectedRaw{
|
|
{1, 2, 3, 0},
|
|
{4, 5, 6, 11},
|
|
{7, 8, 9, 3},
|
|
{0, 5, 2, 27}};
|
|
std::vector<std::optional<std::vector<double>>> expectedTransformed(
|
|
expectedRaw.size());
|
|
|
|
for (size_t i = 0; i < expectedRaw.size(); i++) {
|
|
auto rawValues = expectedRaw[i];
|
|
std::vector<double> transformedValues(rawValues.size());
|
|
for (size_t j = 0; j < rawValues.size(); j++) {
|
|
transformedValues[j] = normalize(rawValues[j]);
|
|
}
|
|
expectedTransformed[i] = transformedValues;
|
|
}
|
|
checkNormalizedTextureArrayValues(
|
|
data,
|
|
4,
|
|
expectedRaw,
|
|
expectedTransformed);
|
|
}
|
|
|
|
SECTION("int16_t array") {
|
|
// clang-format off
|
|
std::vector<uint8_t> data{
|
|
255, 255, 0, 1,
|
|
9, 0, 146, 195,
|
|
20, 2, 2, 0,
|
|
8, 255, 0, 1};
|
|
// clang-format on
|
|
std::vector<std::vector<int16_t>> expectedRaw{
|
|
{-1, 256},
|
|
{9, -15470},
|
|
{532, 2},
|
|
{-248, 256}};
|
|
std::vector<std::optional<std::vector<double>>> expectedTransformed(
|
|
expectedRaw.size());
|
|
|
|
for (size_t i = 0; i < expectedRaw.size(); i++) {
|
|
auto rawValues = expectedRaw[i];
|
|
std::vector<double> transformedValues(rawValues.size());
|
|
for (size_t j = 0; j < rawValues.size(); j++) {
|
|
transformedValues[j] = normalize(rawValues[j]);
|
|
}
|
|
expectedTransformed[i] = transformedValues;
|
|
}
|
|
|
|
checkNormalizedTextureArrayValues(
|
|
data,
|
|
2,
|
|
expectedRaw,
|
|
expectedTransformed);
|
|
}
|
|
|
|
SECTION("uint8_t array with offset / scale") {
|
|
// clang-format off
|
|
std::vector<uint8_t> data{
|
|
1, 2, 3, 0,
|
|
4, 5, 6, 11,
|
|
7, 8, 9, 3,
|
|
0, 0, 0, 0,};
|
|
// clang-format on
|
|
|
|
const std::vector<double> offset{1, 2, 0, 4};
|
|
const std::vector<double> scale{1, -1, 3, -2};
|
|
std::vector<std::vector<uint8_t>> expectedRaw{
|
|
{1, 2, 3, 0},
|
|
{4, 5, 6, 11},
|
|
{7, 8, 9, 3},
|
|
{0, 0, 0, 0}};
|
|
std::vector<std::optional<std::vector<double>>> expectedTransformed(
|
|
expectedRaw.size());
|
|
|
|
for (size_t i = 0; i < expectedRaw.size(); i++) {
|
|
auto rawValues = expectedRaw[i];
|
|
std::vector<double> transformedValues(rawValues.size());
|
|
for (size_t j = 0; j < rawValues.size(); j++) {
|
|
transformedValues[j] = normalize(rawValues[j]) * scale[j] + offset[j];
|
|
}
|
|
expectedTransformed[i] = transformedValues;
|
|
}
|
|
|
|
checkNormalizedTextureArrayValues(
|
|
data,
|
|
4,
|
|
expectedRaw,
|
|
expectedTransformed,
|
|
JsonValue::Array{offset[0], offset[1], offset[2], offset[3]},
|
|
JsonValue::Array{scale[0], scale[1], scale[2], scale[3]});
|
|
}
|
|
|
|
SECTION("uint8_t array with noData") {
|
|
// clang-format off
|
|
std::vector<uint8_t> data{
|
|
1, 2, 3, 0,
|
|
4, 5, 6, 11,
|
|
7, 8, 9, 3,
|
|
0, 0, 0, 0,};
|
|
// clang-format on
|
|
|
|
JsonValue::Array noData{0, 0, 0, 0};
|
|
std::vector<std::vector<uint8_t>> expectedRaw{
|
|
{1, 2, 3, 0},
|
|
{4, 5, 6, 11},
|
|
{7, 8, 9, 3},
|
|
{0, 0, 0, 0}};
|
|
std::vector<std::optional<std::vector<double>>> expectedTransformed(
|
|
expectedRaw.size());
|
|
|
|
for (size_t i = 0; i < expectedRaw.size() - 1; i++) {
|
|
auto rawValues = expectedRaw[i];
|
|
std::vector<double> transformedValues(rawValues.size());
|
|
for (size_t j = 0; j < rawValues.size(); j++) {
|
|
transformedValues[j] = normalize(rawValues[j]);
|
|
}
|
|
expectedTransformed[i] = transformedValues;
|
|
}
|
|
|
|
expectedTransformed[3] = std::nullopt;
|
|
|
|
checkNormalizedTextureArrayValues(
|
|
data,
|
|
4,
|
|
expectedRaw,
|
|
expectedTransformed,
|
|
std::nullopt,
|
|
std::nullopt,
|
|
noData);
|
|
}
|
|
|
|
SECTION("uint8_t array with all properties") {
|
|
// clang-format off
|
|
std::vector<uint8_t> data{
|
|
1, 2, 3, 0,
|
|
4, 5, 6, 11,
|
|
7, 8, 9, 3,
|
|
0, 0, 0, 0,};
|
|
// clang-format on
|
|
|
|
const std::vector<double> offset{1, 2, 0, 4};
|
|
const std::vector<double> scale{1, -1, 3, -2};
|
|
JsonValue::Array noData{0, 0, 0, 0};
|
|
JsonValue::Array defaultValue{1.0, 2.0, 3.0, 4.0};
|
|
|
|
std::vector<std::vector<uint8_t>> expectedRaw{
|
|
{1, 2, 3, 0},
|
|
{4, 5, 6, 11},
|
|
{7, 8, 9, 3},
|
|
{0, 0, 0, 0}};
|
|
std::vector<std::optional<std::vector<double>>> expectedTransformed(
|
|
expectedRaw.size());
|
|
|
|
for (size_t i = 0; i < expectedRaw.size() - 1; i++) {
|
|
auto rawValues = expectedRaw[i];
|
|
std::vector<double> transformedValues(rawValues.size());
|
|
for (size_t j = 0; j < rawValues.size(); j++) {
|
|
transformedValues[j] = normalize(rawValues[j]) * scale[j] + offset[j];
|
|
}
|
|
expectedTransformed[i] = transformedValues;
|
|
}
|
|
|
|
expectedTransformed[3] = std::vector<double>{1.0, 2.0, 3.0, 4.0};
|
|
|
|
checkNormalizedTextureArrayValues(
|
|
data,
|
|
4,
|
|
expectedRaw,
|
|
expectedTransformed,
|
|
JsonValue::Array{offset[0], offset[1], offset[2], offset[3]},
|
|
JsonValue::Array{scale[0], scale[1], scale[2], scale[3]},
|
|
noData,
|
|
defaultValue);
|
|
}
|
|
}
|
|
|
|
TEST_CASE("Check that PropertyTextureProperty values override class property "
|
|
"values") {
|
|
ClassProperty classProperty;
|
|
classProperty.type = ClassProperty::Type::SCALAR;
|
|
classProperty.componentType = ClassProperty::ComponentType::FLOAT32;
|
|
|
|
classProperty.offset = 0.0f;
|
|
classProperty.scale = 1.0f;
|
|
classProperty.min = -10.0f;
|
|
classProperty.max = 10.0f;
|
|
|
|
Sampler sampler;
|
|
ImageCesium image;
|
|
image.width = 2;
|
|
image.height = 2;
|
|
image.channels = 4;
|
|
image.bytesPerChannel = 1;
|
|
|
|
// clang-format off
|
|
std::vector<uint8_t> data{
|
|
0, 0, 0, 1,
|
|
9, 0, 1, 0,
|
|
20, 2, 2, 0,
|
|
8, 1, 0, 1};
|
|
// clang-format on
|
|
|
|
const float offset = 1.0f;
|
|
const float scale = 2.0f;
|
|
std::vector<uint32_t> expectedUint{16777216, 65545, 131604, 16777480};
|
|
std::vector<float> expectedRaw(expectedUint.size());
|
|
std::vector<std::optional<float>> expectedTransformed(expectedUint.size());
|
|
for (size_t i = 0; i < expectedUint.size(); i++) {
|
|
float value = *reinterpret_cast<float*>(&expectedUint[i]);
|
|
expectedRaw[i] = value;
|
|
expectedTransformed[i] = value * scale + offset;
|
|
}
|
|
|
|
std::vector<std::byte>& imageData = image.pixelData;
|
|
imageData.resize(data.size());
|
|
std::memcpy(imageData.data(), data.data(), data.size());
|
|
|
|
PropertyTextureProperty property;
|
|
property.offset = offset;
|
|
property.scale = scale;
|
|
property.min = std::numeric_limits<float>::lowest();
|
|
property.max = std::numeric_limits<float>::max();
|
|
property.channels = {0, 1, 2, 3};
|
|
|
|
PropertyTexturePropertyView<float> view(
|
|
property,
|
|
classProperty,
|
|
sampler,
|
|
image);
|
|
CHECK(view.getSwizzle() == "rgba");
|
|
|
|
REQUIRE(view.offset() == offset);
|
|
REQUIRE(view.scale() == scale);
|
|
REQUIRE(view.min() == std::numeric_limits<float>::lowest());
|
|
REQUIRE(view.max() == std::numeric_limits<float>::max());
|
|
|
|
std::vector<glm::dvec2> texCoords{
|
|
glm::dvec2(0, 0),
|
|
glm::dvec2(0.5, 0),
|
|
glm::dvec2(0, 0.5),
|
|
glm::dvec2(0.5, 0.5)};
|
|
|
|
for (size_t i = 0; i < texCoords.size(); i++) {
|
|
glm::dvec2 uv = texCoords[i];
|
|
REQUIRE(view.getRaw(uv[0], uv[1]) == expectedRaw[i]);
|
|
REQUIRE(view.get(uv[0], uv[1]) == expectedTransformed[i]);
|
|
}
|
|
}
|
|
|
|
TEST_CASE("Check that non-adjacent channels resolve to expected output") {
|
|
std::vector<glm::dvec2> texCoords{
|
|
glm::dvec2(0, 0),
|
|
glm::dvec2(0.5, 0),
|
|
glm::dvec2(0, 0.5),
|
|
glm::dvec2(0.5, 0.5)};
|
|
|
|
SECTION("single-byte scalar") {
|
|
PropertyTextureProperty property;
|
|
property.channels = {3};
|
|
|
|
ClassProperty classProperty;
|
|
classProperty.type = ClassProperty::Type::SCALAR;
|
|
classProperty.componentType = ClassProperty::ComponentType::UINT8;
|
|
|
|
Sampler sampler;
|
|
ImageCesium image;
|
|
image.width = 2;
|
|
image.height = 2;
|
|
image.channels = 4;
|
|
image.bytesPerChannel = 1;
|
|
|
|
// clang-format off
|
|
std::vector<uint8_t> data{
|
|
0, 1, 2, 3,
|
|
1, 2, 3, 4,
|
|
1, 0, 1, 0,
|
|
2, 3, 8, 1};
|
|
// clang-format on
|
|
|
|
std::vector<std::byte>& imageData = image.pixelData;
|
|
imageData.resize(data.size());
|
|
std::memcpy(imageData.data(), data.data(), data.size());
|
|
|
|
PropertyTexturePropertyView<uint8_t> view(
|
|
property,
|
|
classProperty,
|
|
sampler,
|
|
image);
|
|
CHECK(view.getSwizzle() == "a");
|
|
|
|
std::vector<uint8_t> expected{3, 4, 0, 1};
|
|
for (size_t i = 0; i < expected.size(); i++) {
|
|
glm::dvec2 uv = texCoords[i];
|
|
REQUIRE(view.getRaw(uv[0], uv[1]) == expected[i]);
|
|
REQUIRE(view.get(uv[0], uv[1]) == expected[i]);
|
|
}
|
|
}
|
|
|
|
SECTION("multi-byte scalar") {
|
|
PropertyTextureProperty property;
|
|
property.channels = {2, 0};
|
|
|
|
ClassProperty classProperty;
|
|
classProperty.type = ClassProperty::Type::SCALAR;
|
|
classProperty.componentType = ClassProperty::ComponentType::UINT16;
|
|
|
|
Sampler sampler;
|
|
ImageCesium image;
|
|
image.width = 2;
|
|
image.height = 2;
|
|
image.channels = 4;
|
|
image.bytesPerChannel = 1;
|
|
|
|
// clang-format off
|
|
std::vector<uint8_t> data{
|
|
0, 1, 2, 3,
|
|
1, 2, 3, 4,
|
|
1, 0, 1, 0,
|
|
2, 3, 8, 1};
|
|
// clang-format on
|
|
std::vector<std::byte>& imageData = image.pixelData;
|
|
imageData.resize(data.size());
|
|
std::memcpy(imageData.data(), data.data(), data.size());
|
|
|
|
PropertyTexturePropertyView<uint16_t> view(
|
|
property,
|
|
classProperty,
|
|
sampler,
|
|
image);
|
|
CHECK(view.getSwizzle() == "br");
|
|
|
|
std::vector<uint16_t> expected{2, 259, 257, 520};
|
|
for (size_t i = 0; i < expected.size(); i++) {
|
|
glm::dvec2 uv = texCoords[i];
|
|
REQUIRE(view.getRaw(uv[0], uv[1]) == expected[i]);
|
|
REQUIRE(view.get(uv[0], uv[1]) == expected[i]);
|
|
}
|
|
}
|
|
|
|
SECTION("vecN") {
|
|
PropertyTextureProperty property;
|
|
property.channels = {3, 2, 1};
|
|
|
|
ClassProperty classProperty;
|
|
classProperty.type = ClassProperty::Type::VEC3;
|
|
classProperty.componentType = ClassProperty::ComponentType::UINT8;
|
|
|
|
Sampler sampler;
|
|
ImageCesium image;
|
|
image.width = 2;
|
|
image.height = 2;
|
|
image.channels = 4;
|
|
image.bytesPerChannel = 1;
|
|
|
|
// clang-format off
|
|
std::vector<uint8_t> data{
|
|
0, 1, 2, 3,
|
|
1, 2, 3, 4,
|
|
1, 0, 1, 0,
|
|
2, 3, 8, 1};
|
|
// clang-format on
|
|
std::vector<std::byte>& imageData = image.pixelData;
|
|
imageData.resize(data.size());
|
|
std::memcpy(imageData.data(), data.data(), data.size());
|
|
|
|
PropertyTexturePropertyView<glm::u8vec3> view(
|
|
property,
|
|
classProperty,
|
|
sampler,
|
|
image);
|
|
CHECK(view.getSwizzle() == "abg");
|
|
|
|
std::vector<glm::u8vec3> expected{
|
|
glm::u8vec3(3, 2, 1),
|
|
glm::u8vec3(4, 3, 2),
|
|
glm::u8vec3(0, 1, 0),
|
|
glm::u8vec3(1, 8, 3)};
|
|
for (size_t i = 0; i < expected.size(); i++) {
|
|
glm::dvec2 uv = texCoords[i];
|
|
REQUIRE(view.getRaw(uv[0], uv[1]) == expected[i]);
|
|
REQUIRE(view.get(uv[0], uv[1]) == expected[i]);
|
|
}
|
|
}
|
|
|
|
SECTION("array") {
|
|
PropertyTextureProperty property;
|
|
property.channels = {1, 0, 3, 2};
|
|
|
|
ClassProperty classProperty;
|
|
classProperty.type = ClassProperty::Type::SCALAR;
|
|
classProperty.componentType = ClassProperty::ComponentType::UINT8;
|
|
classProperty.array = true;
|
|
|
|
Sampler sampler;
|
|
ImageCesium image;
|
|
image.width = 2;
|
|
image.height = 2;
|
|
image.channels = 4;
|
|
image.bytesPerChannel = 1;
|
|
|
|
// clang-format off
|
|
std::vector<uint8_t> data{
|
|
1, 2, 3, 0,
|
|
4, 5, 6, 11,
|
|
7, 8, 9, 3,
|
|
0, 5, 2, 27};
|
|
// clang-format on
|
|
|
|
std::vector<std::byte>& imageData = image.pixelData;
|
|
imageData.resize(data.size());
|
|
std::memcpy(imageData.data(), data.data(), data.size());
|
|
|
|
PropertyTexturePropertyView<PropertyArrayView<uint8_t>> view(
|
|
property,
|
|
classProperty,
|
|
sampler,
|
|
image);
|
|
CHECK(view.getSwizzle() == "grab");
|
|
|
|
std::vector<std::vector<uint8_t>> expected{
|
|
{2, 1, 0, 3},
|
|
{5, 4, 11, 6},
|
|
{8, 7, 3, 9},
|
|
{5, 0, 27, 2}};
|
|
|
|
for (size_t i = 0; i < expected.size(); i++) {
|
|
std::vector<uint8_t>& expectedValue = expected[i];
|
|
glm::dvec2 uv = texCoords[i];
|
|
|
|
auto value = view.getRaw(uv[0], uv[1]);
|
|
REQUIRE(static_cast<size_t>(value.size()) == expectedValue.size());
|
|
|
|
auto maybeValue = view.get(uv[0], uv[1]);
|
|
REQUIRE(maybeValue);
|
|
REQUIRE(maybeValue->size() == value.size());
|
|
for (int64_t j = 0; j < value.size(); j++) {
|
|
REQUIRE(value[j] == expectedValue[static_cast<size_t>(j)]);
|
|
REQUIRE((*maybeValue)[j] == value[j]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
TEST_CASE("Check sampling with different sampler values") {
|
|
PropertyTextureProperty property;
|
|
property.channels = {0};
|
|
|
|
ClassProperty classProperty;
|
|
classProperty.type = ClassProperty::Type::SCALAR;
|
|
classProperty.componentType = ClassProperty::ComponentType::UINT8;
|
|
|
|
ImageCesium image;
|
|
image.width = 2;
|
|
image.height = 2;
|
|
image.channels = 1;
|
|
image.bytesPerChannel = 1;
|
|
|
|
std::vector<uint8_t> data{12, 33, 56, 67};
|
|
std::vector<std::byte>& imageData = image.pixelData;
|
|
imageData.resize(data.size());
|
|
std::memcpy(imageData.data(), data.data(), data.size());
|
|
|
|
SECTION("REPEAT") {
|
|
Sampler sampler;
|
|
sampler.wrapS = Sampler::WrapS::REPEAT;
|
|
sampler.wrapT = Sampler::WrapT::REPEAT;
|
|
|
|
PropertyTexturePropertyView<uint8_t> view(
|
|
property,
|
|
classProperty,
|
|
sampler,
|
|
image);
|
|
CHECK(view.getSwizzle() == "r");
|
|
|
|
std::vector<glm::dvec2> uvs{
|
|
glm::dvec2(1.0, 0),
|
|
glm::dvec2(-1.5, 0),
|
|
glm::dvec2(0, -0.5),
|
|
glm::dvec2(1.5, -0.5)};
|
|
for (size_t i = 0; i < uvs.size(); i++) {
|
|
glm::dvec2 uv = uvs[i];
|
|
REQUIRE(view.getRaw(uv[0], uv[1]) == data[i]);
|
|
REQUIRE(view.get(uv[0], uv[1]) == data[i]);
|
|
}
|
|
}
|
|
|
|
SECTION("MIRRORED_REPEAT") {
|
|
Sampler sampler;
|
|
sampler.wrapS = Sampler::WrapS::MIRRORED_REPEAT;
|
|
sampler.wrapT = Sampler::WrapT::MIRRORED_REPEAT;
|
|
// REPEAT: | 1 2 3 | 1 2 3 |
|
|
// MIRRORED: | 1 2 3 | 3 2 1 |
|
|
// Sampling 0.6 is equal to sampling 1.4 or -0.6.
|
|
|
|
PropertyTexturePropertyView<uint8_t> view(
|
|
property,
|
|
classProperty,
|
|
sampler,
|
|
image);
|
|
CHECK(view.getSwizzle() == "r");
|
|
|
|
std::vector<glm::dvec2> uvs{
|
|
glm::dvec2(2.0, 0),
|
|
glm::dvec2(-0.75, 0),
|
|
glm::dvec2(0, 1.25),
|
|
glm::dvec2(-1.25, 2.75)};
|
|
for (size_t i = 0; i < uvs.size(); i++) {
|
|
glm::dvec2 uv = uvs[i];
|
|
REQUIRE(view.getRaw(uv[0], uv[1]) == data[i]);
|
|
REQUIRE(view.get(uv[0], uv[1]) == data[i]);
|
|
}
|
|
}
|
|
|
|
SECTION("CLAMP_TO_EDGE") {
|
|
Sampler sampler;
|
|
sampler.wrapS = Sampler::WrapS::CLAMP_TO_EDGE;
|
|
sampler.wrapT = Sampler::WrapT::CLAMP_TO_EDGE;
|
|
|
|
PropertyTexturePropertyView<uint8_t> view(
|
|
property,
|
|
classProperty,
|
|
sampler,
|
|
image);
|
|
CHECK(view.getSwizzle() == "r");
|
|
|
|
std::vector<glm::dvec2> uvs{
|
|
glm::dvec2(-1.0, 0),
|
|
glm::dvec2(1.4, 0),
|
|
glm::dvec2(0, 2.0),
|
|
glm::dvec2(1.5, 1.5)};
|
|
for (size_t i = 0; i < uvs.size(); i++) {
|
|
glm::dvec2 uv = uvs[i];
|
|
REQUIRE(view.getRaw(uv[0], uv[1]) == data[i]);
|
|
REQUIRE(view.get(uv[0], uv[1]) == data[i]);
|
|
}
|
|
}
|
|
|
|
SECTION("Mismatched wrap values") {
|
|
Sampler sampler;
|
|
sampler.wrapS = Sampler::WrapS::REPEAT;
|
|
sampler.wrapT = Sampler::WrapT::CLAMP_TO_EDGE;
|
|
|
|
PropertyTexturePropertyView<uint8_t> view(
|
|
property,
|
|
classProperty,
|
|
sampler,
|
|
image);
|
|
CHECK(view.getSwizzle() == "r");
|
|
|
|
std::vector<glm::dvec2> uvs{
|
|
glm::dvec2(1.0, 0),
|
|
glm::dvec2(-1.5, -1.0),
|
|
glm::dvec2(0, 1.5),
|
|
glm::dvec2(1.5, 1.5)};
|
|
for (size_t i = 0; i < uvs.size(); i++) {
|
|
glm::dvec2 uv = uvs[i];
|
|
REQUIRE(view.getRaw(uv[0], uv[1]) == data[i]);
|
|
REQUIRE(view.get(uv[0], uv[1]) == data[i]);
|
|
}
|
|
}
|
|
}
|
|
|
|
TEST_CASE("Test PropertyTextureProperty constructs with "
|
|
"applyKhrTextureTransformExtension = true") {
|
|
std::vector<uint8_t> data{1, 2, 3, 4};
|
|
|
|
PropertyTextureProperty property;
|
|
property.texCoord = 0;
|
|
|
|
ExtensionKhrTextureTransform& textureTransformExtension =
|
|
property.addExtension<ExtensionKhrTextureTransform>();
|
|
textureTransformExtension.offset = {0.5, -0.5};
|
|
textureTransformExtension.rotation = CesiumUtility::Math::PiOverTwo;
|
|
textureTransformExtension.scale = {0.5, 0.5};
|
|
textureTransformExtension.texCoord = 10;
|
|
|
|
ClassProperty classProperty;
|
|
classProperty.type = ClassProperty::Type::SCALAR;
|
|
classProperty.componentType = ClassProperty::ComponentType::UINT8;
|
|
|
|
Sampler sampler;
|
|
sampler.wrapS = Sampler::WrapS::REPEAT;
|
|
sampler.wrapT = Sampler::WrapT::REPEAT;
|
|
|
|
ImageCesium image;
|
|
image.width = 2;
|
|
image.height = 2;
|
|
image.channels = 1;
|
|
image.bytesPerChannel = 1;
|
|
|
|
std::vector<std::byte>& imageData = image.pixelData;
|
|
imageData.resize(data.size());
|
|
std::memcpy(imageData.data(), data.data(), data.size());
|
|
|
|
property.channels = {0};
|
|
|
|
TextureViewOptions options;
|
|
options.applyKhrTextureTransformExtension = true;
|
|
|
|
PropertyTexturePropertyView<uint8_t>
|
|
view(property, classProperty, sampler, image, options);
|
|
REQUIRE(view.status() == PropertyTexturePropertyViewStatus::Valid);
|
|
|
|
auto textureTransform = view.getTextureTransform();
|
|
REQUIRE(textureTransform != std::nullopt);
|
|
REQUIRE(textureTransform->offset() == glm::dvec2(0.5, -0.5));
|
|
REQUIRE(textureTransform->rotation() == CesiumUtility::Math::PiOverTwo);
|
|
REQUIRE(textureTransform->scale() == glm::dvec2(0.5, 0.5));
|
|
|
|
// Texcoord is overridden by value in KHR_texture_transform.
|
|
REQUIRE(
|
|
view.getTexCoordSetIndex() == textureTransform->getTexCoordSetIndex());
|
|
REQUIRE(textureTransform->getTexCoordSetIndex() == 10);
|
|
|
|
// This transforms to the following UV values:
|
|
// (0, 0) -> (0.5, -0.5) -> wraps to (0.5, 0.5)
|
|
// (1, 0) -> (0.5, -1) -> wraps to (0.5, 0)
|
|
// (0, 1) -> (1, -0.5) -> wraps to (0, 0.5)
|
|
// (1, 1) -> (1, -1) -> wraps to (0.0, 0.0)
|
|
std::vector<glm::dvec2> texCoords{
|
|
glm::dvec2(0, 0),
|
|
glm::dvec2(1.0, 0),
|
|
glm::dvec2(0, 1.0),
|
|
glm::dvec2(1.0, 1.0)};
|
|
|
|
std::vector<uint8_t> expectedValues{4, 2, 3, 1};
|
|
|
|
for (size_t i = 0; i < texCoords.size(); i++) {
|
|
glm::dvec2 uv = texCoords[i];
|
|
REQUIRE(view.getRaw(uv[0], uv[1]) == expectedValues[i]);
|
|
REQUIRE(view.get(uv[0], uv[1]) == expectedValues[i]);
|
|
}
|
|
}
|
|
|
|
TEST_CASE("Test normalized PropertyTextureProperty constructs with "
|
|
"applyKhrTextureTransformExtension = true") {
|
|
std::vector<uint8_t> data{0, 64, 127, 255};
|
|
|
|
PropertyTextureProperty property;
|
|
property.texCoord = 0;
|
|
|
|
ExtensionKhrTextureTransform& textureTransformExtension =
|
|
property.addExtension<ExtensionKhrTextureTransform>();
|
|
textureTransformExtension.offset = {0.5, -0.5};
|
|
textureTransformExtension.rotation = CesiumUtility::Math::PiOverTwo;
|
|
textureTransformExtension.scale = {0.5, 0.5};
|
|
textureTransformExtension.texCoord = 10;
|
|
|
|
ClassProperty classProperty;
|
|
classProperty.type = ClassProperty::Type::SCALAR;
|
|
classProperty.componentType = ClassProperty::ComponentType::UINT8;
|
|
classProperty.normalized = true;
|
|
|
|
Sampler sampler;
|
|
sampler.wrapS = Sampler::WrapS::REPEAT;
|
|
sampler.wrapT = Sampler::WrapT::REPEAT;
|
|
|
|
ImageCesium image;
|
|
image.width = 2;
|
|
image.height = 2;
|
|
image.channels = 1;
|
|
image.bytesPerChannel = 1;
|
|
|
|
std::vector<std::byte>& imageData = image.pixelData;
|
|
imageData.resize(data.size());
|
|
std::memcpy(imageData.data(), data.data(), data.size());
|
|
|
|
property.channels = {0};
|
|
|
|
TextureViewOptions options;
|
|
options.applyKhrTextureTransformExtension = true;
|
|
|
|
PropertyTexturePropertyView<uint8_t, true>
|
|
view(property, classProperty, sampler, image, options);
|
|
REQUIRE(view.status() == PropertyTexturePropertyViewStatus::Valid);
|
|
|
|
auto textureTransform = view.getTextureTransform();
|
|
REQUIRE(textureTransform != std::nullopt);
|
|
REQUIRE(textureTransform->offset() == glm::dvec2(0.5, -0.5));
|
|
REQUIRE(textureTransform->rotation() == CesiumUtility::Math::PiOverTwo);
|
|
REQUIRE(textureTransform->scale() == glm::dvec2(0.5, 0.5));
|
|
|
|
// Texcoord is overridden by value in KHR_texture_transform.
|
|
REQUIRE(
|
|
view.getTexCoordSetIndex() == textureTransform->getTexCoordSetIndex());
|
|
REQUIRE(textureTransform->getTexCoordSetIndex() == 10);
|
|
|
|
// This transforms to the following UV values:
|
|
// (0, 0) -> (0.5, -0.5) -> wraps to (0.5, 0.5)
|
|
// (1, 0) -> (0.5, -1) -> wraps to (0.5, 0)
|
|
// (0, 1) -> (1, -0.5) -> wraps to (0, 0.5)
|
|
// (1, 1) -> (1, -1) -> wraps to (0.0, 0.0)
|
|
std::vector<glm::dvec2> texCoords{
|
|
glm::dvec2(0, 0),
|
|
glm::dvec2(1.0, 0),
|
|
glm::dvec2(0, 1.0),
|
|
glm::dvec2(1.0, 1.0)};
|
|
|
|
std::vector<uint8_t> expectedValues{255, 64, 127, 0};
|
|
|
|
for (size_t i = 0; i < texCoords.size(); i++) {
|
|
glm::dvec2 uv = texCoords[i];
|
|
REQUIRE(view.getRaw(uv[0], uv[1]) == expectedValues[i]);
|
|
REQUIRE(
|
|
view.get(uv[0], uv[1]) ==
|
|
static_cast<double>(expectedValues[i]) / 255.0);
|
|
}
|
|
}
|
|
|
|
TEST_CASE("Test PropertyTextureProperty constructs with "
|
|
"makeImageCopy = true") {
|
|
std::vector<uint8_t> data{1, 2, 3, 4};
|
|
|
|
PropertyTextureProperty property;
|
|
property.texCoord = 0;
|
|
|
|
ExtensionKhrTextureTransform& textureTransformExtension =
|
|
property.addExtension<ExtensionKhrTextureTransform>();
|
|
textureTransformExtension.offset = {0.5, -0.5};
|
|
textureTransformExtension.rotation = CesiumUtility::Math::PiOverTwo;
|
|
textureTransformExtension.scale = {0.5, 0.5};
|
|
textureTransformExtension.texCoord = 10;
|
|
|
|
ClassProperty classProperty;
|
|
classProperty.type = ClassProperty::Type::SCALAR;
|
|
classProperty.componentType = ClassProperty::ComponentType::UINT8;
|
|
|
|
Sampler sampler;
|
|
sampler.wrapS = Sampler::WrapS::REPEAT;
|
|
sampler.wrapT = Sampler::WrapT::REPEAT;
|
|
|
|
ImageCesium image;
|
|
image.width = 2;
|
|
image.height = 2;
|
|
image.channels = 1;
|
|
image.bytesPerChannel = 1;
|
|
|
|
std::vector<std::byte>& imageData = image.pixelData;
|
|
imageData.resize(data.size());
|
|
std::memcpy(imageData.data(), data.data(), data.size());
|
|
|
|
property.channels = {0};
|
|
|
|
TextureViewOptions options;
|
|
options.makeImageCopy = true;
|
|
|
|
PropertyTexturePropertyView<uint8_t>
|
|
view(property, classProperty, sampler, image, options);
|
|
REQUIRE(view.status() == PropertyTexturePropertyViewStatus::Valid);
|
|
|
|
// Clear the original image data.
|
|
std::vector<std::byte> emptyData;
|
|
image.pixelData.swap(emptyData);
|
|
|
|
const ImageCesium* pImage = view.getImage();
|
|
REQUIRE(pImage);
|
|
REQUIRE(pImage->width == image.width);
|
|
REQUIRE(pImage->height == image.height);
|
|
REQUIRE(pImage->channels == image.channels);
|
|
REQUIRE(pImage->bytesPerChannel == image.bytesPerChannel);
|
|
REQUIRE(pImage->pixelData.size() == data.size());
|
|
|
|
std::vector<glm::dvec2> texCoords{
|
|
glm::dvec2(0, 0),
|
|
glm::dvec2(0.5, 0),
|
|
glm::dvec2(0, 0.5),
|
|
glm::dvec2(0.5, 0.5)};
|
|
|
|
for (size_t i = 0; i < texCoords.size(); i++) {
|
|
glm::dvec2 uv = texCoords[i];
|
|
REQUIRE(view.getRaw(uv[0], uv[1]) == data[i]);
|
|
REQUIRE(view.get(uv[0], uv[1]) == data[i]);
|
|
}
|
|
}
|
|
|
|
TEST_CASE("Test normalized PropertyTextureProperty constructs with "
|
|
"makeImageCopy = true") {
|
|
std::vector<uint8_t> data{0, 64, 127, 255};
|
|
|
|
PropertyTextureProperty property;
|
|
property.texCoord = 0;
|
|
|
|
ExtensionKhrTextureTransform& textureTransformExtension =
|
|
property.addExtension<ExtensionKhrTextureTransform>();
|
|
textureTransformExtension.offset = {0.5, -0.5};
|
|
textureTransformExtension.rotation = CesiumUtility::Math::PiOverTwo;
|
|
textureTransformExtension.scale = {0.5, 0.5};
|
|
textureTransformExtension.texCoord = 10;
|
|
|
|
ClassProperty classProperty;
|
|
classProperty.type = ClassProperty::Type::SCALAR;
|
|
classProperty.componentType = ClassProperty::ComponentType::UINT8;
|
|
classProperty.normalized = true;
|
|
|
|
Sampler sampler;
|
|
sampler.wrapS = Sampler::WrapS::REPEAT;
|
|
sampler.wrapT = Sampler::WrapT::REPEAT;
|
|
|
|
ImageCesium image;
|
|
image.width = 2;
|
|
image.height = 2;
|
|
image.channels = 1;
|
|
image.bytesPerChannel = 1;
|
|
|
|
std::vector<std::byte>& imageData = image.pixelData;
|
|
imageData.resize(data.size());
|
|
std::memcpy(imageData.data(), data.data(), data.size());
|
|
|
|
property.channels = {0};
|
|
|
|
TextureViewOptions options;
|
|
options.makeImageCopy = true;
|
|
|
|
PropertyTexturePropertyView<uint8_t, true>
|
|
view(property, classProperty, sampler, image, options);
|
|
REQUIRE(view.status() == PropertyTexturePropertyViewStatus::Valid);
|
|
|
|
// Clear the original image data.
|
|
std::vector<std::byte> emptyData;
|
|
image.pixelData.swap(emptyData);
|
|
|
|
const ImageCesium* pImage = view.getImage();
|
|
REQUIRE(pImage);
|
|
REQUIRE(pImage->width == image.width);
|
|
REQUIRE(pImage->height == image.height);
|
|
REQUIRE(pImage->channels == image.channels);
|
|
REQUIRE(pImage->bytesPerChannel == image.bytesPerChannel);
|
|
REQUIRE(pImage->pixelData.size() == data.size());
|
|
|
|
std::vector<glm::dvec2> texCoords{
|
|
glm::dvec2(0, 0),
|
|
glm::dvec2(0.5, 0),
|
|
glm::dvec2(0, 0.5),
|
|
glm::dvec2(0.5, 0.5)};
|
|
|
|
for (size_t i = 0; i < texCoords.size(); i++) {
|
|
glm::dvec2 uv = texCoords[i];
|
|
REQUIRE(view.getRaw(uv[0], uv[1]) == data[i]);
|
|
REQUIRE(view.get(uv[0], uv[1]) == static_cast<double>(data[i]) / 255.0);
|
|
}
|
|
}
|