refactored example by Robin
|
@ -25,4 +25,5 @@ ParadiSO wird mit den notwendigen Komponenten geliefert. Diese sollte jedoch hie
|
||||||
|
|
||||||
## Zuarbeiten
|
## Zuarbeiten
|
||||||
|
|
||||||
* [TimePlex](https://code.technotecture.net/Timeplex)
|
* [Tim Götzelmann](https://code.technotecture.net/Timeplex)
|
||||||
|
* [Robin Rottstädt](https://code.technotecture.net/robin_rottstaedt)
|
|
@ -25,4 +25,5 @@ ParadiSO comes with batteries included. However, it should be mentioned here:
|
||||||
|
|
||||||
## Contributors
|
## Contributors
|
||||||
|
|
||||||
* [TimePlex](https://code.technotecture.net/Timeplex)
|
* [Tim Götzelmann](https://code.technotecture.net/Timeplex)
|
||||||
|
* [Robin Rottstädt](https://code.technotecture.net/robin_rottstaedt)
|
|
@ -1,3 +1,3 @@
|
||||||
add_subdirectory(simple)
|
add_subdirectory(simple)
|
||||||
add_subdirectory(pong)
|
add_subdirectory(pong)
|
||||||
add_subdirectory(flappy_bird)
|
add_subdirectory(quickwings)
|
|
@ -1,11 +0,0 @@
|
||||||
file(GLOB_RECURSE flappy_bird_src "*.cpp")
|
|
||||||
file(GLOB_RECURSE flappy_bird_lib "lib/*.hpp" "lib/*.h")
|
|
||||||
file(GLOB_RECURSE flappy_bird_assets "assets/*")
|
|
||||||
|
|
||||||
add_executable(flappy_bird ${flappy_bird_src} ${flappy_bird_lib})
|
|
||||||
target_link_libraries(flappy_bird paradiso_core)
|
|
||||||
|
|
||||||
add_custom_command(TARGET flappy_bird POST_BUILD
|
|
||||||
COMMAND ${CMAKE_COMMAND} -E copy_directory
|
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/assets/ $<TARGET_FILE_DIR:flappy_bird>/assets)
|
|
||||||
|
|
|
@ -1,72 +0,0 @@
|
||||||
#include <paradiso/rgba.hpp>
|
|
||||||
#include <paradiso/sprite.hpp>
|
|
||||||
|
|
||||||
#include <fstream>
|
|
||||||
#include <iostream>
|
|
||||||
#include <optional>
|
|
||||||
#include <unordered_map>
|
|
||||||
|
|
||||||
// STB image loading
|
|
||||||
#define STB_IMAGE_IMPLEMENTATION
|
|
||||||
#include "lib/stb_image.h"
|
|
||||||
|
|
||||||
#include "lib/image_loader.hpp"
|
|
||||||
|
|
||||||
std::unordered_map<std::string, paradiso::Bitmap> image_loader::image_cache =
|
|
||||||
std::unordered_map<std::string, paradiso::Bitmap>();
|
|
||||||
|
|
||||||
paradiso::Bitmap image_loader::load(const std::string& filename) {
|
|
||||||
if (image_cache.find(filename) == image_cache.end()) {
|
|
||||||
std::string path = ASSET_PATH + filename;
|
|
||||||
std::cout << "Loading " << path << std::endl;
|
|
||||||
auto data = readBMP(path);
|
|
||||||
image_cache[filename] = data;
|
|
||||||
}
|
|
||||||
return image_cache[filename];
|
|
||||||
}
|
|
||||||
|
|
||||||
paradiso::Bitmap image_loader::readBMP(std::string& filename) {
|
|
||||||
// Load with stb_image
|
|
||||||
stbi_set_flip_vertically_on_load(true); // flip y axis for OpenGL
|
|
||||||
int width, height, channels;
|
|
||||||
unsigned char* image =
|
|
||||||
stbi_load(filename.c_str(), &width, &height, &channels, 4);
|
|
||||||
int size = width * height;
|
|
||||||
|
|
||||||
if (!image)
|
|
||||||
throw std::runtime_error("Error loading image");
|
|
||||||
|
|
||||||
// Convert to Vector of RGBA
|
|
||||||
std::vector<paradiso::RGBA> rgba = std::vector<paradiso::RGBA>(size);
|
|
||||||
for (int i = 0; i < size; i++) {
|
|
||||||
// get rgba values
|
|
||||||
int pos = i * 4;
|
|
||||||
int r = image[pos + 0];
|
|
||||||
int g = image[pos + 1];
|
|
||||||
int b = image[pos + 2];
|
|
||||||
int a = image[pos + 3];
|
|
||||||
|
|
||||||
// bug in from_rgba. it expects bgra, not rgba
|
|
||||||
auto val = paradiso::RGBA::from_rgba(b, g, r, a);
|
|
||||||
rgba[i] = val;
|
|
||||||
}
|
|
||||||
|
|
||||||
// rotate image by 90 degrees CW
|
|
||||||
std::vector<paradiso::RGBA> rotated = std::vector<paradiso::RGBA>(size);
|
|
||||||
for (int x = 0; x < width; x++) {
|
|
||||||
for (int y = 0; y < height; y++) {
|
|
||||||
|
|
||||||
int pos = y * width + x;
|
|
||||||
int pos_rotated = x * height + (height - y - 1);
|
|
||||||
rotated[pos_rotated] = rgba[pos];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// free image
|
|
||||||
stbi_image_free(image);
|
|
||||||
|
|
||||||
return paradiso::Bitmap::from_data(
|
|
||||||
paradiso::Size{static_cast<unsigned int>(height),
|
|
||||||
static_cast<unsigned int>(width)},
|
|
||||||
rotated);
|
|
||||||
}
|
|
|
@ -1,24 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <paradiso/bitmap.hpp>
|
|
||||||
|
|
||||||
#include <optional>
|
|
||||||
#include <string>
|
|
||||||
#include <unordered_map>
|
|
||||||
|
|
||||||
class image_loader {
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* @brief loads an Image from a file
|
|
||||||
* @param[in] filename path to file
|
|
||||||
* @return bitmap from file
|
|
||||||
*/
|
|
||||||
static paradiso::Bitmap load(const std::string& filename);
|
|
||||||
|
|
||||||
private:
|
|
||||||
static inline const std::string ASSET_PATH = "assets/";
|
|
||||||
|
|
||||||
static std::unordered_map<std::string, paradiso::Bitmap> image_cache;
|
|
||||||
|
|
||||||
static paradiso::Bitmap readBMP(std::string& filename);
|
|
||||||
};
|
|
20
examples/quickwings/CMakeLists.txt
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
set(quickwings_srcs quickwings.cpp)
|
||||||
|
set(quickwings_assets
|
||||||
|
assets/background-day.png
|
||||||
|
assets/base.png
|
||||||
|
assets/pipe-green.png
|
||||||
|
assets/yellowbird-downflap.png
|
||||||
|
assets/yellowbird-midflap.png
|
||||||
|
assets/yellowbird-upflap.png
|
||||||
|
)
|
||||||
|
|
||||||
|
set_source_files_properties(${quickwings_assets} PROPERTIES HEADER_FILE_ONLY TRUE)
|
||||||
|
|
||||||
|
add_executable(quickwings ${quickwings_srcs} ${quickwings_assets})
|
||||||
|
|
||||||
|
target_link_libraries(quickwings paradiso_core)
|
||||||
|
|
||||||
|
add_custom_command(TARGET quickwings POST_BUILD
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E copy_directory
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/assets/ $<TARGET_FILE_DIR:quickwings>/assets)
|
||||||
|
|
Before Width: | Height: | Size: 6.9 KiB After Width: | Height: | Size: 6.9 KiB |
Before Width: | Height: | Size: 470 B After Width: | Height: | Size: 470 B |
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 2.5 KiB |
Before Width: | Height: | Size: 426 B After Width: | Height: | Size: 426 B |
Before Width: | Height: | Size: 425 B After Width: | Height: | Size: 425 B |
Before Width: | Height: | Size: 427 B After Width: | Height: | Size: 427 B |
|
@ -1,11 +1,12 @@
|
||||||
/**
|
/**
|
||||||
* paradiso - Paradigmen der Softwareentwicklung
|
* paradiso - Paradigmen der Softwareentwicklung
|
||||||
*
|
*
|
||||||
* (c) Copyright 2023 Hartmut Seichter
|
* (c) Copyright 2023 Hartmut Seichter, Robin Rottstädt
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <paradiso/bitmap.hpp>
|
#include <paradiso/bitmap.hpp>
|
||||||
|
#include <paradiso/bitmap_io.hpp>
|
||||||
#include <paradiso/context.hpp>
|
#include <paradiso/context.hpp>
|
||||||
#include <paradiso/geometry.hpp>
|
#include <paradiso/geometry.hpp>
|
||||||
#include <paradiso/renderer.hpp>
|
#include <paradiso/renderer.hpp>
|
||||||
|
@ -17,9 +18,10 @@
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <thread>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
#include "lib/image_loader.hpp"
|
// #include "lib/image_loader.hpp"
|
||||||
|
|
||||||
const int frame_rate = 60;
|
const int frame_rate = 60;
|
||||||
|
|
||||||
|
@ -33,7 +35,7 @@ struct Background {
|
||||||
|
|
||||||
Background() {
|
Background() {
|
||||||
auto backgroundImage =
|
auto backgroundImage =
|
||||||
image_loader::load(std::string("background-day.png"));
|
paradiso::BitmapIO::get().load("background-day.png");
|
||||||
backgroundLeft = paradiso::Sprite{
|
backgroundLeft = paradiso::Sprite{
|
||||||
.bitmap = backgroundImage,
|
.bitmap = backgroundImage,
|
||||||
.pivot = paradiso::Vector2<float>::make(0.0f, 0.0f),
|
.pivot = paradiso::Vector2<float>::make(0.0f, 0.0f),
|
||||||
|
@ -43,7 +45,7 @@ struct Background {
|
||||||
.pivot = paradiso::Vector2<float>::make(2.0f, 0.0f),
|
.pivot = paradiso::Vector2<float>::make(2.0f, 0.0f),
|
||||||
.scale = paradiso::Vector2<float>::make(1.01f, 1.0f)};
|
.scale = paradiso::Vector2<float>::make(1.01f, 1.0f)};
|
||||||
|
|
||||||
auto grassImage = image_loader::load(std::string("base.png"));
|
auto grassImage = paradiso::BitmapIO::get().load("base.png");
|
||||||
grassLeft = paradiso::Sprite{
|
grassLeft = paradiso::Sprite{
|
||||||
.bitmap = grassImage,
|
.bitmap = grassImage,
|
||||||
.pivot = paradiso::Vector2<float>::make(0.0f, -1.0f),
|
.pivot = paradiso::Vector2<float>::make(0.0f, -1.0f),
|
||||||
|
@ -77,7 +79,7 @@ struct Grass {
|
||||||
paradiso::Sprite* scrolling[2] = {&grassLeft, &grassRight};
|
paradiso::Sprite* scrolling[2] = {&grassLeft, &grassRight};
|
||||||
|
|
||||||
Grass() {
|
Grass() {
|
||||||
auto grassImage = image_loader::load(std::string("base.png"));
|
auto grassImage = paradiso::BitmapIO::get().load(std::string("base.png"));
|
||||||
grassLeft = paradiso::Sprite{
|
grassLeft = paradiso::Sprite{
|
||||||
.bitmap = grassImage,
|
.bitmap = grassImage,
|
||||||
.pivot = paradiso::Vector2<float>::make(0.0f, -0.9f),
|
.pivot = paradiso::Vector2<float>::make(0.0f, -0.9f),
|
||||||
|
@ -104,7 +106,7 @@ struct Grass {
|
||||||
paradiso::Renderer renderer{};
|
paradiso::Renderer renderer{};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct FlappyBird {
|
struct QuickWings {
|
||||||
|
|
||||||
paradiso::Renderer renderer1{};
|
paradiso::Renderer renderer1{};
|
||||||
paradiso::Renderer renderer2{};
|
paradiso::Renderer renderer2{};
|
||||||
|
@ -131,24 +133,24 @@ struct FlappyBird {
|
||||||
|
|
||||||
float rotation = 0.0f;
|
float rotation = 0.0f;
|
||||||
|
|
||||||
FlappyBird() {
|
QuickWings() {
|
||||||
float scaleh = 0.07f;
|
float scaleh = 0.07f;
|
||||||
float scalew = scaleh * 1.416666666666667f;
|
float scalew = scaleh * 1.416666666666667f;
|
||||||
|
|
||||||
birds = {
|
birds = {
|
||||||
paradiso::Sprite{
|
paradiso::Sprite{
|
||||||
.bitmap =
|
.bitmap =
|
||||||
image_loader::load(std::string("yellowbird-downflap.png")),
|
paradiso::BitmapIO::get().load("yellowbird-downflap.png"),
|
||||||
.pivot = paradiso::Vector2<float>::make(0.0f, 0.0f),
|
.pivot = paradiso::Vector2<float>::make(0.0f, 0.0f),
|
||||||
.scale = paradiso::Vector2<float>::make(scalew, scaleh)},
|
.scale = paradiso::Vector2<float>::make(scalew, scaleh)},
|
||||||
paradiso::Sprite{
|
paradiso::Sprite{
|
||||||
.bitmap =
|
.bitmap =
|
||||||
image_loader::load(std::string("yellowbird-midflap.png")),
|
paradiso::BitmapIO::get().load("yellowbird-midflap.png"),
|
||||||
.pivot = paradiso::Vector2<float>::make(0.0f, 0.0f),
|
.pivot = paradiso::Vector2<float>::make(0.0f, 0.0f),
|
||||||
.scale = paradiso::Vector2<float>::make(scalew, scaleh)},
|
.scale = paradiso::Vector2<float>::make(scalew, scaleh)},
|
||||||
paradiso::Sprite{
|
paradiso::Sprite{
|
||||||
.bitmap =
|
.bitmap =
|
||||||
image_loader::load(std::string("yellowbird-upflap.png")),
|
paradiso::BitmapIO::get().load("yellowbird-upflap.png"),
|
||||||
.pivot = paradiso::Vector2<float>::make(0.0f, 0.0f),
|
.pivot = paradiso::Vector2<float>::make(0.0f, 0.0f),
|
||||||
.scale = paradiso::Vector2<float>::make(scalew, scaleh)}};
|
.scale = paradiso::Vector2<float>::make(scalew, scaleh)}};
|
||||||
}
|
}
|
||||||
|
@ -266,11 +268,16 @@ auto main() -> int {
|
||||||
// nothing beats a classic look
|
// nothing beats a classic look
|
||||||
ctx.set_clearcolor(paradiso::RGBA::from_rgb(0x00, 0x00, 0x00));
|
ctx.set_clearcolor(paradiso::RGBA::from_rgb(0x00, 0x00, 0x00));
|
||||||
|
|
||||||
|
|
||||||
|
// Asset loader bekommt den Pfad
|
||||||
|
|
||||||
|
paradiso::BitmapIO::get().set_path("assets");
|
||||||
|
|
||||||
// Load
|
// Load
|
||||||
auto background = Background{};
|
auto background = Background{};
|
||||||
auto grass = Grass{};
|
auto grass = Grass{};
|
||||||
|
|
||||||
auto flappyBird = FlappyBird{};
|
auto quickwingsapp = QuickWings{};
|
||||||
|
|
||||||
// timer
|
// timer
|
||||||
|
|
||||||
|
@ -285,13 +292,13 @@ auto main() -> int {
|
||||||
auto t1 = std::chrono::high_resolution_clock::now();
|
auto t1 = std::chrono::high_resolution_clock::now();
|
||||||
|
|
||||||
// Keyboard and state change
|
// Keyboard and state change
|
||||||
flappyBird.on_keyboard(w.keyboard_input());
|
quickwingsapp.on_keyboard(w.keyboard_input());
|
||||||
flappyBird.update();
|
quickwingsapp.update();
|
||||||
|
|
||||||
// Draw
|
// Draw
|
||||||
background.draw(shader);
|
background.draw(shader);
|
||||||
grass.draw(shader);
|
grass.draw(shader);
|
||||||
flappyBird.draw(shader);
|
quickwingsapp.draw(shader);
|
||||||
|
|
||||||
// wait for frame rate
|
// wait for frame rate
|
||||||
auto t2 = std::chrono::high_resolution_clock::now();
|
auto t2 = std::chrono::high_resolution_clock::now();
|
|
@ -8,6 +8,7 @@ add_subdirectory(src/vendor/glad)
|
||||||
add_subdirectory(src/vendor/glfw-3.3.8)
|
add_subdirectory(src/vendor/glfw-3.3.8)
|
||||||
|
|
||||||
set(paradiso_srcs
|
set(paradiso_srcs
|
||||||
|
src/bitmap_io.cpp
|
||||||
src/shader.cpp
|
src/shader.cpp
|
||||||
src/window.cpp
|
src/window.cpp
|
||||||
src/renderer.cpp
|
src/renderer.cpp
|
||||||
|
@ -18,6 +19,7 @@ set(paradiso_srcs
|
||||||
set(paradiso_incs
|
set(paradiso_incs
|
||||||
include/paradiso/aabb.hpp
|
include/paradiso/aabb.hpp
|
||||||
include/paradiso/bitmap.hpp
|
include/paradiso/bitmap.hpp
|
||||||
|
include/paradiso/bitmap_io.hpp
|
||||||
include/paradiso/geometry.hpp
|
include/paradiso/geometry.hpp
|
||||||
include/paradiso/sprite.hpp
|
include/paradiso/sprite.hpp
|
||||||
include/paradiso/shader.hpp
|
include/paradiso/shader.hpp
|
||||||
|
@ -35,6 +37,8 @@ target_include_directories(
|
||||||
paradiso_core
|
paradiso_core
|
||||||
PUBLIC
|
PUBLIC
|
||||||
include
|
include
|
||||||
|
PRIVATE
|
||||||
|
src/vendor/stb
|
||||||
)
|
)
|
||||||
|
|
||||||
target_link_libraries(
|
target_link_libraries(
|
||||||
|
|
56
src/lib/include/paradiso/bitmap_io.hpp
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2023 Hartmut Seichter
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#ifndef PARADISO_BITMAP_IO_HPP
|
||||||
|
#define PARADISO_BITMAP_IO_HPP
|
||||||
|
|
||||||
|
#include <paradiso/bitmap.hpp>
|
||||||
|
|
||||||
|
#include <string_view>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
namespace paradiso {
|
||||||
|
|
||||||
|
struct BitmapIO {
|
||||||
|
|
||||||
|
static BitmapIO& get();
|
||||||
|
|
||||||
|
Bitmap load(std::string_view filename, bool ignore_cache = false) const;
|
||||||
|
|
||||||
|
void set_path(std::string_view path);
|
||||||
|
|
||||||
|
std::string path() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
struct Impl;
|
||||||
|
std::unique_ptr<Impl> impl_;
|
||||||
|
|
||||||
|
BitmapIO();
|
||||||
|
~BitmapIO() = default;
|
||||||
|
BitmapIO(const BitmapIO&) = delete;
|
||||||
|
BitmapIO(BitmapIO&&) = delete;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace paradiso
|
||||||
|
|
||||||
|
#endif
|
141
src/lib/src/bitmap_io.cpp
Normal file
|
@ -0,0 +1,141 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2023 Hartmut Seichter
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
// based on image_loader by Robin Rottstädt
|
||||||
|
|
||||||
|
#include "paradiso/bitmap_io.hpp"
|
||||||
|
#include "paradiso/bitmap.hpp"
|
||||||
|
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
|
// STB image loading
|
||||||
|
#define STB_IMAGE_IMPLEMENTATION
|
||||||
|
#include "stb_image.h"
|
||||||
|
|
||||||
|
#include <filesystem>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
namespace paradiso {
|
||||||
|
|
||||||
|
struct BitmapIO::Impl {
|
||||||
|
|
||||||
|
std::filesystem::path asset_path_ = {};
|
||||||
|
|
||||||
|
using BitmapCacheType = std::unordered_map<std::string_view, Bitmap>;
|
||||||
|
|
||||||
|
BitmapCacheType cache_;
|
||||||
|
|
||||||
|
static Bitmap read(std::string_view filename) {
|
||||||
|
|
||||||
|
// Load with stb_image
|
||||||
|
stbi_set_flip_vertically_on_load(true); // flip y axis for OpenGL
|
||||||
|
|
||||||
|
int width{}, height{}, channels{};
|
||||||
|
|
||||||
|
auto stb_free = [](uint8_t* data) { stbi_image_free(data); };
|
||||||
|
|
||||||
|
if (std::unique_ptr<uint8_t, decltype(stb_free)> image{
|
||||||
|
stbi_load(filename.data(), &width, &height, &channels, 0)};
|
||||||
|
image.get()) {
|
||||||
|
|
||||||
|
int size = width * height;
|
||||||
|
|
||||||
|
// Convert to Vector of RGBA
|
||||||
|
std::vector<paradiso::RGBA> rgba =
|
||||||
|
std::vector<paradiso::RGBA>(size);
|
||||||
|
for (int i = 0; i < size; i++) {
|
||||||
|
// get rgba values
|
||||||
|
int pos = i * 4;
|
||||||
|
int r = image.get()[pos + 0];
|
||||||
|
int g = image.get()[pos + 1];
|
||||||
|
int b = image.get()[pos + 2];
|
||||||
|
int a = image.get()[pos + 3];
|
||||||
|
|
||||||
|
// bug in from_rgba. it expects bgra, not rgba
|
||||||
|
auto val = paradiso::RGBA::from_rgba(b, g, r, a);
|
||||||
|
rgba[i] = val;
|
||||||
|
}
|
||||||
|
|
||||||
|
// rotate image by 90 degrees CW
|
||||||
|
std::vector<paradiso::RGBA> rotated =
|
||||||
|
std::vector<paradiso::RGBA>(size);
|
||||||
|
for (int x = 0; x < width; x++) {
|
||||||
|
for (int y = 0; y < height; y++) {
|
||||||
|
|
||||||
|
int pos = y * width + x;
|
||||||
|
int pos_rotated = x * height + (height - y - 1);
|
||||||
|
rotated[pos_rotated] = rgba[pos];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return paradiso::Bitmap::from_data(
|
||||||
|
paradiso::Size{static_cast<unsigned int>(height),
|
||||||
|
static_cast<unsigned int>(width)},
|
||||||
|
rotated);
|
||||||
|
} else {
|
||||||
|
std::cerr << "cannot load " << filename << '\n';
|
||||||
|
}
|
||||||
|
|
||||||
|
return Bitmap(); // well, no exception ...
|
||||||
|
}
|
||||||
|
|
||||||
|
Bitmap load(std::string_view filename) {
|
||||||
|
if (cache_.find(filename) == cache_.end()) {
|
||||||
|
|
||||||
|
auto asset_filepath = asset_path_ / std::filesystem::path(filename);
|
||||||
|
|
||||||
|
std::cout << "Loading " << asset_filepath << std::endl;
|
||||||
|
|
||||||
|
// moving to C++23 this should be replaced with
|
||||||
|
// std::expected
|
||||||
|
auto data = read(asset_filepath.c_str());
|
||||||
|
|
||||||
|
cache_[filename] = data;
|
||||||
|
}
|
||||||
|
return cache_[filename.data()];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
BitmapIO::BitmapIO() : impl_{std::make_unique<BitmapIO::Impl>()} {}
|
||||||
|
|
||||||
|
BitmapIO& BitmapIO::get() {
|
||||||
|
static BitmapIO instance;
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
Bitmap BitmapIO::load(std::string_view filename, bool ignore_cache) const {
|
||||||
|
return impl_->load(filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BitmapIO::set_path(std::string_view path)
|
||||||
|
{
|
||||||
|
impl_->asset_path_ = path;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string BitmapIO::path() const
|
||||||
|
{
|
||||||
|
return impl_->asset_path_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace paradiso
|