22 const auto fold = [](
char c)
26 return left.size() ==
right.size() && std::equal(
28 [
fold](
char a,
char b) { return fold(a) == fold(b); });
31 std::expected<LoadedTexture, std::string>
loadTexture(
32 const ResourcePaths& paths,
const BoardTextureRecipe&
recipe,
34 std::string_view fileName)
37 recipe.mesh, location, fileName, context);
39 return std::unexpected(std::string(
relative.error().detail));
41 recipe.mesh, location, fileName, context);
43 return std::unexpected(
resolved.error());
48 std::ifstream
input(*
resolved, std::ios::binary | std::ios::ate);
50 return std::unexpected(*
relative +
": cannot open texture BMP");
53 return std::unexpected(*
relative +
": texture BMP exceeds file budget");
55 result.bytes.resize(
static_cast<std::size_t
>(size));
56 input.seekg(0, std::ios::beg);
57 if (!result.bytes.empty())
58 input.read(
reinterpret_cast<char*
>(result.bytes.data()),
59 static_cast<std::streamsize
>(result.bytes.size()));
61 return std::unexpected(*
relative +
": cannot read complete texture BMP");
67 return std::unexpected(*
relative +
": " +
image.error().detail);
73 fileName.find(
"_256") != std::string_view::npos)
81 expected = asset.expectedDimensions;
86 return std::unexpected(*
relative +
": texture BMP dimensions do not match the catalog");
88 result.image = std::move(*
image);
93 std::expected<std::vector<std::shared_ptr<const HmdTextureImage>>, std::string>
99 std::vector<std::shared_ptr<const HmdTextureImage>>
images;
105 return std::unexpected(
"invalid board texture recipe");
114 return std::unexpected(
base.error());
120 return std::unexpected(overlay.error());
121 if (
base->metadata.bitsPerPixel != 8 || overlay->metadata.bitsPerPixel != 8)
122 return std::unexpected(
"nonpalettized board overlays are not supported");
123 if (overlay->image.width !=
base->image.width ||
124 overlay->image.height !=
base->image.height)
125 return std::unexpected(
"board overlay dimensions differ from the base texture");
130 const auto width = overlay->image.width;
131 const auto height = overlay->image.height;
133 for (std::uint32_t
y = 0;
y <
height; ++
y)
135 const auto sourceY = overlay->metadata.topDown() ?
y :
height - 1U -
y;
136 const auto*
row = overlay->bytes.data() + overlay->metadata.pixelDataOffset +
sourceY *
stride;
137 for (std::uint32_t
x = 0;
x <
width; ++
x)
139 if (
row[
x] == std::byte{0})
continue;
140 const auto pixel = (
static_cast<std::size_t
>(
y) *
width +
x) * 4U;
141 std::copy_n(overlay->image.pixels.data() +
pixel, 4,
146 auto image = std::make_shared<HmdTextureImage>();
149 image->texturePage =
static_cast<std::uint16_t
>(
150 ((
y & 0x200U) << 2U) | ((
y & 0x100U) >> 4U) |
151 ((
x & 0x3FFU) >> 6U) | (1U << 7U));
154 image->logicalX =
static_cast<std::int32_t
>((
x & 63U) * 2U);
155 image->logicalY =
static_cast<std::int32_t
>(
y & 255U);
158 image->rgba = std::move(
base->image.pixels);
std::atomic< float > left
std::atomic< float > right
LegacyBitmapMetadata metadata
std::vector< std::byte > bytes
constexpr DataId boardMeshDataId(BoardMeshKind mesh) noexcept
constexpr TextureDimensions textureDimensions(TextureResolution resolution) noexcept
constexpr bool isValidTextureResolution(TextureResolution resolution) noexcept
std::expected< LegacyBitmapRGBA8, BitmapError > decodeLegacyBitmapRGBA8(std::span< const std::byte > bytes, std::size_t maxPixels)
constexpr bool isValidBoardMeshKind(BoardMeshKind mesh) noexcept
std::expected< std::string, TextureCatalogError > boardTextureRelativePath(BoardMeshKind mesh, TextureLocation location, std::string_view fileName, const BoardTextureContext &context)
std::expected< std::filesystem::path, std::string > resolveBoardTexturePath(const ResourcePaths &stockPaths, BoardMeshKind mesh, TextureLocation location, std::string_view fileName, const BoardTextureContext &context)
const std::vector< LegacyTextureAsset > & legacyTextureCorpusManifest()
std::expected< std::vector< std::shared_ptr< const HmdTextureImage > >, std::string > loadBoardTextureImages(const ResourcePaths &paths, const BoardTextureRecipe &recipe, const BoardTextureContext &context)
std::expected< LegacyBitmapMetadata, BitmapError > inspectLegacyBitmap(std::span< const std::byte > bytes)