Squash improve-ide-compat into main

Fixes GH-5

- cppcheck replaced with clang-tidy
- clang-tidy lint warnings fixed
- Reworked build tools from scratch to make IDE setup easier
- Added 1.5 IDE setup guides
This commit is contained in:
2023-11-10 21:30:55 +01:00
parent 189d19fd4a
commit ae4e265a90
66 changed files with 2017 additions and 1498 deletions

View File

@@ -1,5 +1,6 @@
#include "game.h"
#include <array>
#include <iostream>
#define GLM_FORCE_RADIANS
@@ -15,167 +16,181 @@
#include "logging.h"
using namespace progressia::main::logging;
namespace progressia {
namespace main {
namespace progressia::main {
std::unique_ptr<Primitive> cube1, cube2;
std::unique_ptr<Texture> texture1, texture2;
std::unique_ptr<View> perspective;
std::unique_ptr<Light> light;
class GameImpl : public Game {
GraphicsInterface *gint;
DISABLE_COPYING(GameImpl)
DISABLE_MOVING(GameImpl)
void addRect(glm::vec3 origin, glm::vec3 width, glm::vec3 height,
glm::vec4 color, std::vector<Vertex> &vertices,
std::vector<Vertex::Index> &indices) {
public:
std::unique_ptr<Primitive> cube1;
std::unique_ptr<Primitive> cube2;
std::unique_ptr<Texture> texture1;
std::unique_ptr<Texture> texture2;
std::unique_ptr<View> perspective;
std::unique_ptr<Light> light;
Vertex::Index offset = vertices.size();
GraphicsInterface *gint;
vertices.push_back({origin, color, {}, {0, 0}});
vertices.push_back({origin + width, color, {}, {0, 1}});
vertices.push_back({origin + width + height, color, {}, {1, 1}});
vertices.push_back({origin + height, color, {}, {1, 0}});
static void addRect(glm::vec3 origin, glm::vec3 width, glm::vec3 height,
glm::vec4 color, std::vector<Vertex> &vertices,
std::vector<Vertex::Index> &indices) {
indices.push_back(offset + 0);
indices.push_back(offset + 1);
indices.push_back(offset + 2);
Vertex::Index offset = vertices.size();
indices.push_back(offset + 0);
indices.push_back(offset + 2);
indices.push_back(offset + 3);
}
vertices.push_back({origin, color, {}, {0, 0}});
vertices.push_back({origin + width, color, {}, {0, 1}});
vertices.push_back({origin + width + height, color, {}, {1, 1}});
vertices.push_back({origin + height, color, {}, {1, 0}});
void addBox(glm::vec3 origin, glm::vec3 length, glm::vec3 height,
glm::vec3 depth, std::array<glm::vec4, 6> colors,
std::vector<Vertex> &vertices,
std::vector<Vertex::Index> &indices) {
addRect(origin, height, length, colors[0], vertices, indices);
addRect(origin, length, depth, colors[1], vertices, indices);
addRect(origin, depth, height, colors[2], vertices, indices);
addRect(origin + height, depth, length, colors[3], vertices, indices);
addRect(origin + length, height, depth, colors[4], vertices, indices);
addRect(origin + depth, length, height, colors[5], vertices, indices);
}
indices.push_back(offset + 0);
indices.push_back(offset + 1);
indices.push_back(offset + 2);
void initialize(GraphicsInterface &gintp) {
indices.push_back(offset + 0);
indices.push_back(offset + 2);
indices.push_back(offset + 3);
}
debug("game init begin");
gint = &gintp;
static void addBox(glm::vec3 origin, glm::vec3 length, glm::vec3 height,
glm::vec3 depth, std::array<glm::vec4, 6> colors,
std::vector<Vertex> &vertices,
std::vector<Vertex::Index> &indices) {
addRect(origin, height, length, colors[0], vertices, indices);
addRect(origin, length, depth, colors[1], vertices, indices);
addRect(origin, depth, height, colors[2], vertices, indices);
addRect(origin + height, depth, length, colors[3], vertices, indices);
addRect(origin + length, height, depth, colors[4], vertices, indices);
addRect(origin + depth, length, height, colors[5], vertices, indices);
}
texture1.reset(gint->newTexture(
progressia::main::loadImage(u"../assets/texture.png")));
texture2.reset(gint->newTexture(
progressia::main::loadImage(u"../assets/texture2.png")));
GameImpl(GraphicsInterface &gintp) {
// Cube 1
{
std::vector<Vertex> vertices;
std::vector<Vertex::Index> indices;
auto white = glm::vec4(1, 1, 1, 1);
debug("game init begin");
gint = &gintp;
addBox({-0.5, -0.5, -0.5}, {1, 0, 0}, {0, 1, 0}, {0, 0, 1},
{white, white, white, white, white, white}, vertices, indices);
texture1 =
gint->newTexture(progressia::main::loadImage("assets/texture.png"));
texture2 = gint->newTexture(
progressia::main::loadImage("assets/texture2.png"));
for (std::size_t i = 0; i < indices.size(); i += 3) {
Vertex &a = vertices[indices[i + 0]];
Vertex &b = vertices[indices[i + 1]];
Vertex &c = vertices[indices[i + 2]];
// Cube 1
{
std::vector<Vertex> vertices;
std::vector<Vertex::Index> indices;
auto white = glm::vec4(1, 1, 1, 1);
glm::vec3 x = b.position - a.position;
glm::vec3 y = c.position - a.position;
addBox({-0.5, -0.5, -0.5}, {1, 0, 0}, {0, 1, 0}, {0, 0, 1},
{white, white, white, white, white, white}, vertices,
indices);
glm::vec3 normal = glm::normalize(glm::cross(x, y));
for (std::size_t i = 0; i < indices.size(); i += 3) {
Vertex &a = vertices[indices[i + 0]];
Vertex &b = vertices[indices[i + 1]];
Vertex &c = vertices[indices[i + 2]];
a.normal = normal;
b.normal = normal;
c.normal = normal;
glm::vec3 x = b.position - a.position;
glm::vec3 y = c.position - a.position;
glm::vec3 normal = glm::normalize(glm::cross(x, y));
a.normal = normal;
b.normal = normal;
c.normal = normal;
}
cube1 = gint->newPrimitive(vertices, indices, &*texture1);
}
cube1.reset(gint->newPrimitive(vertices, indices, &*texture1));
}
// Cube 2
{
std::vector<Vertex> vertices;
std::vector<Vertex::Index> indices;
auto white = glm::vec4(1, 1, 1, 1);
// Cube 2
{
std::vector<Vertex> vertices;
std::vector<Vertex::Index> indices;
auto white = glm::vec4(1, 1, 1, 1);
addBox({-0.5, -2.5, -0.5}, {1, 0, 0}, {0, 1, 0}, {0, 0, 1},
{white, white, white, white, white, white}, vertices,
indices);
addBox({-0.5, -2.5, -0.5}, {1, 0, 0}, {0, 1, 0}, {0, 0, 1},
{white, white, white, white, white, white}, vertices, indices);
for (std::size_t i = 0; i < indices.size(); i += 3) {
Vertex &a = vertices[indices[i + 0]];
Vertex &b = vertices[indices[i + 1]];
Vertex &c = vertices[indices[i + 2]];
for (std::size_t i = 0; i < indices.size(); i += 3) {
Vertex &a = vertices[indices[i + 0]];
Vertex &b = vertices[indices[i + 1]];
Vertex &c = vertices[indices[i + 2]];
glm::vec3 x = b.position - a.position;
glm::vec3 y = c.position - a.position;
glm::vec3 x = b.position - a.position;
glm::vec3 y = c.position - a.position;
glm::vec3 normal = glm::normalize(glm::cross(x, y));
glm::vec3 normal = glm::normalize(glm::cross(x, y));
a.normal = normal;
b.normal = normal;
c.normal = normal;
}
a.normal = normal;
b.normal = normal;
c.normal = normal;
cube2 = gint->newPrimitive(vertices, indices, &*texture2);
}
cube2.reset(gint->newPrimitive(vertices, indices, &*texture2));
perspective = gint->newView();
light = gint->newLight();
debug("game init complete");
}
perspective.reset(gint->newView());
light.reset(gint->newLight());
void renderTick() override {
debug("game init complete");
}
{
float fov = 70.0F;
void renderTick() {
auto extent = gint->getViewport();
auto proj = glm::perspective(
glm::radians(fov), extent.x / (float)extent.y, 0.1F, 10.0F);
proj[1][1] *= -1;
{
float fov = 70.0f;
auto view = glm::lookAt(glm::vec3(2.0F, 2.0F, 2.0F),
glm::vec3(0.0F, 0.0F, 0.0F),
glm::vec3(0.0F, 0.0F, 1.0F));
auto extent = gint->getViewport();
auto proj = glm::perspective(glm::radians(fov),
extent.x / (float)extent.y, 0.1f, 10.0f);
proj[1][1] *= -1;
perspective->configure(proj, view);
}
auto view = glm::lookAt(glm::vec3(2.0f, 2.0f, 2.0f),
glm::vec3(0.0f, 0.0f, 0.0f),
glm::vec3(0.0f, 0.0f, 1.0f));
perspective->use();
perspective->configure(proj, view);
float contrast = glm::sin(gint->tmp_getTime() / 3) * 0.18F + 0.18F;
glm::vec3 color0(0.60F, 0.60F, 0.70F);
glm::vec3 color1(1.10F, 1.05F, 0.70F);
auto m =
static_cast<float>(glm::sin(gint->tmp_getTime() / 3) * 0.5 + 0.5);
glm::vec3 color = m * color1 + (1 - m) * color0;
light->configure(color, glm::vec3(1.0F, -2.0F, 1.0F), contrast, 0.1F);
light->use();
auto model = glm::eulerAngleYXZ(0.0F, 0.0F, gint->tmp_getTime() * 0.1F);
gint->setModelTransform(model);
cube1->draw();
cube2->draw();
}
perspective->use();
~GameImpl() override {
debug("game shutdown begin");
float contrast = glm::sin(gint->tmp_getTime() / 3) * 0.18f + 0.18f;
glm::vec3 color0(0.60f, 0.60f, 0.70f);
glm::vec3 color1(1.10f, 1.05f, 0.70f);
cube1.reset();
cube2.reset();
texture1.reset();
texture2.reset();
float m = glm::sin(gint->tmp_getTime() / 3) * 0.5 + 0.5;
glm::vec3 color = m * color1 + (1 - m) * color0;
light.reset();
perspective.reset();
light->configure(color, glm::vec3(1.0f, -2.0f, 1.0f), contrast, 0.1f);
light->use();
debug("game shutdown complete");
}
};
auto model = glm::eulerAngleYXZ(0.0f, 0.0f, gint->tmp_getTime() * 0.1f);
gint->setModelTransform(model);
cube1->draw();
cube2->draw();
std::unique_ptr<Game> makeGame(GraphicsInterface &gint) {
return std::make_unique<GameImpl>(gint);
}
void shutdown() {
debug("game shutdown begin");
cube1.reset();
cube2.reset();
texture1.reset();
texture2.reset();
light.reset();
perspective.reset();
debug("game shutdown complete");
}
} // namespace main
} // namespace progressia
} // namespace progressia::main

View File

@@ -1,13 +1,16 @@
#pragma once
#include "rendering.h"
#include "util.h"
namespace progressia {
namespace main {
namespace progressia::main {
void initialize(GraphicsInterface &);
void renderTick();
void shutdown();
class Game : private NonCopyable {
public:
virtual ~Game() = default;
virtual void renderTick() = 0;
};
} // namespace main
} // namespace progressia
std::unique_ptr<Game> makeGame(GraphicsInterface &);
} // namespace progressia::main

View File

@@ -8,8 +8,7 @@
#include <mutex>
#include <sstream>
namespace progressia {
namespace main {
namespace progressia::main {
namespace detail {
@@ -21,7 +20,7 @@ class LogSinkBackend {
void flush();
public:
LogSinkBackend() {}
LogSinkBackend() = default;
std::ostream &getOutput() { return buffer; }
@@ -46,14 +45,17 @@ class LogSinkBackend {
namespace {
std::ofstream openLogFile() {
// FIXME this is relative to bin, not root dir
std::filesystem::create_directories("../run");
std::filesystem::create_directories("../run/logs");
return std::ofstream("../run/logs/latest.log");
std::filesystem::create_directories("run");
std::filesystem::create_directories("run/logs");
return std::ofstream("run/logs/latest.log");
}
} // namespace
// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables): TODO
std::mutex logFileMutex;
// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
std::ofstream logFile = openLogFile();
// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
thread_local detail::LogSinkBackend theBackend;
std::ostream &detail::LogSink::getStream() const {
@@ -78,7 +80,7 @@ detail::LogSink::~LogSink() {
}
}
detail::LogSink::LogSink(LogSink &&moveFrom)
detail::LogSink::LogSink(LogSink &&moveFrom) noexcept
: isCurrentSink(moveFrom.isCurrentSink) {
moveFrom.isCurrentSink = false;
}
@@ -99,6 +101,7 @@ void detail::LogSinkBackend::flush() {
namespace {
// FIXME This approach is horribly inefficient. It is also unsafe if any
// other piece of code wants access to std::localtime.
// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
std::mutex getLocalTimeMutex;
std::tm getLocalTimeAndDontExplodePlease() {
std::lock_guard<std::mutex> lock(getLocalTimeMutex);
@@ -165,5 +168,4 @@ detail::LogSink fatal(const char *start) { return log(LogLevel::FATAL, start); }
} // namespace logging
} // namespace main
} // namespace progressia
} // namespace progressia::main

View File

@@ -1,14 +1,13 @@
#pragma once
#include "boost/core/noncopyable.hpp"
#include "util.h"
#include <ostream>
namespace progressia {
namespace main {
namespace progressia::main {
namespace detail {
class LogSink : private boost::noncopyable {
class LogSink : private progressia::main::NonCopyable {
private:
bool isCurrentSink;
@@ -24,7 +23,7 @@ class LogSink : private boost::noncopyable {
LogSink(bool isCurrentSink);
~LogSink();
LogSink(LogSink &&);
LogSink(LogSink &&) noexcept;
template <typename T>
friend const LogSink &operator<<(const LogSink &sink, const T &x) {
@@ -60,5 +59,4 @@ detail::LogSink fatal(const char *start = nullptr);
void initializeLogging();
void shutdownLogging();
} // namespace main
} // namespace progressia
} // namespace progressia::main

View File

@@ -1,10 +1,9 @@
#pragma once
#include "../config.h"
#include <config.h>
#include <cstdlib>
namespace progressia {
namespace main {
namespace progressia::main {
namespace meta {
namespace detail {
@@ -37,5 +36,4 @@ constexpr uint32_t VERSION_MINOR = (VERSION_NUMBER & 0x00FF00) >> 8;
constexpr uint32_t VERSION_PATCH = (VERSION_NUMBER & 0x0000FF) >> 0;
} // namespace meta
} // namespace main
} // namespace progressia
} // namespace progressia::main

View File

@@ -3,6 +3,4 @@
#include "rendering/graphics_interface.h"
#include "rendering/image.h"
namespace progressia {
namespace main {} // namespace main
} // namespace progressia
namespace progressia::main {} // namespace progressia::main

View File

@@ -1,6 +1,6 @@
#pragma once
#include "boost/core/noncopyable.hpp"
#include "../util.h"
#include <vector>
#define GLM_FORCE_RADIANS
@@ -12,8 +12,7 @@
#include "image.h"
namespace progressia {
namespace main {
namespace progressia::main {
struct Vertex {
@@ -25,31 +24,27 @@ struct Vertex {
glm::vec2 texCoord;
};
class Texture : private boost::noncopyable {
public:
using Backend = void *;
class Texture : private progressia::main::NonCopyable {
private:
Backend backend;
struct Backend;
std::unique_ptr<Backend> backend;
friend class GraphicsInterface;
friend class Primitive;
public:
Texture(Backend);
Texture(std::unique_ptr<Backend>);
~Texture();
};
class Primitive : private boost::noncopyable {
public:
using Backend = void *;
class Primitive : private progressia::main::NonCopyable {
private:
Backend backend;
struct Backend;
std::unique_ptr<Backend> backend;
friend class GraphicsInterface;
public:
Primitive(Backend);
Primitive(std::unique_ptr<Backend>);
~Primitive();
void draw();
@@ -57,30 +52,28 @@ class Primitive : private boost::noncopyable {
const Texture *getTexture() const;
};
class View : private boost::noncopyable {
public:
using Backend = void *;
class View : private progressia::main::NonCopyable {
private:
Backend backend;
struct Backend;
std::unique_ptr<Backend> backend;
friend class GraphicsInterface;
public:
View(Backend);
View(std::unique_ptr<Backend>);
~View();
void configure(const glm::mat4 &proj, const glm::mat4 &view);
void use();
};
class Light : private boost::noncopyable {
public:
using Backend = void *;
class Light : private progressia::main::NonCopyable {
private:
Backend backend;
struct Backend;
std::unique_ptr<Backend> backend;
friend class GraphicsInterface;
public:
Light(Backend);
Light(std::unique_ptr<Backend>);
~Light();
void configure(const glm::vec3 &color, const glm::vec3 &from,
@@ -88,7 +81,7 @@ class Light : private boost::noncopyable {
void use();
};
class GraphicsInterface : private boost::noncopyable {
class GraphicsInterface : private progressia::main::NonCopyable {
public:
using Backend = void *;
@@ -99,18 +92,18 @@ class GraphicsInterface : private boost::noncopyable {
GraphicsInterface(Backend);
~GraphicsInterface();
Texture *newTexture(const Image &);
std::unique_ptr<Texture> newTexture(const Image &);
Primitive *newPrimitive(const std::vector<Vertex> &,
const std::vector<Vertex::Index> &,
Texture *texture);
std::unique_ptr<Primitive> newPrimitive(const std::vector<Vertex> &,
const std::vector<Vertex::Index> &,
Texture *texture);
glm::vec2 getViewport() const;
void setModelTransform(const glm::mat4 &);
View *newView();
Light *newLight();
std::unique_ptr<View> newView();
std::unique_ptr<Light> newLight();
void flush();
void startNextLayer();
@@ -119,5 +112,4 @@ class GraphicsInterface : private boost::noncopyable {
uint64_t getLastStartedFrame();
};
} // namespace main
} // namespace progressia
} // namespace progressia::main

View File

@@ -4,15 +4,17 @@
#include <filesystem>
#include <fstream>
#include <iostream>
#include <limits>
#include <vector>
#include "stb/stb_image.h"
#include <embedded_resources.h>
#include "../logging.h"
using namespace progressia::main::logging;
namespace progressia {
namespace main {
namespace progressia::main {
std::size_t Image::getSize() const { return data.size(); }
@@ -20,33 +22,36 @@ const Image::Byte *Image::getData() const { return data.data(); }
Image::Byte *Image::getData() { return data.data(); }
Image loadImage(const std::filesystem::path &path) {
Image loadImage(const std::string &path) {
std::ifstream file(path, std::ios::ate | std::ios::binary);
auto resource = __embedded_resources::getEmbeddedResource(path);
if (!file.is_open()) {
fatal() << "Could not access a PNG image in file " << path;
if (resource.data == nullptr) {
// REPORT_ERROR
progressia::main::logging::fatal()
<< "Could not find resource \"" << path << "\"";
exit(1);
}
std::size_t fileSize = static_cast<std::size_t>(file.tellg());
std::vector<Image::Byte> png(fileSize);
std::vector<Image::Byte> png(resource.data,
resource.data + resource.length);
file.seekg(0);
file.read(reinterpret_cast<char *>(png.data()), fileSize);
if (png.size() > std::numeric_limits<int>::max()) {
// REPORT_ERROR
progressia::main::logging::fatal()
<< "Could not load \"" << path << "\": image file too large";
exit(1);
}
file.close();
int dataSize = static_cast<int>(png.size());
int width = 0;
int height = 0;
int channelsInFile = 0;
int width;
int height;
int channelsInFile;
Image::Byte *stbAllocatedData = stbi_load_from_memory(
png.data(), dataSize, &width, &height, &channelsInFile, STBI_rgb_alpha);
Image::Byte *stbAllocatedData =
stbi_load_from_memory(png.data(), png.size(), &width, &height,
&channelsInFile, STBI_rgb_alpha);
if (stbAllocatedData == NULL) {
if (stbAllocatedData == nullptr) {
fatal() << "Could not decode a PNG image from file " << path;
// REPORT_ERROR
exit(1);
@@ -61,5 +66,4 @@ Image loadImage(const std::filesystem::path &path) {
data};
}
} // namespace main
} // namespace progressia
} // namespace progressia::main

View File

@@ -3,8 +3,7 @@
#include <filesystem>
#include <vector>
namespace progressia {
namespace main {
namespace progressia::main {
class Image {
public:
@@ -19,7 +18,6 @@ class Image {
Byte *getData();
};
Image loadImage(const std::filesystem::path &);
Image loadImage(const std::string &);
} // namespace main
} // namespace progressia
} // namespace progressia::main

View File

@@ -28,3 +28,25 @@
}; \
}
// clang-format on
// clang-format off
#define DISABLE_MOVING(CLASS) \
CLASS &operator=(CLASS &&) = delete; \
CLASS(CLASS &&) = delete; \
// clang-format on
// clang-format off
#define DISABLE_COPYING(CLASS) \
CLASS &operator=(const CLASS &) = delete; \
CLASS(const CLASS &) = delete; \
// clang-format on
namespace progressia::main {
struct NonCopyable {
NonCopyable &operator=(const NonCopyable &) = delete;
NonCopyable(const NonCopyable &) = delete;
NonCopyable() = default;
};
} // namespace progressia::main