Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • gamedev/fggl
  • onuralpsezer/fggl
2 results
Show changes
Showing
with 1332 additions and 260 deletions
/*
* ${license.title}
* Copyright (C) 2022 ${license.owner}
* ${license.mailto}
* This file is part of FGGL.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
* FGGL is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
* FGGL is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* You should have received a copy of the GNU Lesser General Public License along with FGGL.
* If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef FGGL_MATH_PHYS3D_SHAPES_HPP
#define FGGL_MATH_PHYS3D_SHAPES_HPP
#ifndef FGGL_MATH_SHAPES_HPP
#define FGGL_MATH_SHAPES_HPP
#include "fggl/math/types.hpp"
#include <vector>
......@@ -63,9 +57,9 @@ namespace fggl::math::phs3d {
math::vec3 min;
math::vec3 max;
void add(const math::vec3& p);
void add(const math::vec3 &p);
void emtpy();
void set(const AABB& other, const math::mat4& m);
void set(const AABB &other, const math::mat4 &m);
inline math::vec3 center() const {
return (min + max) / 2.0F;
......@@ -79,23 +73,23 @@ namespace fggl::math::phs3d {
return max - center();
}
static AABB fromPoints(const std::vector<math::vec3>& points);
static AABB fromPoints(const std::vector<math::vec3> &points);
};
struct Plane {
glm::vec3 normal;
float d; // distance to origin
inline bool contains(const math::vec3& point) {
inline bool contains(const math::vec3 &point) {
return glm::dot(point, normal) == d;
}
inline float distance(const math::vec3& q) {
inline float distance(const math::vec3 &q) {
return glm::dot(q, normal) - d;
}
static Plane fromPoints(const math::vec3, const math::vec3, const math::vec3);
static Plane bestFit(const std::vector<math::vec3>& points);
static Plane bestFit(const std::vector<math::vec3> &points);
};
struct Barycentric {
......@@ -104,8 +98,8 @@ namespace fggl::math::phs3d {
bool inTriangle() {
return 0 <= b[0] && b[0] <= 1 &&
0 <= b[1] && b[1] <= 1 &&
0 <= b[2] && b[2] <= 1;
0 <= b[1] && b[1] <= 1 &&
0 <= b[2] && b[2] <= 1;
}
inline bool isLegal() const {
......@@ -113,8 +107,8 @@ namespace fggl::math::phs3d {
}
};
constexpr float THIRD = 1.0F/3.0F;
const Barycentric cGrav = { {THIRD, THIRD, THIRD}};
constexpr float THIRD = 1.0F / 3.0F;
const Barycentric cGrav = {{THIRD, THIRD, THIRD}};
struct Triangle {
std::array<math::vec3, 3> v;
......@@ -136,11 +130,11 @@ namespace fggl::math::phs3d {
}
inline float length(int a, int b) const {
return glm::length( edge(a, b));
return glm::length(edge(a, b));
}
inline float perimeter() const {
return length(3, 2) + length(1,3) + length(2, 1);
return length(3, 2) + length(1, 3) + length(2, 1);
}
inline float area() const {
......@@ -196,17 +190,17 @@ namespace fggl::math::phs3d {
return 0.0F;
}
bool CartToBarycentric(const math::vec3& cart, Barycentric& outVal);
bool CartToBarycentric2(const math::vec3& cart, Barycentric& outVal);
bool CartToBarycentric(const math::vec3 &cart, Barycentric &outVal);
bool CartToBarycentric2(const math::vec3 &cart, Barycentric &outVal);
math::vec3 BarycentricToCart(const Barycentric& p) const {
math::vec3 BarycentricToCart(const Barycentric &p) const {
return v[0] * p.b[0] +
v[1] * p.b[1] +
v[2] * p.b[2];
v[1] * p.b[1] +
v[2] * p.b[2];
}
};
} // namespace fggl::math::phys3d
#endif //FGGL_MATH_PHYS3D_SHAPES_HPP
#endif //FGGL_MATH_SHAPES_HPP
/*
* This file is part of FGGL.
*
* FGGL is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* FGGL is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with FGGL.
* If not, see <https://www.gnu.org/licenses/>.
*/
//
// Created by webpigeon on 27/11/22.
//
#ifndef FGGL_MATH_STATS_HPP
#define FGGL_MATH_STATS_HPP
#include <cstdint>
#include <cmath>
namespace fggl::math {
class CumulativeAverage {
public:
inline void add(float item) {
m_current = ( item + (m_count * m_current) ) / (m_count + 1);
m_count++;
}
inline float average() {
return m_current;
}
private:
float m_current;
std::size_t m_count;
};
/**
* Useful Statistics class.
* ported to C++ from Piers' Java implementation.
*
* @tparam T
*/
template<typename T>
class Statistics {
public:
void add(T observation) {
m_count++;
m_sum += observation;
m_sumSquared += (observation * observation);
m_min = std::min(m_min, observation);
m_max = std::max(m_max, observation);
m_dirty = true;
}
inline T average() {
compute();
return m_average;
}
inline T average() const {
if ( m_dirty ) {
return m_sum / m_count;
}
return m_average;
}
inline T standardDeviation() {
compute();
return m_standardDiv;
}
inline T standardDeviation() const {
if ( !m_dirty ) {
return m_standardDiv;
}
T avg = average();
T num = m_sumSquared - (m_count * avg * avg);
return num < 0 ? 0 : sqrt( num / (m_count-1));
}
inline T standardError() {
compute();
return m_standardDiv / sqrt(m_count);
}
inline T standardError() const {
if ( !m_dirty ) {
return m_standardDiv / sqrt(m_count);
}
return standardDeviation() / sqrt(m_count);
}
inline T squareSum () const {
return m_sumSquared;
}
inline std::size_t count() const {
return m_count;
}
inline T sum() const {
return m_sum;
}
inline T min() const {
return m_min;
}
inline T max() const {
return m_max;
}
private:
T m_average{0};
T m_sum{0};
T m_sumSquared{0};
T m_standardDiv{0};
T m_min{0};
T m_max{0};
std::size_t m_count{0};
bool m_dirty{false};
void compute() {
if ( !m_dirty ) {
return;
}
m_average = m_sum / m_count;
T num = m_sumSquared - (m_count * m_average * m_average);
if ( num < 0 ) {
num = 0;
}
m_standardDiv = sqrt( num / (m_count-1) );
m_dirty = false;
}
};
using StatisticsF = Statistics<float>;
using StatisticsD = Statistics<double>;
} // namespace fggl::math
#endif //FGGL_MATH_STATS_HPP
/*
* This file is part of FGGL.
*
* FGGL is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* FGGL is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with FGGL.
* If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef FGGL_MATH_TRIANGULATION_HPP
#define FGGL_MATH_TRIANGULATION_HPP
......@@ -113,13 +127,13 @@ namespace fggl::math {
}
static data::Vertex2D pointToVertex(const math::vec2 &point) {
return data::Vertex2D{ point, {1.0f, 1.0f, 1.0f} };
return data::Vertex2D{point, {1.0F, 1.0F, 1.0F}, {0.0F, 0.0F}};
}
/**
* Fast Triangulation for convex polygons.
*/
void fan_triangulation(const PolygonVertex& polygon, data::Mesh2D &mesh);
void fan_triangulation(const PolygonVertex &polygon, data::Mesh2D &mesh);
} // namespace fggl::util
......
#ifndef FGGL_MATH_TYPES_H
#define FGGL_MATH_TYPES_H
/*
* This file is part of FGGL.
*
* FGGL is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* FGGL is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with FGGL.
* If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef FGGL_MATH_TYPES_HPP
#define FGGL_MATH_TYPES_HPP
#include <tuple>
#include <iostream>
#include <glm/glm.hpp>
#include "fggl/math/vector.hpp"
#include <glm/ext/matrix_transform.hpp>
#include <glm/gtc/quaternion.hpp>
#include <glm/gtx/transform.hpp>
#include <glm/gtx/euler_angles.hpp>
#include <glm/gtx/quaternion.hpp>
#include "fggl/math/fmath.hpp"
#include "fggl/util/guid.hpp"
#ifndef M_PI
#define M_PI 3.14159265358979323846
#define M_PI 3.14159265358979323846
#endif
#ifndef M_PI_2
#define M_PI_2 1.57079632679489661923
#define M_PI_2 1.57079632679489661923
#endif
namespace fggl::math {
......@@ -25,38 +43,102 @@ namespace fggl::math {
constexpr float HALF_PI = M_PI_2;
constexpr float TAU = PI * 2;
using uint8 = std::uint8_t;
// math types (aliased for ease of use)
/**
* A 4D floating-point vector.
*/
using vec4 = glm::vec4;
using vec4f = glm::vec4;
/**
* A 4D signed integer vector.
*/
using vec4i = glm::ivec4;
using vec4ui = glm::ivec4;
/**
* A 4D unsigned integer vector.
*/
using vec4ui = glm::uvec4;
/**
* A 3D floating-point vector.
*/
using vec3 = glm::vec3;
/**
* A 3D integer vector.
*/
using vec3i = glm::ivec3;
using vec3f = glm::vec3;
using vec3ui = glm::ivec3;
/**
* A 3D unsigned integer vector.
*/
using vec3ui = glm::uvec3;
/**
* A 2D floating-point vector
*/
using vec2 = glm::vec2;
using vec2f = glm::vec2;
/**
* A 2D integer vector
*/
using vec2i = glm::ivec2;
using vec2ui = glm::ivec2;
/**
* a 2D unsigned integer vector
*/
using vec2ui = glm::uvec2;
using vec2b = glm::bvec2;
using vec3b = glm::bvec3;
using vec4b = glm::bvec4;
/**
* A 2x2 floating-point matrix.
*/
using mat2 = glm::mat2;
/**
* A 3x3 floating-point matrix.
*/
using mat3 = glm::mat3;
/**
* A 4x4 floating-point matrix.
*/
using mat4 = glm::mat4;
/**
* A quaternion.
*/
using quat = glm::quat;
constexpr static const math::vec2 VEC2_ZERO {0.0F, 0.0F};
constexpr static const math::vec3 VEC3_ZERO {0.0F, 0.0F, 0.0F};
constexpr static const math::vec3 VEC3_ONES {1.0F, 1.0F, 1.0F};
constexpr static const math::mat4 IDENTITY_M4{1.0F};
constexpr static const math::quat IDENTITY_Q{1.0F, 0.0, 0.0, 0.0};
constexpr static const math::vec3 AXIS_X{1.0F, 0.0F, 0.0F};
constexpr static const math::vec3 AXIS_Y{0.0F, 1.0F, 0.0F};
constexpr static const math::vec3 AXIS_Z{0.0F, 0.0F, 1.0F};
constexpr static const math::mat4 IDENTITY_M4 {1.0F};
constexpr static const math::quat IDENTITY_Q {1.0F, 0.0, 0.0, 0.0};
constexpr auto minElm(vec3 a, vec3 b) -> vec3{
return {
a.x < b.x ? a.x : b.x,
a.y < b.y ? a.y : b.y,
a.z < b.z ? a.z : b.z
};
}
constexpr static const math::vec3 AXIS_X { 1.0F, 0.0F, 0.0F };
constexpr static const math::vec3 AXIS_Y { 0.0F, 1.0F, 0.0F };
constexpr static const math::vec3 AXIS_Z { 0.0F, 0.0F, 1.0F };
constexpr auto maxElm(vec3 a, vec3 b) -> vec3 {
return {
a.x > b.x ? a.x : b.x,
a.y > b.y ? a.y : b.y,
a.z > b.z ? a.z : b.z
};
}
// fastFloor from OpenSimplex2
inline int fastFloor(double x) {
......@@ -64,27 +146,60 @@ namespace fggl::math {
return x < xi ? xi - 1 : xi;
}
inline float rescale_norm(float value, float min, float max) {
/**
* Rescale a value between [min, max] into [0, 1].
*
* @param value the value to rescale
* @param min the minimum value of the original range
* @param max the maximum value of the original range
* @return the rescaled value, [0, 1]
*/
constexpr float rescale_norm(float value, float min, float max) {
return (value - min) / (max - min);
}
inline float rescale_norm(float value, float min, float max, float newMin, float newMax) {
/**
* Rescale a value between [min, max] into [newMin, newMax].
*
* @param value the value to rescale
* @param min the minimum value of the original range
* @param max the maximum value of the original range
* @param newMin the new minimum value
* @param newMax the new maximum value
* @return the rescaled value, [newMin, newMax]
*/
constexpr float rescale_norm(float value, float min, float max, float newMin, float newMax) {
return newMin + ((value - min) * (newMax - newMin)) / (max - min);
}
inline float rescale_ndc(float value, float newMin, float newMax){
/**
* Rescale a normalised device-coordinate value [-1, 1] into another range.
*
* @param value the value to rescale, [-1.0, 1.0]
* @param newMin the new minimum value
* @param newMax the new maximum value
* @return the rescaled value, [newMin, newMax]
*/
constexpr float rescale_ndc(float value, float newMin, float newMax) {
return rescale_norm(value, -1, 1, newMin, newMax);
}
inline float rescale_01(float value, float newMin, float newMax){
/**
* Rescale a normalised value [0, 1] into another range.
*
* @param value the value to rescale
* @param newMin the new minimum value
* @param newMax the new maximum value
* @return the rescaled value, [newMin, newMax]
*/
constexpr float rescale_01(float value, float newMin, float newMax) {
return rescale_norm(value, 0, 1, newMin, newMax);
}
inline float recale_mean(float value, float avg, float max, float min) {
constexpr float recale_mean(float value, float avg, float max, float min) {
return (value - avg) / (max - min);
}
// reference vectors
constexpr vec3f UP{0.0f, 1.0f, 0.0f};
constexpr vec3f FORWARD{1.0f, 0.0f, 0.0f};
......@@ -98,8 +213,14 @@ namespace fggl::math {
return modelMatrix(offset, glm::quat(eulerAngles));
}
// FIXME: we have multiple definitions of rays in the codebase!
struct Ray {
vec3 origin;
vec3 direction;
};
struct Transform {
constexpr static const char name[] = "Transform";
constexpr static const util::GUID guid = util::make_guid("Transform");
Transform() :
m_model(IDENTITY_M4),
......@@ -167,14 +288,14 @@ namespace fggl::math {
[[nodiscard]]
inline mat4 local() const {
const glm::mat4 transformX = glm::rotate( math::IDENTITY_M4,glm::radians(m_euler.x), AXIS_X );
const glm::mat4 transformY = glm::rotate( math::IDENTITY_M4, glm::radians(m_euler.y), AXIS_Y );
const glm::mat4 transformZ = glm::rotate( math::IDENTITY_M4, glm::radians(m_euler.z), AXIS_Z );
const glm::mat4 transformX = glm::rotate(math::IDENTITY_M4, glm::radians(m_euler.x), AXIS_X);
const glm::mat4 transformY = glm::rotate(math::IDENTITY_M4, glm::radians(m_euler.y), AXIS_Y);
const glm::mat4 transformZ = glm::rotate(math::IDENTITY_M4, glm::radians(m_euler.z), AXIS_Z);
const auto rotation = transformY * transformX * transformZ;
return glm::translate(math::IDENTITY_M4, m_origin)
* rotation
* glm::scale( math::IDENTITY_M4, m_scale );
* glm::scale(math::IDENTITY_M4, m_scale);
}
[[nodiscard]]
......@@ -182,7 +303,7 @@ namespace fggl::math {
return local();
}
inline void update(const math::mat4& parent) {
inline void update(const math::mat4 &parent) {
m_model = parent * local();
}
......@@ -202,14 +323,14 @@ namespace fggl::math {
vec3 m_scale;
};
}
inline math::mat4 calc_view_matrix(const Transform &transform) {
return glm::lookAt(transform.origin(), transform.origin() + transform.forward(), transform.up());
}
// feels a bit strange to be doing this...
namespace glm {
inline bool operator<(const vec3 &lhs, const vec3 &rhs) {
return std::tie(lhs.x, lhs.y, lhs.z)
< std::tie(rhs.x, rhs.y, rhs.z);
inline math::mat4 calc_view_matrix(const Transform &transform, vec3 target) {
return glm::lookAt(transform.origin(), target, transform.up());
}
}
#endif
/*
* This file is part of FGGL.
*
* FGGL is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* FGGL is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with FGGL.
* If not, see <https://www.gnu.org/licenses/>.
*/
//
// Created by webpigeon on 20/08/22.
//
#ifndef FGGL_MATH_VECTOR_HPP
#define FGGL_MATH_VECTOR_HPP
#include <ostream>
#include <tuple>
#define GLM_ENABLE_EXPERIMENTAL
#include <glm/glm.hpp>
namespace glm {
inline bool operator<(const vec2 &lhs, const vec2 &rhs) {
return std::tie(lhs.x, lhs.y)
< std::tie(rhs.x, rhs.y);
}
inline bool operator<(const vec3 &lhs, const vec3 &rhs) {
return std::tie(lhs.x, lhs.y, lhs.z)
< std::tie(rhs.x, rhs.y, rhs.z);
}
inline bool operator<(const vec4 &lhs, const vec4 &rhs) {
return std::tie(lhs.x, lhs.y, lhs.z, lhs.w)
< std::tie(rhs.x, rhs.y, rhs.z, rhs.w);
}
// output stream operators
inline std::ostream &operator<<(std::ostream &os, const vec2 &v) {
os << "(" << v.x << ", " << v.y << ")";
return os;
}
inline std::ostream &operator<<(std::ostream &os, const vec3 &v) {
os << "(" << v.x << ", " << v.y << "," << v.z << ")";
return os;
}
inline std::ostream &operator<<(std::ostream &os, const vec4 &v) {
os << "(" << v.x << ", " << v.y << "," << v.z << "," << v.w << ")";
return os;
}
}
#endif //FGGL_MATH_VECTOR_HPP
/*
* This file is part of FGGL.
*
* FGGL is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* FGGL is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with FGGL.
* If not, see <https://www.gnu.org/licenses/>.
*/
//
// Created by webpigeon on 22/10/22.
// FIXME HACKY IMPLEMENTATION DETAIL BECAUSE THE ASSET LOADING PIPELINE IS BAD
//
#include "fggl/mesh/mesh.hpp"
#ifndef FGGL_MESH_COMPONENTS_HPP
#define FGGL_MESH_COMPONENTS_HPP
namespace fggl::mesh {
struct StaticMesh3D {
constexpr static const char name[] = "StaticMesh3D";
constexpr static const util::GUID guid = util::make_guid(name);
util::GUID meshReference;
Mesh3D mesh;
std::string pipeline;
inline StaticMesh3D() = default;
inline StaticMesh3D(const Mesh3D &aMesh, std::string aPipeline) :
mesh(aMesh), pipeline(std::move(aPipeline)) {}
};
struct StaticMultiMesh3D {
constexpr static const char name[] = "StaticMultiMesh3D";
constexpr static const util::GUID guid = util::make_guid(name);
util::GUID meshReference;
MultiMesh3D mesh;
std::string pipeline;
inline StaticMultiMesh3D() = default;
inline StaticMultiMesh3D(const MultiMesh3D &aMesh, std::string aPipeline) :
mesh(aMesh), pipeline(std::move(aPipeline)) {}
};
}
#endif //FGGL_MESH_COMPONENTS// _HPP
/*
* This file is part of FGGL.
*
* FGGL is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* FGGL is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with FGGL.
* If not, see <https://www.gnu.org/licenses/>.
*/
//
// Created by webpigeon on 18/10/22.
//
#ifndef FGGL_MESH_MESH_HPP
#define FGGL_MESH_MESH_HPP
#include "fggl/math/types.hpp"
#include "fggl/assets/types.hpp"
#include <vector>
#include <span>
namespace fggl::mesh {
struct Vertex3D {
math::vec3 position;
math::vec3 normal;
math::vec3 colour{ 1.0F, 1.0F, 1.0F };
math::vec2 texPos{ NAN, NAN };
static Vertex3D from_pos(math::vec3 pos) {
return {
.position = pos,
.normal {NAN, NAN, NAN},
.colour {1.0F, 1.0F, 1.0F},
.texPos { pos.x, pos.z }
};
}
};
struct Vertex2D {
math::vec2 position;
math::vec2 colour;
math::vec2 texPos;
};
enum TextureType {
DIFFUSE, NORMAL
};
constexpr auto MISSING_TEXTURE = assets::AssetID::make(0);
struct Material {
std::string name;
math::vec3 ambient;
math::vec3 diffuse;
math::vec3 specular;
std::vector<assets::AssetID> diffuseTextures{};
std::vector<assets::AssetID> normalTextures{};
std::vector<assets::AssetID> specularTextures{};
inline assets::AssetID getPrimaryDiffuse() {
assert( !diffuseTextures.empty() );
return diffuseTextures.empty() ? MISSING_TEXTURE : diffuseTextures[0];
}
inline assets::AssetID getPrimaryNormals() {
assert( !normalTextures.empty() );
return normalTextures.empty() ? MISSING_TEXTURE : normalTextures[0];
}
inline assets::AssetID getPrimarySpecular() {
assert( !specularTextures.empty() );
return specularTextures.empty() ? MISSING_TEXTURE : specularTextures[0];
}
};
template<typename VertexFormat>
struct Mesh {
std::vector<VertexFormat> data;
std::vector<uint32_t> indices;
assets::AssetID material;
inline uint32_t append(const VertexFormat& vert) {
auto nextIdx = data.size();
data.push_back(vert);
return nextIdx;
}
};
template<typename MeshFormat>
struct MultiMesh {
std::vector<MeshFormat> meshes;
std::vector<assets::AssetID> materials;
MeshFormat& generate() {
return meshes.template emplace_back();
}
};
using Mesh2D = Mesh<Vertex2D>;
using MultiMesh2D = MultiMesh<Mesh2D>;
using Mesh3D = Mesh<Vertex3D>;
using MultiMesh3D = MultiMesh<Mesh3D>;
}
#endif //FGGL_MESH_MESH_HPP
/*
* This file is part of FGGL.
*
* FGGL is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* FGGL is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with FGGL.
* If not, see <https://www.gnu.org/licenses/>.
*/
//
// Created by webpigeon on 27/06/22.
//
#ifndef FGGL_MODULES_MANAGER_HPP
#define FGGL_MODULES_MANAGER_HPP
#include "fggl/modules/module.hpp"
#include "fggl/debug/logging.hpp"
#include "fggl/ds/graph.hpp"
#include <cassert>
#include <queue>
#include <vector>
#include <map>
#include <stack>
#include <set>
#include <iostream>
namespace fggl::modules {
/**
* Store and initialise modules present in the engine.
*
* This class is responsible for keeping track of which modules the library user has requested, and ensuring that
* their dependencies are loaded in the correct order. Once the dependency graph has been built and instances
* created, it is responsible for providing references to these initialised classes.
*/
class Manager {
public:
Manager() = default;
template<ServiceType T>
class Service {
public:
inline Service(Manager* manager) : m_manager(manager) {}
inline T* operator->() {
if ( m_ptr == nullptr ) {
m_ptr = m_manager->get<T>();
}
return m_ptr;
}
private:
Manager* m_manager;
std::shared_ptr<T> m_ptr;
};
inline void addVirtual(const Config &config) {
assert(!m_locked);
m_modules[config.name] = config;
for (const auto &service : config.provides) {
m_serviceProviders[service] = config.name;
}
}
template<ModuleType T>
void use() {
assert(!m_locked);
Config config{.name = T::name, .provides = {}, .depends = {}};
for (auto service : T::provides) {
config.provides.push_back(service);
}
for (auto service : T::depends) {
config.depends.push_back(service);
}
config.factory = T::factory;
addVirtual(config);
}
// FIXME this should be in cpp file
bool buildGraph() {
// resolve links between modules
for (auto &moduleItr : m_modules) {
if (moduleItr.second.depends.empty()) {
m_dependencies.addVertex(moduleItr.first);
continue;
}
for (auto &service : moduleItr.second.depends) {
auto provider = m_serviceProviders.find(service);
if (provider == m_serviceProviders.end()) {
debug::log(debug::Level::warning,
"{} depends on {}, but nothing provides it",
moduleItr.first,
service.get());
// nothing can provide the service requested, setup is invalid.
return false;
}
m_dependencies.addEdge(moduleItr.first, provider->second);
}
}
return true;
}
template<ServiceType T>
T *get() const {
assert(m_locked);
return m_services.template get<T>();
}
template<ServiceType T>
Service<T> getLazy() const {
assert(m_locked);
return { this };
}
//FIXME this should be in cpp file!
void resolve() {
assert( !m_locked );
if (!buildGraph()) {
return;
}
std::queue<ModuleIdentifier> stack;
m_dependencies.getOrderRev(stack);
while (!stack.empty()) {
auto nextToInit = stack.front();
debug::log(debug::Level::info, "Initializing {}", nextToInit);
auto &module = m_modules.at(nextToInit);
if (module.factory != nullptr) {
for (auto &service : module.provides) {
bool result = module.factory(service, m_services);
if (!result) {
debug::log(debug::Level::warning,
"{} could not create service {}",
nextToInit,
service.get());
}
}
} else {
debug::log(debug::Level::warning, "{} has no factory - skipping", nextToInit);
}
stack.pop();
}
debug::log(debug::Level::info, "engine boot complete");
m_locked = true;
}
inline Services& services() {
return m_services;
}
private:
bool m_locked = false;
Services m_services;
std::map<ModuleIdentifier, Config> m_modules;
ds::DirectedGraph<ModuleIdentifier> m_dependencies;
std::map<ServiceName, ModuleIdentifier> m_serviceProviders;
};
} // namespace fggl::modules
#endif //FGGL_MODULES_MANAGER_HPP
/*
* This file is part of FGGL.
*
* FGGL is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* FGGL is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with FGGL.
* If not, see <https://www.gnu.org/licenses/>.
*/
//
// Created by webpigeon on 27/06/22.
//
#ifndef FGGL_MODULES_MODULE_HPP
#define FGGL_MODULES_MODULE_HPP
#include <string>
#include <vector>
#include <functional>
#include <map>
#include <memory>
#include "fggl/util/safety.hpp"
#include "service.hpp"
namespace fggl::modules {
template<typename T>
concept ModuleType = requires(T type) {
{ T::provides };
{ T::depends };
};
using ModuleIdentifier = std::string;
using ServiceFactory = std::function<bool(ServiceName , Services &)>;
struct Config {
ModuleIdentifier name;
std::vector<ServiceName> provides;
std::vector<ServiceName> depends;
ServiceFactory factory = nullptr;
};
class Module {
public:
virtual ~Module() = default;
// copying modules is bad
Module(const Module&) = delete;
Module& operator=(const Module&) = delete;
// moving modules is bad
Module(Module&&) = delete;
Module& operator=(Module&&) = delete;
virtual auto create(ServiceName, Services&) -> bool = 0;
};
} // namespace fggl::modules
#endif //FGGL_MODULES_MODULE_HPP
/*
* This file is part of FGGL.
*
* FGGL is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* FGGL is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with FGGL.
* If not, see <https://www.gnu.org/licenses/>.
*/
//
// Created by webpigeon on 25/03/23.
//
#ifndef FGGL_MODULES_SERVICE_HPP
#define FGGL_MODULES_SERVICE_HPP
#include <map>
#include <memory>
#include "fggl/util/safety.hpp"
namespace fggl::modules {
using ServiceName = util::OpaqueName<std::string_view, struct ModuleServiceTag>;
constexpr ServiceName make_service(const std::string_view name) {
return ServiceName::make(name);
}
template<typename T>
concept ServiceType = requires(T* type) {
{ T::service };
};
template<typename T, typename U>
concept Derived = std::is_base_of<U, T>::value;
class Services {
public:
template<ServiceType Svc, Derived<Svc> Impl, typename ...Args>
void bind(Args... args) {
m_services[Svc::service] = std::make_shared<Impl>(args...);
}
template<ServiceType Svc, typename ...Args>
Svc *create(Args... args) {
auto svc = std::make_shared<Svc>(args...);
m_services[Svc::service] = svc;
return svc.get();
}
template<ServiceType Svc>
void provide(std::shared_ptr<Svc> service) {
m_services[Svc::service] = service;
}
template<ServiceType S>
S *get() const {
auto serviceWrapper = m_services.at(S::service);
auto ptr = std::static_pointer_cast<S>(serviceWrapper);
return ptr.get();
}
private:
std::map<ServiceName, std::shared_ptr<void>> m_services;
};
} // namespace fggl::modules
#endif //FGGL_MODULES_SERVICE_HPP
/*
* ${license.title}
* Copyright (C) 2022 ${license.owner}
* ${license.mailto}
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
//
// Created by webpigeon on 24/04/22.
//
#ifndef FGGL_PHYS_BULLET_BULLET_HPP
#define FGGL_PHYS_BULLET_BULLET_HPP
#include "fggl/ecs3/module/module.h"
#include "fggl/phys/types.hpp"
#include "fggl/phys/bullet/types.hpp"
namespace fggl::phys::bullet {
/**
* Bullet integration module.
*
* This provides the ability for FGGL to use bullet as a physics backened. Bullet is mature, stable physics
* engine which makes it suitable for most use cases. For use with FGGL there is a reasonable amount of copying
* back and forth to keep the two states in sync.
*/
struct BulletModule : ecs3::Module {
public:
BulletModule() = default;
[[nodiscard]]
std::string name() const override {
return "phys::Bullet3";
}
void onLoad(ecs3::ModuleManager & /*manager*/, ecs3::TypeRegistry &types) override {
// dependencies
types.make<phys::CollisionCallbacks>();
types.make<phys::CollisionCache>();
types.make<phys::RigidBody>();
types.make<phys::Dynamics>();
// my types
types.make<phys::bullet::BulletBody>();
}
};
} // namespace fggl::phys::bullet
namespace fggl::phys {
// allows using fggl::phys::Bullet3 as the module name
using Bullet3 = bullet::BulletModule;
} // namespace fggl::phys
#endif //FGGL_PHYS_BULLET_BULLET_HPP
/*
* ${license.title}
* Copyright (C) 2022 ${license.owner}
* ${license.mailto}
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
//
// Created by webpigeon on 11/06/22.
//
#ifndef FGGL_PHYS_BULLET_MOTION_HPP
#define FGGL_PHYS_BULLET_MOTION_HPP
#include "fggl/phys/bullet/types.hpp"
namespace fggl::phys::bullet {
class FgglMotionState : public btMotionState {
public:
FgglMotionState(fggl::ecs3::World* world, fggl::ecs3::entity_t entity) : m_world(world), m_entity(entity) {
}
virtual ~FgglMotionState() = default;
void getWorldTransform(btTransform& worldTrans) const override {
const auto* transform = m_world->get<fggl::math::Transform>(m_entity);
worldTrans.setFromOpenGLMatrix( glm::value_ptr(transform->model()) );
}
void setWorldTransform(const btTransform& worldTrans) override {
auto* transform = m_world->get<fggl::math::Transform>(m_entity);
// set position
auto btOrigin = worldTrans.getOrigin();
transform->origin( {btOrigin.x(), btOrigin.y(), btOrigin.z()} );
// set rotation
math::vec3 angles;
worldTrans.getRotation().getEulerZYX(angles.x, angles.y, angles.z);
transform->euler(angles);
}
private:
fggl::ecs3::World* m_world;
fggl::ecs3::entity_t m_entity;
};
} // namespace fggl::phys::bullet
#endif //FGGL_PHYS_BULLET_INTEGRATIONS_HPP
/*
* ${license.title}
* Copyright (C) 2022 ${license.owner}
* ${license.mailto}
* This file is part of FGGL.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
* FGGL is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
* FGGL is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* You should have received a copy of the GNU Lesser General Public License along with FGGL.
* If not, see <https://www.gnu.org/licenses/>.
*/
//
......@@ -27,22 +21,23 @@
#include <functional>
#include <unordered_set>
#include "fggl/entity/entity.hpp"
namespace fggl::phys {
using CollisionCB = std::function<void(ecs3::entity_t, ecs3::entity_t)>;
using CollisionCB = std::function<void(entity::EntityID, entity::EntityID)>;
struct CollisionCallbacks {
constexpr static const char* name = "phys::Callbacks";
constexpr static const char *name = "phys::Callbacks";
CollisionCB onEnter = nullptr;
CollisionCB onExit = nullptr;
CollisionCB onStay = nullptr;
};
struct CollisionCache {
constexpr static const char* name = "phys::Cache";
std::unordered_set<ecs3::entity_t> collisions;
std::unordered_set<ecs3::entity_t> lastFrame;
constexpr static const char *name = "phys::Cache";
std::unordered_set<entity::EntityID> collisions;
std::unordered_set<entity::EntityID> lastFrame;
};
} // namespace fggl::phys
......
/*
* This file is part of FGGL.
*
* FGGL is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* FGGL is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with FGGL.
* If not, see <https://www.gnu.org/licenses/>.
*/
//
// Created by webpigeon on 20/08/22.
//
#ifndef FGGL_PHYS_NULL_HPP
#define FGGL_PHYS_NULL_HPP
#include "fggl/phys/types.hpp"
#include "fggl/phys/service.hpp"
namespace fggl::phys {
inline void build_noop(const entity::ComponentSpec & /*config*/,
entity::EntityManager &manager,
const entity::EntityID &entity,
modules::Services &/*services*/) {
manager.add<fggl::phys::RigidBody>(entity);
manager.add<fggl::phys::Dynamics>(entity);
}
class NullPhysicsEngine : public PhysicsEngine {
public:
inline void step() override {}
void setDebugDraw(bool /* enable */) override {}
inline std::vector<ContactPoint> scanCollisions(entity::EntityID /*entity*/) override {
return {};
}
inline entity::EntityID raycast(math::vec3 /*from*/, math::vec3 /*to*/) override {
return entity::INVALID;
}
inline std::vector<entity::EntityID> raycastAll(math::vec3 /*from*/, math::vec3 /*to*/) override {
return {};
}
inline std::vector<entity::EntityID> sweep(PhyShape & /*shape*/,
math::Transform & /*from*/,
math::Transform & /*to*/) override {
return {};
}
};
class NullPhysicsProvider : public PhysicsProvider {
public:
virtual ~NullPhysicsProvider() = default;
inline PhysicsEngine *create(entity::EntityManager * /*entityManager*/,
entity::EntityFactory *factory) override {
factory->bind(util::make_guid("phys::Body"), build_noop);
return new NullPhysicsEngine();
}
};
struct NullPhysics {
constexpr static const char *name = "fggl::phys::null";
constexpr static const std::array<modules::ServiceName, 1> provides = {
phys::PhysicsProvider::service
};
constexpr static const std::array<modules::ServiceName, 1> depends = {
entity::EntityFactory::service
};
static bool factory(modules::ServiceName serviceName, modules::Services &serviceManager);
};
} // namespace fggl::phys
#endif //FGGL_PHYS_NULL_HPP
/*
* This file is part of FGGL.
*
* FGGL is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* FGGL is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with FGGL.
* If not, see <https://www.gnu.org/licenses/>.
*/
//
// Created by webpigeon on 01/08/22.
//
#ifndef FGGL_PHYS_SERVICE_HPP
#define FGGL_PHYS_SERVICE_HPP
#include "fggl/modules/module.hpp"
#include "fggl/entity/module.hpp"
#include "fggl/phys/types.hpp"
namespace fggl::phys {
class PhysicsProvider {
public:
constexpr static const auto service = modules::make_service("fggl::phys::service");
virtual ~PhysicsProvider() = default;
virtual PhysicsEngine *create(entity::EntityManager *entityManager, entity::EntityFactory *factory) = 0;
};
}
#endif //FGGL_PHYS_SERVICE_HPP
/*
* ${license.title}
* Copyright (C) 2022 ${license.owner}
* ${license.mailto}
* This file is part of FGGL.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
* FGGL is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
* FGGL is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* You should have received a copy of the GNU Lesser General Public License along with FGGL.
* If not, see <https://www.gnu.org/licenses/>.
*/
//
......@@ -25,6 +19,7 @@
#ifndef FGGL_PHYS_TYPES_HPP
#define FGGL_PHYS_TYPES_HPP
#include "fggl/math/types.hpp"
#include "fggl/phys/callbacks.hpp"
namespace fggl::phys {
......@@ -33,9 +28,9 @@ namespace fggl::phys {
constexpr math::vec3 UNIT_EXTENTS{0.5F, 0.5F, 0.5F};
enum class ShapeType {
UNSET,
BOX,
SPHERE
UNSET,
BOX,
SPHERE
};
struct PhyShape {
......@@ -47,22 +42,24 @@ namespace fggl::phys {
struct Box : public PhyShape {
math::vec3 extents;
explicit inline Box(math::vec3 ext) : PhyShape(ShapeType::BOX), extents(ext) {}
};
struct Sphere : public PhyShape {
float radius = 1.0F;
explicit inline Sphere(float rad) : PhyShape(ShapeType::SPHERE), radius(rad) {}
};
enum class BodyType {
STATIC, KINEMATIC, DYNAMIC
STATIC, KINEMATIC, DYNAMIC
};
struct RigidBody {
constexpr static const char* name = "phys::Body";
constexpr static const char *name = "phys::Body";
float mass = MASS_DEFAULT;
PhyShape* shape = nullptr;
PhyShape *shape = nullptr;
BodyType type = BodyType::DYNAMIC;
[[nodiscard]]
......@@ -72,13 +69,13 @@ namespace fggl::phys {
};
struct Dynamics {
constexpr static const char* name = "phys::Dynamics";
constexpr static const char *name = "phys::Dynamics";
math::vec3 force = math::VEC3_ZERO;
};
struct ContactPoint {
ecs3::entity_t entityA;
ecs3::entity_t entityB;
entity::EntityID entityA;
entity::EntityID entityB;
math::vec3 localA;
math::vec3 localB;
math::vec3 normal;
......@@ -103,19 +100,30 @@ namespace fggl::phys {
virtual ~PhysicsEngine() = default;
// no copy and no move
PhysicsEngine(PhysicsEngine&) = delete;
PhysicsEngine(PhysicsEngine&&) = delete;
PhysicsEngine& operator=(PhysicsEngine&) = delete;
PhysicsEngine& operator=(PhysicsEngine&&) = delete;
PhysicsEngine(PhysicsEngine &) = delete;
PhysicsEngine(PhysicsEngine &&) = delete;
PhysicsEngine &operator=(PhysicsEngine &) = delete;
PhysicsEngine &operator=(PhysicsEngine &&) = delete;
// query methods (first cut - unstable APIs)
virtual std::vector<ContactPoint> scanCollisions(ecs3::entity_t entity) = 0;
virtual ecs3::entity_t raycast(math::vec3 from, math::vec3 to) = 0;
virtual std::vector<ecs3::entity_t> raycastAll(math::vec3 from, math::vec3 to) = 0;
virtual std::vector<ecs3::entity_t> sweep(PhyShape& shape, math::Transform& from, math::Transform& to) = 0;
virtual std::vector<ContactPoint> scanCollisions(entity::EntityID entity) = 0;
virtual entity::EntityID raycast(math::vec3 from, math::vec3 to) = 0;
inline entity::EntityID raycast(math::Ray ray, float maxDist = 1000.0F) {
return raycast(ray.origin, ray.origin + ray.direction * maxDist);
}
virtual std::vector<entity::EntityID> raycastAll(math::vec3 from, math::vec3 to) = 0;
virtual std::vector<entity::EntityID> sweep(PhyShape &shape,
math::Transform &from,
math::Transform &to) = 0;
// update
virtual void step() = 0;
// debug
virtual void setDebugDraw(bool enable) = 0;
};
} // namespace fggl::phys
......
/*
* This file is part of FGGL.
*
* FGGL is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* FGGL is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with FGGL.
* If not, see <https://www.gnu.org/licenses/>.
*/
//
// Created by webpigeon on 19/09/22.
//
#ifndef FGGL_PLATFORM_FALLBACK_FILE_HPP
#define FGGL_PLATFORM_FALLBACK_FILE_HPP
#include <cstdio>
#include <cassert>
namespace fggl::platform {
class File {
public:
inline File(FILE* filePtr) : m_handle(filePtr) {
assert(filePtr != nullptr);
}
inline ~File() {
release();
}
template<typename T>
inline void write(const T* dataPtr) {
assert( m_handle != nullptr );
int status = fwrite(dataPtr, sizeof(T), 1, m_handle );
assert( status == 1);
}
template<typename T>
inline void writeArr(const T* dataPtr, std::size_t numElms) {
assert( m_handle != nullptr);
int status = fwrite(dataPtr, sizeof(T), numElms, m_handle );
assert( status == 1);
}
private:
std::FILE* m_handle;
inline void release() {
if ( m_handle != NULL) {
fclose(m_handle);
}
}
};
} // namespace fggl::platform
#endif //FGGL_PLATFORM_FALLBACK_FILE_HPP
/*
* This file is part of FGGL.
*
* FGGL is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* FGGL is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with FGGL.
* If not, see <https://www.gnu.org/licenses/>.
*/
//
// Low-Level Linux-specific path management
// Created by webpigeon on 23/06/22.
// see https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html
//
#ifndef FGGL_PLATFORM_FALLBACK_PATHS_HPP
#define FGGL_PLATFORM_FALLBACK_PATHS_HPP
#include "fggl/platform/paths.hpp"
#include <filesystem>
#include <array>
#include <vector>
namespace fggl::platform {
/**
* The environment variable used for containing user configurations.
*
* The directory mentioned by this environment variable should be read/writeable.
* The directory should be used for storing user-editable configuration options (eg. preferences).
*/
constexpr const char *ENV_USER_CONFIG = "FGGL_CONFIG_HOME";
/**
* Fallback user configuration directory.
*
* Default user configuration directory if none is set by the environment variable.
*/
constexpr const char *DEFAULT_USER_CONFIG = "user_config";
/**
* The environment variable used for containing engine data.
*
* This directory is used for storing persistent user data and therefore should be read/writable.
* The directory should be used for storing user-modifiable state (eg, save files) or downloaded modifications.
*/
constexpr const char *ENV_USER_DATA = "FGGL_DATA_HOME";
/**
* Fallback user data directory.
*
* Default user data directory if none is set by the environment variable.
*/
constexpr const char *DEFAULT_USER_DATA = "user_data";
/**
* The environment variable used for containing semi-persistent user data.
*
* The application should be able to expect this directory to exist while the application is running, but otherwise
* cannot expect the data to be persistent. It MAY be persistent but the application should not rely on this.
* It should be used for resources which can be re-generated if needed, but can be useful if already present.
*/
constexpr const char *ENV_USER_CACHE = "FGGL_CACHE_HOME";
struct EnginePaths {
std::filesystem::path userConfig;
std::filesystem::path userData;
std::filesystem::path userCache;
};
/**
* Fallback implementation of calc engine paths.
*
* For operating systems we don't know about, this simply uses the environment variables defined above and some
* sane defaults to construct the paths used to locate our data and user configuration.
*
* @param base an application-unique string used to construct the paths.
* @return the generated paths, for use with the rest of the engine.
*/
EnginePaths calc_engine_paths(const char *base);
// search routines for finding data and configuration files
std::filesystem::path locate_data(const EnginePaths &paths, const std::filesystem::path &relPath);
std::filesystem::path locate_config(const EnginePaths &paths, const std::filesystem::path &relPath);
std::filesystem::path locate_cache(const EnginePaths &paths, const std::filesystem::path &relPath);
}
#endif //FGGL_PLATFORM_FALLBACK_PATHS_HPP
/*
* This file is part of FGGL.
*
* FGGL is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* FGGL is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with FGGL.
* If not, see <https://www.gnu.org/licenses/>.
*/
//
// Low-Level Linux-specific path management
// Created by webpigeon on 23/06/22.
// see https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html
//
#ifndef FGGL_PLATFORM_LINUX_PATHS_HPP
#define FGGL_PLATFORM_LINUX_PATHS_HPP
#include "fggl/platform/paths.hpp"
#include <filesystem>
#include <array>
#include <vector>
namespace fggl::platform {
constexpr const char *ENV_USER_CONFIG = "XDG_CONFIG_HOME";
constexpr const char *ENV_USER_DATA = "XDG_DATA_HOME";
constexpr const char *ENV_USER_CACHE = "XDG_CACHE_HOME";
constexpr const char *ENV_DATA_DIRS = "XDG_DATA_DIRS";
constexpr const char *ENV_CONFIG_DIRS = "XDG_CONFIG_DIRS";
// fallback user paths defined in the XDG spec
constexpr const char *DEFAULT_USER_CONFIG = "~/.config";
constexpr const char *DEFAULT_USER_DATA = "~/.local/share";
constexpr const char *DEFAULT_USER_CACHE = "~/.cache";
// fallback search paths defined in the XDG spec
constexpr const std::array<const char *, 2> DEFAULT_DATA_DIRS = {"/usr/local/share/", "/usr/share/"};
constexpr const std::array<const char *, 1> DEFAULT_CONFIG_DIRS = {"/etc/xdg"};
struct EnginePaths {
std::filesystem::path userConfig;
std::filesystem::path userData;
std::filesystem::path userCache;
std::vector<std::filesystem::path> dataDirs;
std::vector<std::filesystem::path> configDirs;
};
EnginePaths calc_engine_paths(const char *base);
// search routines for finding data and configuration files
std::filesystem::path locate_data(const EnginePaths &paths, const std::filesystem::path &relPath);
std::filesystem::path locate_config(const EnginePaths &paths, const std::filesystem::path &relPath);
std::filesystem::path locate_cache(const EnginePaths &paths, const std::filesystem::path &relPath);
}
#endif //FGGL_PLATFORM_LINUX_PATHS_HPP
/*
* This file is part of FGGL.
*
* FGGL is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* FGGL is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with FGGL.
* If not, see <https://www.gnu.org/licenses/>.
*/
//
// Created by webpigeon on 26/06/22.
//
#ifndef FGGL_PLATFORM_PATHS_HPP
#define FGGL_PLATFORM_PATHS_HPP
#include <filesystem>
#include <vector>
#ifdef __linux__
#define FGGL_PLATFORM_PATHS linux
#include "fggl/platform/linux/paths.hpp"
#else
#define FGGL_PLATFORM_PATHS fallback
#include "fggl/platform/fallback/paths.hpp"
#endif
#endif //FGGL_PLATFORM_PATHS_HPP