Browse Source

Improve ant trait definitions, trait loaders, and morphogenesis.

master
C. J. Howard 2 years ago
parent
commit
a7e5aca4a0
68 changed files with 1676 additions and 1682 deletions
  1. +0
    -1
      CMakeLists.txt
  2. +1
    -1
      src/application.cpp
  3. +1
    -1
      src/color/xyy.hpp
  4. +1
    -1
      src/color/xyz.hpp
  5. +0
    -82
      src/game/ant/breed.hpp
  6. +20
    -6
      src/game/ant/caste-type.hpp
  7. +63
    -6
      src/game/ant/caste.hpp
  8. +444
    -508
      src/game/ant/morphogenesis.cpp
  9. +3
    -4
      src/game/ant/morphogenesis.hpp
  10. +78
    -0
      src/game/ant/species.hpp
  11. +12
    -12
      src/game/ant/subcaste-type.hpp
  12. +10
    -4
      src/game/ant/trait/antennae.hpp
  13. +7
    -9
      src/game/ant/trait/body-size.hpp
  14. +4
    -4
      src/game/ant/trait/cocoon.hpp
  15. +1
    -1
      src/game/ant/trait/diet.hpp
  16. +1
    -1
      src/game/ant/trait/egg.hpp
  17. +15
    -7
      src/game/ant/trait/eyes.hpp
  18. +1
    -1
      src/game/ant/trait/foraging-time.hpp
  19. +0
    -51
      src/game/ant/trait/forewings.hpp
  20. +48
    -0
      src/game/ant/trait/founding-mode.hpp
  21. +6
    -1
      src/game/ant/trait/gaster.hpp
  22. +11
    -8
      src/game/ant/trait/head.hpp
  23. +4
    -4
      src/game/ant/trait/larva.hpp
  24. +9
    -4
      src/game/ant/trait/legs.hpp
  25. +11
    -5
      src/game/ant/trait/loader/antennae-loader.cpp
  26. +12
    -19
      src/game/ant/trait/loader/body-size-loader.cpp
  27. +3
    -6
      src/game/ant/trait/loader/cocoon-loader.cpp
  28. +2
    -1
      src/game/ant/trait/loader/egg-loader.cpp
  29. +32
    -25
      src/game/ant/trait/loader/eyes-loader.cpp
  30. +7
    -1
      src/game/ant/trait/loader/gaster-loader.cpp
  31. +15
    -14
      src/game/ant/trait/loader/head-loader.cpp
  32. +7
    -6
      src/game/ant/trait/loader/larva-loader.cpp
  33. +12
    -6
      src/game/ant/trait/loader/legs-loader.cpp
  34. +16
    -10
      src/game/ant/trait/loader/mandibles-loader.cpp
  35. +19
    -13
      src/game/ant/trait/loader/mesosoma-loader.cpp
  36. +24
    -30
      src/game/ant/trait/loader/ocelli-loader.cpp
  37. +2
    -1
      src/game/ant/trait/loader/pigmentation-loader.cpp
  38. +2
    -2
      src/game/ant/trait/loader/pilosity-loader.cpp
  39. +5
    -8
      src/game/ant/trait/loader/sting-loader.cpp
  40. +43
    -42
      src/game/ant/trait/loader/waist-loader.cpp
  41. +99
    -0
      src/game/ant/trait/loader/wings-loader.cpp
  42. +13
    -6
      src/game/ant/trait/mandibles.hpp
  43. +14
    -9
      src/game/ant/trait/mesosoma.hpp
  44. +3
    -1
      src/game/ant/trait/nest-site.hpp
  45. +9
    -9
      src/game/ant/trait/ocelli.hpp
  46. +1
    -1
      src/game/ant/trait/pigmentation.hpp
  47. +1
    -1
      src/game/ant/trait/pilosity.hpp
  48. +1
    -1
      src/game/ant/trait/sculpturing.hpp
  49. +13
    -7
      src/game/ant/trait/size-variation.hpp
  50. +19
    -11
      src/game/ant/trait/waist.hpp
  51. +28
    -13
      src/game/ant/trait/wings.hpp
  52. +32
    -81
      src/game/load.cpp
  53. +1
    -1
      src/game/state/boot.cpp
  54. +1
    -0
      src/game/state/gamepad-config-menu.hpp
  55. +53
    -82
      src/game/state/nest-selection.cpp
  56. +0
    -80
      src/game/state/nuptial-flight.cpp
  57. +0
    -1
      src/game/state/splash.cpp
  58. +34
    -96
      src/game/system/terrain.cpp
  59. +4
    -4
      src/game/system/terrain.hpp
  60. +9
    -9
      src/geom/hyperoctree.hpp
  61. +17
    -14
      src/geom/mesh.cpp
  62. +89
    -73
      src/geom/mesh.hpp
  63. +5
    -5
      src/geom/primitive/intersection.hpp
  64. +83
    -77
      src/math/matrix.hpp
  65. +48
    -48
      src/math/quaternion.hpp
  66. +137
    -137
      src/math/vector.hpp
  67. +1
    -0
      src/render/renderer.cpp
  68. +9
    -9
      src/resources/image.hpp

+ 0
- 1
CMakeLists.txt View File

@ -1,6 +1,5 @@
cmake_minimum_required(VERSION 3.7) cmake_minimum_required(VERSION 3.7)
option(VERSION_STRING "Project version string" "0.0.0") option(VERSION_STRING "Project version string" "0.0.0")
project(antkeeper VERSION ${VERSION_STRING} LANGUAGES CXX) project(antkeeper VERSION ${VERSION_STRING} LANGUAGES CXX)

+ 1
- 1
src/application.cpp View File

@ -297,7 +297,7 @@ void application::set_v_sync(bool v_sync)
logger->pop_task(EXIT_FAILURE); logger->pop_task(EXIT_FAILURE);
logger->push_task("Enabling synchronized v-sync"); logger->push_task("Enabling synchronized v-sync");
if (SDL_GL_SetSwapInterval(-1) != 0)
if (SDL_GL_SetSwapInterval(1) != 0)
{ {
logger->pop_task(EXIT_FAILURE); logger->pop_task(EXIT_FAILURE);
} }

+ 1
- 1
src/color/xyy.hpp View File

@ -34,7 +34,7 @@ namespace xyy {
* @return return Luminance of @p x. * @return return Luminance of @p x.
*/ */
template <class T> template <class T>
constexpr inline T luminance(const math::vector3<T>& x)
inline constexpr T luminance(const math::vector3<T>& x)
{ {
return x[2]; return x[2];
} }

+ 1
- 1
src/color/xyz.hpp View File

@ -38,7 +38,7 @@ namespace xyz {
* @return return Luminance of @p x. * @return return Luminance of @p x.
*/ */
template <class T> template <class T>
constexpr inline T luminance(const math::vector3<T>& x)
inline constexpr T luminance(const math::vector3<T>& x)
{ {
return x[1]; return x[1];
} }

+ 0
- 82
src/game/ant/breed.hpp View File

@ -1,82 +0,0 @@
/*
* Copyright (C) 2021 Christopher J. Howard
*
* This file is part of Antkeeper source code.
*
* Antkeeper source code is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Antkeeper source code 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef ANTKEEPER_GAME_ANT_BREED_HPP
#define ANTKEEPER_GAME_ANT_BREED_HPP
#include "game/ant/trait/antennae.hpp"
#include "game/ant/trait/cocoon.hpp"
#include "game/ant/trait/diet.hpp"
#include "game/ant/trait/egg.hpp"
#include "game/ant/trait/eyes.hpp"
#include "game/ant/trait/foraging-time.hpp"
#include "game/ant/trait/forewings.hpp"
#include "game/ant/trait/gaster.hpp"
#include "game/ant/trait/head.hpp"
#include "game/ant/trait/hindwings.hpp"
#include "game/ant/trait/larva.hpp"
#include "game/ant/trait/legs.hpp"
#include "game/ant/trait/mandibles.hpp"
#include "game/ant/trait/mesosoma.hpp"
#include "game/ant/trait/nest.hpp"
#include "game/ant/trait/ocelli.hpp"
#include "game/ant/trait/pigmentation.hpp"
#include "game/ant/trait/pilosity.hpp"
#include "game/ant/trait/sculpturing.hpp"
#include "game/ant/trait/sting.hpp"
#include "game/ant/trait/waist.hpp"
namespace game {
namespace ant {
/**
* Set of all traits that describes an ant breed.
*/
struct breed
{
// Morphological traits
trait::antennae* antennae;
trait::eyes* eyes;
trait::forewings* forewings;
trait::gaster* gaster;
trait::waist* waist;
trait::head* head;
trait::hindwings* hindwings;
trait::legs* legs;
trait::mandibles* mandibles;
trait::mesosoma* mesosoma;
trait::ocelli* ocelli;
trait::sting* sting;
trait::sculpturing* sculpturing;
trait::pigmentation* pigmentation;
trait::pilosity* pilosity;
trait::egg* egg;
trait::larva* larva;
trait::cocoon* cocoon;
// Behavioral traits
trait::diet* diet;
trait::foraging_time* foraging_time;
trait::nest* nest;
};
} // namespace ant
} // namespace game
#endif // ANTKEEPER_GAME_ANT_BREED_HPP

src/game/ant/founding-mode.hpp → src/game/ant/caste-type.hpp View File

@ -17,19 +17,33 @@
* along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>. * along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef ANTKEEPER_GAME_ANT_FOUNDING_MODE_HPP
#define ANTKEEPER_GAME_ANT_FOUNDING_MODE_HPP
#ifndef ANTKEEPER_GAME_ANT_CASTE_TYPE_HPP
#define ANTKEEPER_GAME_ANT_CASTE_TYPE_HPP
namespace game { namespace game {
namespace ant { namespace ant {
enum class founding_mode
/**
* Ant caste type enumerations
*
* @see https://www.antwiki.org/wiki/Caste_Terminology
*/
enum class caste_type
{ {
semi_claustral,
claustral
/// Queen caste type.
queen,
/// Worker caste type.
worker,
/// Soldier caste type.
soldier,
/// Male caste type.
male
}; };
} // namespace ant } // namespace ant
} // namespace game } // namespace game
#endif // ANTKEEPER_GAME_ANT_FOUNDING_MODE_HPP
#endif // ANTKEEPER_GAME_ANT_CASTE_TYPE_HPP

+ 63
- 6
src/game/ant/caste.hpp View File

@ -20,18 +20,75 @@
#ifndef ANTKEEPER_GAME_ANT_CASTE_HPP #ifndef ANTKEEPER_GAME_ANT_CASTE_HPP
#define ANTKEEPER_GAME_ANT_CASTE_HPP #define ANTKEEPER_GAME_ANT_CASTE_HPP
#include "game/ant/caste-type.hpp"
#include "game/ant/trait/antennae.hpp"
#include "game/ant/trait/eyes.hpp"
#include "game/ant/trait/gaster.hpp"
#include "game/ant/trait/head.hpp"
#include "game/ant/trait/legs.hpp"
#include "game/ant/trait/mandibles.hpp"
#include "game/ant/trait/mesosoma.hpp"
#include "game/ant/trait/ocelli.hpp"
#include "game/ant/trait/pigmentation.hpp"
#include "game/ant/trait/sculpturing.hpp"
#include "game/ant/trait/size-variation.hpp"
#include "game/ant/trait/sting.hpp"
#include "game/ant/trait/waist.hpp"
#include "game/ant/trait/wings.hpp"
#include <optional>
namespace game { namespace game {
namespace ant { namespace ant {
/** /**
* Caste type enumerations
* Ant caste description.
*/ */
enum class caste
struct caste
{ {
queen,
worker,
soldier,
male
/// Caste type.
caste_type type;
/// Antennae description.
const trait::antennae* antennae;
/// Eyes description.
const trait::eyes* eyes;
/// Gaster description.
const trait::gaster* gaster;
/// Head description.
const trait::head* head;
/// Legs description.
const trait::legs* legs;
/// Mandibles description.
const trait::mandibles* mandibles;
/// Mesosoma description.
const trait::mesosoma* mesosoma;
/// Ocelli description.
const trait::ocelli* ocelli;
/// Pigmentation description.
const trait::pigmentation* pigmentation;
/// Sculpturing description.
const trait::sculpturing* sculpturing;
/// Size variation description.
const trait::size_variation* size_variation;
/// Sting description.
const trait::sting* sting;
/// Waist description.
const trait::waist* waist;
/// Wings description.
const trait::wings* wings;
}; };
} // namespace ant } // namespace ant

+ 444
- 508
src/game/ant/morphogenesis.cpp
File diff suppressed because it is too large
View File


+ 3
- 4
src/game/ant/morphogenesis.hpp View File

@ -20,7 +20,6 @@
#ifndef ANTKEEPER_GAME_ANT_MORPHOGENESIS_HPP #ifndef ANTKEEPER_GAME_ANT_MORPHOGENESIS_HPP
#define ANTKEEPER_GAME_ANT_MORPHOGENESIS_HPP #define ANTKEEPER_GAME_ANT_MORPHOGENESIS_HPP
#include "game/ant/breed.hpp"
#include "game/ant/caste.hpp" #include "game/ant/caste.hpp"
#include "render/model.hpp" #include "render/model.hpp"
@ -30,11 +29,11 @@ namespace ant {
/** /**
* Generates a 3D model of an ant. * Generates a 3D model of an ant.
* *
* @param breed Breed of the ant.
* @param caste Caste to which the ant belongs.
* @param caste Caste description.
*
* @return 3D model of an ant. * @return 3D model of an ant.
*/ */
render::model* morphogenesis(const ant::breed& breed, ant::caste caste);
render::model* morphogenesis(const ant::caste& caste);
} // namespace ant } // namespace ant
} // namespace game } // namespace game

+ 78
- 0
src/game/ant/species.hpp View File

@ -0,0 +1,78 @@
/*
* Copyright (C) 2021 Christopher J. Howard
*
* This file is part of Antkeeper source code.
*
* Antkeeper source code is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Antkeeper source code 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef ANTKEEPER_GAME_ANT_SPECIES_HPP
#define ANTKEEPER_GAME_ANT_SPECIES_HPP
#include "game/ant/caste.hpp"
#include "game/ant/trait/body-size.hpp"
#include "game/ant/trait/cocoon.hpp"
#include "game/ant/trait/diet.hpp"
#include "game/ant/trait/egg.hpp"
#include "game/ant/trait/foraging-time.hpp"
#include "game/ant/trait/larva.hpp"
#include "game/ant/trait/nest-site.hpp"
#include <optional>
namespace game {
namespace ant {
/**
* Ant species description.
*/
struct species
{
/// Body size description.
const trait::body_size* body_size;
/// Egg description.
const trait::egg* egg;
/// Larva description.
const trait::larva* larva;
/// Cocoon description.
const trait::cocoon* cocoon;
/// Queen caste description.
std::optional<caste> queen_caste;
/// Worker caste description.
std::optional<caste> worker_caste;
/// Soldier caste description.
std::optional<caste> soldier_caste;
/// Male caste description.
std::optional<caste> male_caste;
/// Diet description.
const trait::diet* diet;
/// Foraging time description.
const trait::foraging_time* foraging_time;
/// Nest site description.
const trait::nest_site* nest_site;
};
} // namespace ant
} // namespace game
#endif // ANTKEEPER_GAME_ANT_SPECIES_HPP

src/game/ant/subcaste.hpp → src/game/ant/subcaste-type.hpp View File

@ -17,43 +17,43 @@
* along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>. * along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef ANTKEEPER_GAME_ANT_SUBCASTE_HPP
#define ANTKEEPER_GAME_ANT_SUBCASTE_HPP
#ifndef ANTKEEPER_GAME_ANT_SUBCASTE_TYPE_HPP
#define ANTKEEPER_GAME_ANT_SUBCASTE_TYPE_HPP
namespace game { namespace game {
namespace ant { namespace ant {
/** /**
* Ant subcaste types.
* Ant subcaste type enumerations.
*/ */
enum class subcaste enum class subcaste
{ {
/// A worker from the queen's first batch of eggs, smaller than normal workers.
/// Worker from the queen's first batch of eggs, smaller than normal workers.
nanitic, nanitic,
/// A small worker or soldier.
/// Small worker or soldier.
minor, minor,
/// A normal-sized worker or soldier
/// Normal-sized worker or soldier
media, media,
/// A large worker or soldier.
/// Large worker or soldier.
major, major,
/// A queen or male which still has its wings.
/// Winged queen or male.
alate, alate,
/// A queen or male which has shed its wings.
/// Dewinged queen or male.
dealate, dealate,
/// A queen or male which does not develop wings.
/// Queen or male which does not develop wings.
ergatoid, ergatoid,
/// A queen or male with short, nonfunctional wings.
/// Queen or male with short, nonfunctional wings.
brachypterous brachypterous
}; };
} // namespace ant } // namespace ant
} // namespace game } // namespace game
#endif // ANTKEEPER_GAME_ANT_SUBCASTE_HPP
#endif // ANTKEEPER_GAME_ANT_SUBCASTE_TYPE_HPP

+ 10
- 4
src/game/ant/trait/antennae.hpp View File

@ -27,15 +27,21 @@ namespace ant {
namespace trait { namespace trait {
/** /**
* Trait that describes the antennae of an ant.
* Ant antennae description.
*
* @see https://www.antwiki.org/wiki/Character_States_for_Extant_Ant_Genera_of_the_Formicidae
* @see https://www.antwiki.org/wiki/Morphological_Measurements
*/ */
struct antennae struct antennae
{ {
/// Scape length (SL), measured in mesosomal lengths.
float scape_length;
/// 3D model of the antennae. /// 3D model of the antennae.
render::model* model; render::model* model;
/// Total number of antennal segments.
int total_antennomere_count;
/// Number of antennal segments that constitute a club.
int club_antennomere_count;
}; };
} // namespace trait } // namespace trait

src/game/ant/trait/nest.hpp → src/game/ant/trait/body-size.hpp View File

@ -17,26 +17,24 @@
* along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>. * along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef ANTKEEPER_GAME_ANT_TRAIT_NEST_HPP
#define ANTKEEPER_GAME_ANT_TRAIT_NEST_HPP
#include "game/ant/nest-site.hpp"
#ifndef ANTKEEPER_GAME_ANT_TRAIT_BODY_SIZE_HPP
#define ANTKEEPER_GAME_ANT_TRAIT_BODY_SIZE_HPP
namespace game { namespace game {
namespace ant { namespace ant {
namespace trait { namespace trait {
/** /**
* Trait that describes the nest site of an ant.
* Ant body size description.
*/ */
struct nest
struct body_size
{ {
/// Site of the nest.
game::ant::nest_site site;
/// Mesosoma length (Weber's length) of a media worker, in centimeters.
float mesosoma_length;
}; };
} // namespace trait } // namespace trait
} // namespace ant } // namespace ant
} // namespace game } // namespace game
#endif // ANTKEEPER_GAME_ANT_TRAIT_NEST_HPP
#endif // ANTKEEPER_GAME_ANT_TRAIT_BODY_SIZE_HPP

+ 4
- 4
src/game/ant/trait/cocoon.hpp View File

@ -27,15 +27,15 @@ namespace ant {
namespace trait { namespace trait {
/** /**
* Trait that describes the cocoon of an ant species.
* Ant cocoon description.
*/ */
struct cocoon struct cocoon
{ {
/// Indicates whether a cocoon is formed by the larvae or not.
bool present;
/// 3D model of the cocoon, if present. /// 3D model of the cocoon, if present.
render::model* model; render::model* model;
/// Indicates whether a cocoon is formed by the larvae or not.
bool present;
}; };
} // namespace trait } // namespace trait

+ 1
- 1
src/game/ant/trait/diet.hpp View File

@ -25,7 +25,7 @@ namespace ant {
namespace trait { namespace trait {
/** /**
* Trait that describes the diet of an ant.
* Ant diet description.
*/ */
struct diet struct diet
{ {

+ 1
- 1
src/game/ant/trait/egg.hpp View File

@ -27,7 +27,7 @@ namespace ant {
namespace trait { namespace trait {
/** /**
* Trait that describes the eggs of an ant species.
* Ant egg description.
*/ */
struct egg struct egg
{ {

+ 15
- 7
src/game/ant/trait/eyes.hpp View File

@ -27,21 +27,29 @@ namespace ant {
namespace trait { namespace trait {
/** /**
* Trait that describes the eyes of an ant.
* Ant eyes description.
*
* @see https://www.antwiki.org/wiki/Morphological_Measurements
*/ */
struct eyes struct eyes
{ {
/// Eye length (EL), measured in mesosomal lengths.
/// 3D model of the eyes, if present.
render::model* model;
/// Indicates whether eyes are present.
bool present;
/// Eye length, in mesosomal lengths.
float length; float length;
/// Eye width (EW), measured in mesosomal lengths.
/// Eye width, in mesosomal lengths.
float width; float width;
/// Number of ommatidia.
int ommatidia;
/// Eye height, in mesosomal lengths.
float height;
/// 3D model of the eyes.
render::model* model;
/// Number of ommatidia.
int ommatidia_count;
}; };
} // namespace trait } // namespace trait

+ 1
- 1
src/game/ant/trait/foraging-time.hpp View File

@ -27,7 +27,7 @@ namespace ant {
namespace trait { namespace trait {
/** /**
* Trait that describes the surface foraging time of an ant.
* Ant foraging time description.
*/ */
struct foraging_time struct foraging_time
{ {

+ 0
- 51
src/game/ant/trait/forewings.hpp View File

@ -1,51 +0,0 @@
/*
* Copyright (C) 2021 Christopher J. Howard
*
* This file is part of Antkeeper source code.
*
* Antkeeper source code is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Antkeeper source code 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef ANTKEEPER_GAME_ANT_TRAIT_FOREWINGS_HPP
#define ANTKEEPER_GAME_ANT_TRAIT_FOREWINGS_HPP
#include "render/model.hpp"
namespace game {
namespace ant {
namespace trait {
/**
* Trait that describes the forewings of an ant.
*/
struct forewings
{
/// Wing length, measured in mesosomal lengths.
float length;
/// Wing width, measured in mesosomal lengths.
float width;
/// Degree of venation. A value of `1.0` indicates a highly-developed venation pattern, while `0.0` indicates a complete absence of visible venation.
float venation;
/// 3D model of the forewings.
render::model* model;
};
} // namespace trait
} // namespace ant
} // namespace game
#endif // ANTKEEPER_GAME_ANT_TRAIT_FOREWINGS_HPP

+ 48
- 0
src/game/ant/trait/founding-mode.hpp View File

@ -0,0 +1,48 @@
/*
* Copyright (C) 2021 Christopher J. Howard
*
* This file is part of Antkeeper source code.
*
* Antkeeper source code is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Antkeeper source code 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef ANTKEEPER_GAME_ANT_TRAIT_FOUNDING_MODE_HPP
#define ANTKEEPER_GAME_ANT_TRAIT_FOUNDING_MODE_HPP
namespace game {
namespace ant {
namespace trait {
/**
* Colony founding mode.
*
* @see https://www.antwiki.org/wiki/Colony_Foundation
*/
enum class founding_mode
{
/// Foraging outside the claustral chamber is required.
semi_claustral,
/// Foraging outside the claustral chamber is unnecessary.
claustral,
/// Parent colony splits, with a queen taking a portion of the workforce with her.
fission
};
} // namespace trait
} // namespace ant
} // namespace game
#endif // ANTKEEPER_GAME_ANT_TRAIT_FOUNDING_MODE_HPP

+ 6
- 1
src/game/ant/trait/gaster.hpp View File

@ -27,12 +27,17 @@ namespace ant {
namespace trait { namespace trait {
/** /**
* Trait that describes the gaster of an ant.
* Ant gaster description.
*
* @see https://antwiki.org/wiki/Phragmosis
*/ */
struct gaster struct gaster
{ {
/// 3D model of the gaster. /// 3D model of the gaster.
render::model* model; render::model* model;
/// Degree of phragmosis.
float phragmosis;
}; };
} // namespace trait } // namespace trait

+ 11
- 8
src/game/ant/trait/head.hpp View File

@ -27,21 +27,24 @@ namespace ant {
namespace trait { namespace trait {
/** /**
* Trait that describes the head of an ant.
* Ant head description.
*
* @see https://www.antwiki.org/wiki/Morphological_Measurements
* @see https://antwiki.org/wiki/Phragmosis
*/ */
struct head struct head
{ {
/// Head length in full face view (HL), measured in mesosomal lengths.
/// 3D model of the head.
render::model* model;
/// Head length, in mesosomal lengths.
float length; float length;
/// Head width in full face view (HW), measured in mesosomal lengths.
/// Head width, in mesosomal lengths.
float width; float width;
/// Indicates whether the head can be used to plug nest entrances.
bool phragmotic;
/// 3D model of the head.
render::model* model;
/// Degree of phragmosis.
float phragmosis;
}; };
} // namespace trait } // namespace trait

+ 4
- 4
src/game/ant/trait/larva.hpp View File

@ -27,15 +27,15 @@ namespace ant {
namespace trait { namespace trait {
/** /**
* Trait that describes the larvae of an ant species.
* Ant larva description.
*/ */
struct larva struct larva
{ {
/// Number of larval instars before pupation.
int instars;
/// 3D model of the larva. /// 3D model of the larva.
render::model* model; render::model* model;
/// Number of larval instars before pupation.
int instars;
}; };
} // namespace trait } // namespace trait

+ 9
- 4
src/game/ant/trait/legs.hpp View File

@ -27,15 +27,20 @@ namespace ant {
namespace trait { namespace trait {
/** /**
* Trait that describes the legs of an ant.
* Ant legs description.
*
* @see https://www.antwiki.org/wiki/Morphological_Measurements
*/ */
struct legs struct legs
{ {
/// Running speed, measured in mesosomal lengths per second (ML/s).
float speed;
/// 3D model of the legs. /// 3D model of the legs.
render::model* model; render::model* model;
/// Running speed, in mesosomal lengths per second.
float speed;
/// Grip factor.
float grip;
}; };
} // namespace trait } // namespace trait

+ 11
- 5
src/game/ant/trait/loader/antennae-loader.cpp View File

@ -37,8 +37,11 @@ trait::antennae* resource_loader::load(resource_manager* resour
if (antennae_element == data->end()) if (antennae_element == data->end())
throw std::runtime_error("Invalid antennae trait."); throw std::runtime_error("Invalid antennae trait.");
// Allocate antennae trait
// Allocate and init antennae trait
trait::antennae* antennae = new trait::antennae(); trait::antennae* antennae = new trait::antennae();
antennae->model = nullptr;
antennae->total_antennomere_count = 0;
antennae->club_antennomere_count = 0;
// Load antennae model // Load antennae model
auto model_element = antennae_element->find("model"); auto model_element = antennae_element->find("model");
@ -46,10 +49,13 @@ trait::antennae* resource_loader::load(resource_manager* resour
throw std::runtime_error("Antennae trait doesn't specify antennae model."); throw std::runtime_error("Antennae trait doesn't specify antennae model.");
antennae->model = resource_manager->load<render::model>(model_element->get<std::string>()); antennae->model = resource_manager->load<render::model>(model_element->get<std::string>());
// Parse antennae scape length
antennae->scape_length = 0.0f;
if (auto scape_length_element = antennae_element->find("scape_length"); scape_length_element != antennae_element->end())
antennae->scape_length = scape_length_element->get<float>();
// Parse total antennomere count
if (auto element = antennae_element->find("total_antennomere_count"); element != antennae_element->end())
antennae->total_antennomere_count = element->get<int>();
// Parse club antennomere count
if (auto element = antennae_element->find("club_antennomere_count"); element != antennae_element->end())
antennae->club_antennomere_count = element->get<int>();
// Free JSON data // Free JSON data
delete data; delete data;

src/game/ant/trait/loader/nest-loader.cpp → src/game/ant/trait/loader/body-size-loader.cpp View File

@ -20,39 +20,32 @@
#include "resources/resource-loader.hpp" #include "resources/resource-loader.hpp"
#include "resources/resource-manager.hpp" #include "resources/resource-manager.hpp"
#include "resources/json.hpp" #include "resources/json.hpp"
#include "game/ant/trait/nest.hpp"
#include "game/ant/nest-site.hpp"
#include "game/ant/trait/body-size.hpp"
#include <stdexcept> #include <stdexcept>
using namespace game::ant; using namespace game::ant;
template <> template <>
trait::nest* resource_loader<trait::nest>::load(resource_manager* resource_manager, PHYSFS_File* file, const std::filesystem::path& path)
trait::body_size* resource_loader<trait::body_size>::load(resource_manager* resource_manager, PHYSFS_File* file, const std::filesystem::path& path)
{ {
// Load JSON data // Load JSON data
json* data = resource_loader<json>::load(resource_manager, file, path); json* data = resource_loader<json>::load(resource_manager, file, path);
// Validate trait file // Validate trait file
auto nest_element = data->find("nest");
if (nest_element == data->end())
throw std::runtime_error("Invalid nest trait.");
auto body_size_element = data->find("body_size");
if (body_size_element == data->end())
throw std::runtime_error("Invalid body size trait.");
// Allocate nest trait
trait::nest* nest = new trait::nest();
// Allocate and init body size trait
trait::body_size* body_size = new trait::body_size();
body_size->mesosoma_length = 1.0f;
// Parse nest site
nest->site = nest_site::hypogeic;
if (auto site_element = nest_element->find("site"); site_element != nest_element->end())
{
std::string site = site_element->get<std::string>();
if (site == "hypogeic")
nest->site = nest_site::hypogeic;
else if (site == "arboreal")
nest->site = nest_site::arboreal;
}
// Parse mesosoma length
if (auto element = body_size_element->find("mesosoma_length"); element != body_size_element->end())
body_size->mesosoma_length = element->get<float>();
// Free JSON data // Free JSON data
delete data; delete data;
return nest;
return body_size;
} }

+ 3
- 6
src/game/ant/trait/loader/cocoon-loader.cpp View File

@ -37,11 +37,12 @@ trait::cocoon* resource_loader::load(resource_manager* resource_m
if (cocoon_element == data->end()) if (cocoon_element == data->end())
throw std::runtime_error("Invalid cocoon trait."); throw std::runtime_error("Invalid cocoon trait.");
// Allocate cocoon trait
// Allocate and init cocoon trait
trait::cocoon* cocoon = new trait::cocoon(); trait::cocoon* cocoon = new trait::cocoon();
cocoon->present = false;
cocoon->model = nullptr;
// Parse cocoon present // Parse cocoon present
cocoon->present = false;
if (auto present_element = cocoon_element->find("present"); present_element != cocoon_element->end()) if (auto present_element = cocoon_element->find("present"); present_element != cocoon_element->end())
cocoon->present = present_element->get<bool>(); cocoon->present = present_element->get<bool>();
@ -53,10 +54,6 @@ trait::cocoon* resource_loader::load(resource_manager* resource_m
throw std::runtime_error("Cocoon trait doesn't specify cocoon model."); throw std::runtime_error("Cocoon trait doesn't specify cocoon model.");
cocoon->model = resource_manager->load<render::model>(model_element->get<std::string>()); cocoon->model = resource_manager->load<render::model>(model_element->get<std::string>());
} }
else
{
cocoon->model = nullptr;
}
// Free JSON data // Free JSON data
delete data; delete data;

+ 2
- 1
src/game/ant/trait/loader/egg-loader.cpp View File

@ -37,8 +37,9 @@ trait::egg* resource_loader::load(resource_manager* resource_manager
if (egg_element == data->end()) if (egg_element == data->end())
throw std::runtime_error("Invalid egg trait."); throw std::runtime_error("Invalid egg trait.");
// Allocate egg trait
// Allocate and init egg trait
trait::egg* egg = new trait::egg(); trait::egg* egg = new trait::egg();
egg->model = nullptr;
// Load egg model // Load egg model
auto model_element = egg_element->find("model"); auto model_element = egg_element->find("model");

+ 32
- 25
src/game/ant/trait/loader/eyes-loader.cpp View File

@ -37,37 +37,44 @@ trait::eyes* resource_loader::load(resource_manager* resource_manag
if (eyes_element == data->end()) if (eyes_element == data->end())
throw std::runtime_error("Invalid eyes trait."); throw std::runtime_error("Invalid eyes trait.");
// Allocate eyes trait
// Allocate and init eyes trait
trait::eyes* eyes = new trait::eyes(); trait::eyes* eyes = new trait::eyes();
eyes->present = false;
eyes->model = nullptr;
eyes->length = 0.0f;
eyes->width = 0.0f;
eyes->height = 0.0f;
eyes->ommatidia_count = 0;
// Load eyes model (if not null)
auto model_element = eyes_element->find("model");
if (model_element == eyes_element->end())
throw std::runtime_error("Eyes trait doesn't specify eyes model.");
if (model_element->is_null())
{
eyes->model = nullptr;
}
else
// Parse eyes present
if (auto present_element = eyes_element->find("present"); present_element != eyes_element->end())
eyes->present = present_element->get<bool>();
if (eyes->present)
{ {
// Load eyes model
auto model_element = eyes_element->find("model");
if (model_element == eyes_element->end())
throw std::runtime_error("Eyes trait doesn't specify eyes model.");
eyes->model = resource_manager->load<render::model>(model_element->get<std::string>()); eyes->model = resource_manager->load<render::model>(model_element->get<std::string>());
// Parse length
if (auto element = eyes_element->find("length"); element != eyes_element->end())
eyes->length = element->get<float>();
// Parse width
if (auto element = eyes_element->find("width"); element != eyes_element->end())
eyes->width = element->get<float>();
// Parse height
if (auto element = eyes_element->find("height"); element != eyes_element->end())
eyes->height = element->get<float>();
// Parse ommatidia count
if (auto element = eyes_element->find("ommatidia_count"); element != eyes_element->end())
eyes->ommatidia_count = element->get<int>();
} }
// Parse eyes length
eyes->length = 0.0f;
if (auto length_element = eyes_element->find("length"); length_element != eyes_element->end())
eyes->length = length_element->get<float>();
// Parse eyes width
eyes->width = 0.0f;
if (auto width_element = eyes_element->find("width"); width_element != eyes_element->end())
eyes->width = width_element->get<float>();
// Parse eyes ommatidia
eyes->ommatidia = 0;
if (auto ommatidia_element = eyes_element->find("ommatidia"); ommatidia_element != eyes_element->end())
eyes->ommatidia = ommatidia_element->get<int>();
// Free JSON data // Free JSON data
delete data; delete data;

+ 7
- 1
src/game/ant/trait/loader/gaster-loader.cpp View File

@ -37,8 +37,10 @@ trait::gaster* resource_loader::load(resource_manager* resource_m
if (gaster_element == data->end()) if (gaster_element == data->end())
throw std::runtime_error("Invalid gaster trait."); throw std::runtime_error("Invalid gaster trait.");
// Allocate gaster trait
// Allocate and init gaster trait
trait::gaster* gaster = new trait::gaster(); trait::gaster* gaster = new trait::gaster();
gaster->model = nullptr;
gaster->phragmosis = 0.0;
// Load gaster model // Load gaster model
auto model_element = gaster_element->find("model"); auto model_element = gaster_element->find("model");
@ -46,6 +48,10 @@ trait::gaster* resource_loader::load(resource_manager* resource_m
throw std::runtime_error("Gaster trait doesn't specify gaster model."); throw std::runtime_error("Gaster trait doesn't specify gaster model.");
gaster->model = resource_manager->load<render::model>(model_element->get<std::string>()); gaster->model = resource_manager->load<render::model>(model_element->get<std::string>());
// Parse phragmosis
if (auto element = gaster_element->find("phragmosis"); element != gaster_element->end())
gaster->phragmosis = element->get<float>();
// Free JSON data // Free JSON data
delete data; delete data;

+ 15
- 14
src/game/ant/trait/loader/head-loader.cpp View File

@ -37,29 +37,30 @@ trait::head* resource_loader::load(resource_manager* resource_manag
if (head_element == data->end()) if (head_element == data->end())
throw std::runtime_error("Invalid head trait."); throw std::runtime_error("Invalid head trait.");
// Allocate head trait
// Allocate and init head trait
trait::head* head = new trait::head(); trait::head* head = new trait::head();
head->model = nullptr;
head->length = 0.0f;
head->width = 0.0f;
head->phragmosis = false;
// Load head model
// Load model
auto model_element = head_element->find("model"); auto model_element = head_element->find("model");
if (model_element == head_element->end()) if (model_element == head_element->end())
throw std::runtime_error("Head trait doesn't specify head model."); throw std::runtime_error("Head trait doesn't specify head model.");
head->model = resource_manager->load<render::model>(model_element->get<std::string>()); head->model = resource_manager->load<render::model>(model_element->get<std::string>());
// Parse head length
head->length = 0.0f;
if (auto length_element = head_element->find("length"); length_element != head_element->end())
head->length = length_element->get<float>();
// Parse length
if (auto element = head_element->find("length"); element != head_element->end())
head->length = element->get<float>();
// Parse head width
head->width = 0.0f;
if (auto width_element = head_element->find("width"); width_element != head_element->end())
head->width = width_element->get<float>();
// Parse width
if (auto element = head_element->find("width"); element != head_element->end())
head->width = element->get<float>();
// Parse head phragmotic
head->phragmotic = false;
if (auto phragmotic_element = head_element->find("phragmotic"); phragmotic_element != head_element->end())
head->phragmotic = phragmotic_element->get<bool>();
// Parse phragmosis
if (auto element = head_element->find("phragmosis"); element != head_element->end())
head->phragmosis = element->get<float>();
// Free JSON data // Free JSON data
delete data; delete data;

+ 7
- 6
src/game/ant/trait/loader/larva-loader.cpp View File

@ -37,19 +37,20 @@ trait::larva* resource_loader::load(resource_manager* resource_man
if (larva_element == data->end()) if (larva_element == data->end())
throw std::runtime_error("Invalid larva trait."); throw std::runtime_error("Invalid larva trait.");
// Allocate larva trait
// Allocate and init larva trait
trait::larva* larva = new trait::larva(); trait::larva* larva = new trait::larva();
larva->model = nullptr;
larva->instars = 0;
// Load larva model
// Load model
auto model_element = larva_element->find("model"); auto model_element = larva_element->find("model");
if (model_element == larva_element->end()) if (model_element == larva_element->end())
throw std::runtime_error("Larva trait doesn't specify larva model."); throw std::runtime_error("Larva trait doesn't specify larva model.");
larva->model = resource_manager->load<render::model>(model_element->get<std::string>()); larva->model = resource_manager->load<render::model>(model_element->get<std::string>());
// Parse larva instars
larva->instars = 0;
if (auto instars_element = larva_element->find("instars"); instars_element != larva_element->end())
larva->instars = instars_element->get<int>();
// Parse instars
if (auto element = larva_element->find("instars"); element != larva_element->end())
larva->instars = element->get<int>();
// Free JSON data // Free JSON data
delete data; delete data;

+ 12
- 6
src/game/ant/trait/loader/legs-loader.cpp View File

@ -37,19 +37,25 @@ trait::legs* resource_loader::load(resource_manager* resource_manag
if (legs_element == data->end()) if (legs_element == data->end())
throw std::runtime_error("Invalid legs trait."); throw std::runtime_error("Invalid legs trait.");
// Allocate legs trait
// Allocate and init legs trait
trait::legs* legs = new trait::legs(); trait::legs* legs = new trait::legs();
legs->model = nullptr;
legs->speed = 1.0f;
legs->grip = 1.0f;
// Load legs model
// Load model
auto model_element = legs_element->find("model"); auto model_element = legs_element->find("model");
if (model_element == legs_element->end()) if (model_element == legs_element->end())
throw std::runtime_error("Legs trait doesn't specify legs model."); throw std::runtime_error("Legs trait doesn't specify legs model.");
legs->model = resource_manager->load<render::model>(model_element->get<std::string>()); legs->model = resource_manager->load<render::model>(model_element->get<std::string>());
// Parse legs speed
legs->speed = 0.0f;
if (auto speed_element = legs_element->find("speed"); speed_element != legs_element->end())
legs->speed = speed_element->get<float>();
// Parse speed
if (auto element = legs_element->find("speed"); element != legs_element->end())
legs->speed = element->get<float>();
// Parse grip
if (auto element = legs_element->find("grip"); element != legs_element->end())
legs->grip = element->get<float>();
// Free JSON data // Free JSON data
delete data; delete data;

+ 16
- 10
src/game/ant/trait/loader/mandibles-loader.cpp View File

@ -37,24 +37,30 @@ trait::mandibles* resource_loader::load(resource_manager* reso
if (mandibles_element == data->end()) if (mandibles_element == data->end())
throw std::runtime_error("Invalid mandibles trait."); throw std::runtime_error("Invalid mandibles trait.");
// Allocate mandibles trait
// Allocate and init mandibles trait
trait::mandibles* mandibles = new trait::mandibles(); trait::mandibles* mandibles = new trait::mandibles();
mandibles->model = nullptr;
mandibles->length = 0.0f;
mandibles->apical_dental_count = 0;
mandibles->basal_dental_count = 0;
// Load mandibles model
// Load model
auto model_element = mandibles_element->find("model"); auto model_element = mandibles_element->find("model");
if (model_element == mandibles_element->end()) if (model_element == mandibles_element->end())
throw std::runtime_error("Mandibles trait doesn't specify mandibles model."); throw std::runtime_error("Mandibles trait doesn't specify mandibles model.");
mandibles->model = resource_manager->load<render::model>(model_element->get<std::string>()); mandibles->model = resource_manager->load<render::model>(model_element->get<std::string>());
// Parse mandibles length
mandibles->length = 0.0f;
if (auto length_element = mandibles_element->find("length"); length_element != mandibles_element->end())
mandibles->length = length_element->get<float>();
// Parse length
if (auto element = mandibles_element->find("length"); element != mandibles_element->end())
mandibles->length = element->get<float>();
// Parse apical dental count
if (auto element = mandibles_element->find("apical_dental_count"); element != mandibles_element->end())
mandibles->apical_dental_count = element->get<int>();
// Parse mandibles locking
mandibles->locking = false;
if (auto locking_element = mandibles_element->find("locking"); locking_element != mandibles_element->end())
mandibles->locking = locking_element->get<bool>();
// Parse basal dental count
if (auto element = mandibles_element->find("basal_dental_count"); element != mandibles_element->end())
mandibles->basal_dental_count = element->get<int>();
// Free JSON data // Free JSON data
delete data; delete data;

+ 19
- 13
src/game/ant/trait/loader/mesosoma-loader.cpp View File

@ -37,8 +37,13 @@ trait::mesosoma* resource_loader::load(resource_manager* resour
if (mesosoma_element == data->end()) if (mesosoma_element == data->end())
throw std::runtime_error("Invalid mesosoma trait."); throw std::runtime_error("Invalid mesosoma trait.");
// Allocate mesosoma trait
// Allocate and init mesosoma trait
trait::mesosoma* mesosoma = new trait::mesosoma(); trait::mesosoma* mesosoma = new trait::mesosoma();
mesosoma->model = nullptr;
mesosoma->pronotum_width = 0.0f;
mesosoma->pronotum_spinescence = 0.0f;
mesosoma->mesonotum_spinescence = 0.0f;
mesosoma->propodeum_spinescence = 0.0f;
// Load mesosoma model // Load mesosoma model
auto model_element = mesosoma_element->find("model"); auto model_element = mesosoma_element->find("model");
@ -46,20 +51,21 @@ trait::mesosoma* resource_loader::load(resource_manager* resour
throw std::runtime_error("Mesosoma trait doesn't specify mesosoma model."); throw std::runtime_error("Mesosoma trait doesn't specify mesosoma model.");
mesosoma->model = resource_manager->load<render::model>(model_element->get<std::string>()); mesosoma->model = resource_manager->load<render::model>(model_element->get<std::string>());
// Parse mesosoma length
mesosoma->length = 0.0f;
if (auto length_element = mesosoma_element->find("length"); length_element != mesosoma_element->end())
mesosoma->length = length_element->get<float>();
// Parse pronotum width
if (auto element = mesosoma_element->find("pronotum_width"); element != mesosoma_element->end())
mesosoma->pronotum_width = element->get<float>();
// Parse mesosoma width
mesosoma->width = 0.0f;
if (auto width_element = mesosoma_element->find("width"); width_element != mesosoma_element->end())
mesosoma->width = width_element->get<float>();
// Parse pronotum spinescence
if (auto element = mesosoma_element->find("pronotum_spinescence"); element != mesosoma_element->end())
mesosoma->pronotum_spinescence = element->get<float>();
// Parse mesosoma spinescence
mesosoma->spinescence = 0.0f;
if (auto spinescence_element = mesosoma_element->find("spinescence"); spinescence_element != mesosoma_element->end())
mesosoma->spinescence = spinescence_element->get<float>();
// Parse mesonotum spinescence
if (auto element = mesosoma_element->find("mesonotum_spinescence"); element != mesosoma_element->end())
mesosoma->mesonotum_spinescence = element->get<float>();
// Parse propodeum spinescence
if (auto element = mesosoma_element->find("propodeum_spinescence"); element != mesosoma_element->end())
mesosoma->propodeum_spinescence = element->get<float>();
// Free JSON data // Free JSON data
delete data; delete data;

+ 24
- 30
src/game/ant/trait/loader/ocelli-loader.cpp View File

@ -37,31 +37,33 @@ trait::ocelli* resource_loader::load(resource_manager* resource_m
if (ocelli_element == data->end()) if (ocelli_element == data->end())
throw std::runtime_error("Invalid ocelli trait."); throw std::runtime_error("Invalid ocelli trait.");
// Allocate ocelli trait
// Allocate and init ocelli trait
trait::ocelli* ocelli = new trait::ocelli(); trait::ocelli* ocelli = new trait::ocelli();
ocelli->lateral_ocelli_model = nullptr;
ocelli->median_ocellus_model = nullptr;
ocelli->lateral_ocelli_present = false;
ocelli->median_ocellus_present = false;
ocelli->width = 0.0f;
ocelli->height = 0.0f;
// Parse lateral ocelli
ocelli->lateral_ocelli = false;
if (auto lateral_ocelli_element = ocelli_element->find("lateral_ocelli"); lateral_ocelli_element != ocelli_element->end())
ocelli->lateral_ocelli = lateral_ocelli_element->get<bool>();
// Parse lateral ocelli present
if (auto element = ocelli_element->find("lateral_ocelli_present"); element != ocelli_element->end())
ocelli->lateral_ocelli_present = element->get<bool>();
// Parse median ocellus
ocelli->median_ocellus = false;
if (auto median_ocellus_element = ocelli_element->find("median_ocellus"); median_ocellus_element != ocelli_element->end())
ocelli->median_ocellus = median_ocellus_element->get<bool>();
// Parse median ocellus present
if (auto element = ocelli_element->find("median_ocellus_present"); element != ocelli_element->end())
ocelli->median_ocellus_present = element->get<bool>();
// Parse ocelli width
ocelli->width = 0.0f;
if (auto width_element = ocelli_element->find("width"); width_element != ocelli_element->end())
ocelli->width = width_element->get<float>();
// Parse ocelli height
ocelli->height = 0.0f;
if (auto height_element = ocelli_element->find("height"); height_element != ocelli_element->end())
ocelli->height = height_element->get<float>();
// Parse width
if (auto element = ocelli_element->find("width"); element != ocelli_element->end())
ocelli->width = element->get<float>();
// Load lateral ocelli model (if not null)
if (ocelli->lateral_ocelli)
// Parse height
if (auto element = ocelli_element->find("height"); element != ocelli_element->end())
ocelli->height = element->get<float>();
// Load lateral ocelli model, if present
if (ocelli->lateral_ocelli_present)
{ {
auto lateral_ocelli_model_element = ocelli_element->find("lateral_ocelli_model"); auto lateral_ocelli_model_element = ocelli_element->find("lateral_ocelli_model");
if (lateral_ocelli_model_element == ocelli_element->end() || lateral_ocelli_model_element->is_null()) if (lateral_ocelli_model_element == ocelli_element->end() || lateral_ocelli_model_element->is_null())
@ -69,13 +71,9 @@ trait::ocelli* resource_loader::load(resource_manager* resource_m
ocelli->lateral_ocelli_model = resource_manager->load<render::model>(lateral_ocelli_model_element->get<std::string>()); ocelli->lateral_ocelli_model = resource_manager->load<render::model>(lateral_ocelli_model_element->get<std::string>());
} }
else
{
ocelli->lateral_ocelli_model = nullptr;
}
// Load median ocellus model (if not null)
if (ocelli->median_ocellus)
// Load median ocellus model, if present
if (ocelli->median_ocellus_present)
{ {
auto median_ocellus_model_element = ocelli_element->find("median_ocellus_model"); auto median_ocellus_model_element = ocelli_element->find("median_ocellus_model");
if (median_ocellus_model_element == ocelli_element->end() || median_ocellus_model_element->is_null()) if (median_ocellus_model_element == ocelli_element->end() || median_ocellus_model_element->is_null())
@ -83,10 +81,6 @@ trait::ocelli* resource_loader::load(resource_manager* resource_m
ocelli->median_ocellus_model = resource_manager->load<render::model>(median_ocellus_model_element->get<std::string>()); ocelli->median_ocellus_model = resource_manager->load<render::model>(median_ocellus_model_element->get<std::string>());
} }
else
{
ocelli->median_ocellus_model = nullptr;
}
// Free JSON data // Free JSON data
delete data; delete data;

+ 2
- 1
src/game/ant/trait/loader/pigmentation-loader.cpp View File

@ -36,8 +36,9 @@ trait::pigmentation* resource_loader::load(resource_manager
if (pigmentation_element == data->end()) if (pigmentation_element == data->end())
throw std::runtime_error("Invalid pigmentation trait."); throw std::runtime_error("Invalid pigmentation trait.");
// Allocate pigmentation trait
// Allocate and init pigmentation trait
trait::pigmentation* pigmentation = new trait::pigmentation(); trait::pigmentation* pigmentation = new trait::pigmentation();
pigmentation->material = nullptr;
// Load pigmentation material // Load pigmentation material
auto material_element = pigmentation_element->find("material"); auto material_element = pigmentation_element->find("material");

+ 2
- 2
src/game/ant/trait/loader/pilosity-loader.cpp View File

@ -36,11 +36,11 @@ trait::pilosity* resource_loader::load(resource_manager* resour
if (pilosity_element == data->end()) if (pilosity_element == data->end())
throw std::runtime_error("Invalid pilosity trait."); throw std::runtime_error("Invalid pilosity trait.");
// Allocate pilosity trait
// Allocate and init pilosity trait
trait::pilosity* pilosity = new trait::pilosity(); trait::pilosity* pilosity = new trait::pilosity();
pilosity->density = 0.0f;
// Parse pilosity density // Parse pilosity density
pilosity->density = 0.0f;
if (auto density_element = pilosity_element->find("density"); density_element != pilosity_element->end()) if (auto density_element = pilosity_element->find("density"); density_element != pilosity_element->end())
pilosity->density = density_element->get<float>(); pilosity->density = density_element->get<float>();

+ 5
- 8
src/game/ant/trait/loader/sting-loader.cpp View File

@ -37,13 +37,14 @@ trait::sting* resource_loader::load(resource_manager* resource_man
if (sting_element == data->end()) if (sting_element == data->end())
throw std::runtime_error("Invalid sting trait."); throw std::runtime_error("Invalid sting trait.");
// Allocate sting trait
// Allocate and init sting trait
trait::sting* sting = new trait::sting(); trait::sting* sting = new trait::sting();
sting->present = false;
sting->model = nullptr;
// Parse sting present // Parse sting present
sting->present = false;
if (auto present_element = sting_element->find("present"); present_element != sting_element->end())
sting->present = present_element->get<bool>();
if (auto element = sting_element->find("present"); element != sting_element->end())
sting->present = element->get<bool>();
// Load sting model (if present) // Load sting model (if present)
if (sting->present) if (sting->present)
@ -53,10 +54,6 @@ trait::sting* resource_loader::load(resource_manager* resource_man
throw std::runtime_error("Sting trait doesn't specify sting model."); throw std::runtime_error("Sting trait doesn't specify sting model.");
sting->model = resource_manager->load<render::model>(model_element->get<std::string>()); sting->model = resource_manager->load<render::model>(model_element->get<std::string>());
} }
else
{
sting->model = nullptr;
}
// Free JSON data // Free JSON data
delete data; delete data;

+ 43
- 42
src/game/ant/trait/loader/waist-loader.cpp View File

@ -37,57 +37,58 @@ trait::waist* resource_loader::load(resource_manager* resource_man
if (waist_element == data->end()) if (waist_element == data->end())
throw std::runtime_error("Invalid waist trait."); throw std::runtime_error("Invalid waist trait.");
// Allocate waist trait
// Allocate and init waist trait
trait::waist* waist = new trait::waist(); trait::waist* waist = new trait::waist();
// Load waist model
auto model_element = waist_element->find("model");
if (model_element == waist_element->end())
throw std::runtime_error("Waist trait doesn't specify waist model.");
waist->model = resource_manager->load<render::model>(model_element->get<std::string>());
// Parse waist spinescence
waist->spinescence = 0.0f;
if (auto spinescence_element = waist_element->find("spinescence"); spinescence_element != waist_element->end())
waist->spinescence = spinescence_element->get<float>();
// Parse waist petiole length
waist->model = nullptr;
waist->petiole_present = false;
waist->petiole_length = 0.0f; waist->petiole_length = 0.0f;
if (auto petiole_length_element = waist_element->find("petiole_length"); petiole_length_element != waist_element->end())
waist->petiole_length = petiole_length_element->get<float>();
// Parse waist petiole width
waist->petiole_width = 0.0f; waist->petiole_width = 0.0f;
if (auto petiole_width_element = waist_element->find("petiole_width"); petiole_width_element != waist_element->end())
waist->petiole_width = petiole_width_element->get<float>();
// Parse waist petiole height
waist->petiole_height = 0.0f; waist->petiole_height = 0.0f;
if (auto petiole_height_element = waist_element->find("petiole_height"); petiole_height_element != waist_element->end())
waist->petiole_height = petiole_height_element->get<float>();
// Parse waist postpetiole
waist->postpetiole = false;
if (auto postpetiole_element = waist_element->find("postpetiole"); postpetiole_element != waist_element->end())
waist->postpetiole = postpetiole_element->get<bool>();
waist->petiole_spinescence = 0.0f;
waist->postpetiole_present = false;
waist->postpetiole_length = 0.0f; waist->postpetiole_length = 0.0f;
waist->postpetiole_width = 0.0f; waist->postpetiole_width = 0.0f;
waist->postpetiole_height = 0.0f; waist->postpetiole_height = 0.0f;
if (waist->postpetiole)
waist->postpetiole_spinescence = 0.0f;
// Parse petiole present
if (auto element = waist_element->find("petiole_present"); element != waist_element->end())
waist->petiole_present = element->get<bool>();
if (waist->petiole_present)
{ {
// Parse waist postpetiole length
if (auto postpetiole_length_element = waist_element->find("postpetiole_length"); postpetiole_length_element != waist_element->end())
waist->postpetiole_length = postpetiole_length_element->get<float>();
// Parse petiole properties
if (auto element = waist_element->find("petiole_length"); element != waist_element->end())
waist->petiole_length = element->get<float>();
if (auto element = waist_element->find("petiole_width"); element != waist_element->end())
waist->petiole_width = element->get<float>();
if (auto element = waist_element->find("petiole_height"); element != waist_element->end())
waist->petiole_height = element->get<float>();
if (auto element = waist_element->find("petiole_spinescence"); element != waist_element->end())
waist->petiole_spinescence = element->get<float>();
// Parse postpetiole present
if (auto element = waist_element->find("postpetiole_present"); element != waist_element->end())
waist->postpetiole_present = element->get<bool>();
if (waist->postpetiole_present)
{
// Parse postpetiole properties
if (auto element = waist_element->find("postpetiole_length"); element != waist_element->end())
waist->postpetiole_length = element->get<float>();
if (auto element = waist_element->find("postpetiole_width"); element != waist_element->end())
waist->postpetiole_width = element->get<float>();
if (auto element = waist_element->find("postpetiole_height"); element != waist_element->end())
waist->postpetiole_height = element->get<float>();
if (auto element = waist_element->find("postpetiole_spinescence"); element != waist_element->end())
waist->postpetiole_spinescence = element->get<float>();
}
// Parse waist postpetiole width
if (auto postpetiole_width_element = waist_element->find("postpetiole_width"); postpetiole_width_element != waist_element->end())
waist->postpetiole_width = postpetiole_width_element->get<float>();
// Parse waist postpetiole height
if (auto postpetiole_height_element = waist_element->find("postpetiole_height"); postpetiole_height_element != waist_element->end())
waist->postpetiole_height = postpetiole_height_element->get<float>();
// Load waist model
auto model_element = waist_element->find("model");
if (model_element == waist_element->end())
throw std::runtime_error("Waist trait doesn't specify waist model.");
waist->model = resource_manager->load<render::model>(model_element->get<std::string>());
} }
// Free JSON data // Free JSON data

+ 99
- 0
src/game/ant/trait/loader/wings-loader.cpp View File

@ -0,0 +1,99 @@
/*
* Copyright (C) 2021 Christopher J. Howard
*
* This file is part of Antkeeper source code.
*
* Antkeeper source code is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Antkeeper source code 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>.
*/
#include "resources/resource-loader.hpp"
#include "resources/resource-manager.hpp"
#include "resources/json.hpp"
#include "game/ant/trait/wings.hpp"
#include "render/model.hpp"
#include <stdexcept>
using namespace game::ant;
template <>
trait::wings* resource_loader<trait::wings>::load(resource_manager* resource_manager, PHYSFS_File* file, const std::filesystem::path& path)
{
// Load JSON data
json* data = resource_loader<json>::load(resource_manager, file, path);
// Validate trait file
auto wings_element = data->find("wings");
if (wings_element == data->end())
throw std::runtime_error("Invalid wings trait.");
// Allocate and init wings trait
trait::wings* wings = new trait::wings();
wings->forewings_model = nullptr;
wings->hindwings_model = nullptr;
wings->present = false;
wings->forewing_length = 0.0f;
wings->forewing_width = 0.0f;
wings->forewing_venation = 0.0f;
wings->hindwing_length = 0.0f;
wings->hindwing_width = 0.0f;
wings->hindwing_venation = 0.0f;
// Parse wings present
if (auto present_element = wings_element->find("present"); present_element != wings_element->end())
wings->present = present_element->get<bool>();
if (wings->present)
{
// Load forewings model
auto forewings_model_element = wings_element->find("forewings_model");
if (forewings_model_element == wings_element->end())
throw std::runtime_error("Wings trait doesn't specify forewings model.");
wings->forewings_model = resource_manager->load<render::model>(forewings_model_element->get<std::string>());
// Load hindwings model
auto hindwings_model_element = wings_element->find("hindwings_model");
if (hindwings_model_element == wings_element->end())
throw std::runtime_error("Wings trait doesn't specify hindwings model.");
wings->hindwings_model = resource_manager->load<render::model>(hindwings_model_element->get<std::string>());
// Parse forewing length
if (auto element = wings_element->find("forewing_length"); element != wings_element->end())
wings->forewing_length = element->get<float>();
// Parse forewing width
if (auto element = wings_element->find("forewing_width"); element != wings_element->end())
wings->forewing_width = element->get<float>();
// Parse forewing venation
if (auto element = wings_element->find("forewing_venation"); element != wings_element->end())
wings->forewing_venation = element->get<float>();
// Parse hindwing length
if (auto element = wings_element->find("hindwing_length"); element != wings_element->end())
wings->hindwing_length = element->get<float>();
// Parse hindwing width
if (auto element = wings_element->find("hindwing_width"); element != wings_element->end())
wings->hindwing_width = element->get<float>();
// Parse hindwing venation
if (auto element = wings_element->find("hindwing_venation"); element != wings_element->end())
wings->hindwing_venation = element->get<float>();
}
// Free JSON data
delete data;
return wings;
}

+ 13
- 6
src/game/ant/trait/mandibles.hpp View File

@ -27,18 +27,25 @@ namespace ant {
namespace trait { namespace trait {
/** /**
* Trait that describes the mandibles of an ant.
* Ant mandibles description.
*
* @see https://www.antwiki.org/wiki/Character_States_for_Extant_Ant_Genera_of_the_Formicidae
* @see https://www.antwiki.org/wiki/Morphological_and_Functional_Diversity_of_Ant_Mandibles
* @see https://www.antwiki.org/wiki/Morphological_Measurements
*/ */
struct mandibles struct mandibles
{ {
/// Length of the closed mandibles in full face view (MandL), measured in mesosomal lengths.
/// 3D model of the mandibles.
render::model* model;
/// Mandible length at closure, in mesosomal lengths.
float length; float length;
/// Indicates the mandibles are able to lock open, such as in trap-jaw ants.
bool locking;
/// Number of teeth and denticles on the masticatory (apical) margin of the mandible.
int apical_dental_count;
/// 3D model of the mandibles.
render::model* model;
/// Number of teeth and denticles on the basal margin of the mandible.
int basal_dental_count;
}; };
} // namespace trait } // namespace trait

+ 14
- 9
src/game/ant/trait/mesosoma.hpp View File

@ -27,21 +27,26 @@ namespace ant {
namespace trait { namespace trait {
/** /**
* Trait that describes the mesosoma of an ant.
* Ant mesosoma description.
*
* @see https://www.antwiki.org/wiki/Morphological_Measurements
*/ */
struct mesosoma struct mesosoma
{ {
/// Mesosoma length (ML), also known as the Weber's length (WL).
float length;
/// 3D model of the mesosoma.
render::model* model;
/// Pronotum width in dorsal view (PrW).
float width;
/// Pronotum width, in mesosomal lengths.
float pronotum_width;
/// Degree of spinescence.
float spinescence;
/// Degree of spinescence on the pronotum.
float pronotum_spinescence;
/// 3D model of the mesosoma.
render::model* model;
/// Degree of spinescence on the mesonotum.
float mesonotum_spinescence;
/// Degree of spinescence on the propodeum.
float propodeum_spinescence;
}; };
} // namespace trait } // namespace trait

src/game/ant/nest-site.hpp → src/game/ant/trait/nest-site.hpp View File

@ -22,9 +22,10 @@
namespace game { namespace game {
namespace ant { namespace ant {
namespace trait {
/** /**
* Nest site enumerations.
* Colony nest site description.
*/ */
enum class nest_site enum class nest_site
{ {
@ -32,6 +33,7 @@ enum class nest_site
arboreal arboreal
}; };
} // namespace trait
} // namespace ant } // namespace ant
} // namespace game } // namespace game

+ 9
- 9
src/game/ant/trait/ocelli.hpp View File

@ -27,27 +27,27 @@ namespace ant {
namespace trait { namespace trait {
/** /**
* Trait that describes the ocelli of an ant.
* Ant ocelli description.
*/ */
struct ocelli struct ocelli
{ {
/// 3D model of the lateral ocelli, if present.
render::model* lateral_ocelli_model;
/// 3D model of the median ocellus, if present.
render::model* median_ocellus_model;
/// Lateral ocelli present. /// Lateral ocelli present.
bool lateral_ocelli;
bool lateral_ocelli_present;
/// Median ocellus present. /// Median ocellus present.
bool median_ocellus;
bool median_ocellus_present;
/// Ocellus width, in mesosomal lengths. /// Ocellus width, in mesosomal lengths.
float width; float width;
/// Ocellus height, in mesosomal lengths. /// Ocellus height, in mesosomal lengths.
float height; float height;
/// 3D model of the lateral ocelli.
render::model* lateral_ocelli_model;
/// 3D model of the median ocellus.
render::model* median_ocellus_model;
}; };
} // namespace trait } // namespace trait

+ 1
- 1
src/game/ant/trait/pigmentation.hpp View File

@ -27,7 +27,7 @@ namespace ant {
namespace trait { namespace trait {
/** /**
* Trait that describes the pigmentation of an ant.
* Ant pigmentation description.
*/ */
struct pigmentation struct pigmentation
{ {

+ 1
- 1
src/game/ant/trait/pilosity.hpp View File

@ -25,7 +25,7 @@ namespace ant {
namespace trait { namespace trait {
/** /**
* Trait that describes the pilosity of an ant.
* Ant pilosity description.
*/ */
struct pilosity struct pilosity
{ {

+ 1
- 1
src/game/ant/trait/sculpturing.hpp View File

@ -27,7 +27,7 @@ namespace ant {
namespace trait { namespace trait {
/** /**
* Trait that describes the surface sculpturing of an ant.
* Ant surface sculpturing description.
*/ */
struct sculpturing struct sculpturing
{ {

src/game/ant/trait/size.hpp → src/game/ant/trait/size-variation.hpp View File

@ -17,24 +17,30 @@
* along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>. * along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef ANTKEEPER_GAME_ANT_TRAIT_SIZE_HPP
#define ANTKEEPER_GAME_ANT_TRAIT_SIZE_HPP
#ifndef ANTKEEPER_GAME_ANT_TRAIT_SIZE_VARIATION_HPP
#define ANTKEEPER_GAME_ANT_TRAIT_SIZE_VARIATION_HPP
namespace game { namespace game {
namespace ant { namespace ant {
namespace trait { namespace trait {
/** /**
* Trait that describes the sizes of an ant caste.
* Caste size variation description.
*/ */
struct size
struct size_variation
{ {
/// Size-frequency distribution, with sizes measured in mesosomal lengths.
std::vector<std::tuple<float, float>> distribution;
/// Minimum size factor.
float min_size;
/// Maximum size factor.
float max_size;
/// Mean size factor.
float mean_size;
}; };
} // namespace trait } // namespace trait
} // namespace ant } // namespace ant
} // namespace game } // namespace game
#endif // ANTKEEPER_GAME_ANT_TRAIT_SIZE_HPP
#endif // ANTKEEPER_GAME_ANT_TRAIT_SIZE_VARIATION_HPP

+ 19
- 11
src/game/ant/trait/waist.hpp View File

@ -28,35 +28,43 @@ namespace trait {
/** /**
* Trait that describes the waist (petiole plus postpetiole) of an ant. * Trait that describes the waist (petiole plus postpetiole) of an ant.
*
* @see https://www.antwiki.org/wiki/Morphological_Measurements
*/ */
struct waist struct waist
{ {
/// 3D model of the waist. /// 3D model of the waist.
render::model* model; render::model* model;
/// Degree of spinescence.
float spinescence;
/// Postpetiole presence.
bool postpetiole;
//// Petiole presence.
bool petiole_present;
/// Petiole length in dorsal view (PetL).
/// Petiole length, in mesosomal lengths.
float petiole_length; float petiole_length;
/// Petiole width in dorsal view (PetW).
/// Petiole width, in mesosomal lengths.
float petiole_width; float petiole_width;
/// Petiole height in in lateral profile (PetH).
/// Petiole height, in mesosomal lengths.
float petiole_height; float petiole_height;
/// Postpetiole length in dorsal view (PPL).
/// Degree of petiole spinescence.
float petiole_spinescence;
/// Postpetiole presence.
bool postpetiole_present;
/// Postpetiole length, in mesosomal lengths.
float postpetiole_length; float postpetiole_length;
/// Postpetiole width in dorsal view (PPW).
/// Postpetiole width, in mesosomal lengths.
float postpetiole_width; float postpetiole_width;
/// Postpetiole height in in lateral profile (PPH).
/// Postpetiole height, in mesosomal lengths.
float postpetiole_height; float postpetiole_height;
/// Degree of postpetiole spinescence
float postpetiole_spinescence;
}; };
} // namespace trait } // namespace trait

src/game/ant/trait/hindwings.hpp → src/game/ant/trait/wings.hpp View File

@ -17,8 +17,8 @@
* along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>. * along with Antkeeper source code. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef ANTKEEPER_GAME_ANT_TRAIT_HINDWINGS_HPP
#define ANTKEEPER_GAME_ANT_TRAIT_HINDWINGS_HPP
#ifndef ANTKEEPER_GAME_ANT_TRAIT_WINGS_HPP
#define ANTKEEPER_GAME_ANT_TRAIT_WINGS_HPP
#include "render/model.hpp" #include "render/model.hpp"
@ -27,25 +27,40 @@ namespace ant {
namespace trait { namespace trait {
/** /**
* Trait that describes the hindwings of an ant.
* Ant wings description.
*/ */
struct hindwings
struct wings
{ {
/// Wing length, measured in mesosomal lengths.
float length;
/// 3D model of the forewings.
render::model* forewings_model;
/// Wing width, measured in mesosomal lengths.
float width;
/// 3D model of the hindwings.
render::model* hindwings_model;
/// Degree of venation. A value of `1.0` indicates a highly-developed venation pattern, while `0.0` indicates a complete absence of visible venation.
float venation;
/// Wings presence.
bool present;
/// 3D model of the hindwings.
render::model* model;
/// Forewing length, in mesosomal lengths.
float forewing_length;
/// Forewing width, in mesosomal lengths.
float forewing_width;
/// Degree of forewing venation. A value of `1.0` indicates a highly-developed venation pattern, while `0.0` indicates a complete absence of visible venation.
float forewing_venation;
/// Forewing length, in mesosomal lengths.
float hindwing_length;
/// Forewing width, in mesosomal lengths.
float hindwing_width;
/// Degree of hindwing venation. A value of `1.0` indicates a highly-developed venation pattern, while `0.0` indicates a complete absence of visible venation.
float hindwing_venation;
}; };
} // namespace trait } // namespace trait
} // namespace ant } // namespace ant
} // namespace game } // namespace game
#endif // ANTKEEPER_GAME_ANT_TRAIT_HINDWINGS_HPP
#endif // ANTKEEPER_GAME_ANT_TRAIT_WINGS_HPP

+ 32
- 81
src/game/load.cpp View File

@ -50,83 +50,57 @@ void biome(game::context& ctx, const std::filesystem::path& path)
/* /*
image img; image img;
img.format(1, 1);
img.resize(1024, 1024);
float frequency = 10.0f;
std::size_t octaves = 4;
float lacunarity = 2.0f;
float gain = 0.5f;
auto hash = static_cast<math::vector<std::uint32_t, 2>(*)(const math::vector<float, 2>&)>(math::hash::pcg);
auto noise = static_cast<float(*)(const math::vector<float, 2>&, decltype(hash))>(math::noise::simplex);
auto fbm = [&](const float2& x)
{
return math::noise::fbm
(
x,
octaves,
lacunarity,
gain,
noise,
hash
);
};
img.format(1, 4);
img.resize(2048, 2048);
auto width = img.get_width(); auto width = img.get_width();
auto height = img.get_height(); auto height = img.get_height();
unsigned char* pixels = (unsigned char*)img.data(); unsigned char* pixels = (unsigned char*)img.data();
const float frequency = 400.0f;
float scale_x = 1.0f / static_cast<float>(width - 1) * frequency; float scale_x = 1.0f / static_cast<float>(width - 1) * frequency;
float scale_y = 1.0f / static_cast<float>(height - 1) * frequency; float scale_y = 1.0f / static_cast<float>(height - 1) * frequency;
std::for_each std::for_each
( (
std::execution::par_unseq, std::execution::par_unseq,
img.begin<unsigned char>(),
img.end<unsigned char>(),
[pixels, width, height, scale_x, scale_y, &fbm](auto& pixel)
img.begin<math::vector<unsigned char, 4>>(),
img.end<math::vector<unsigned char, 4>>(),
[pixels, width, height, scale_x, scale_y, frequency](auto& pixel)
{ {
std::size_t i = &pixel - pixels;
std::size_t y = i / width;
std::size_t x = i % width;
const std::size_t i = &pixel - (math::vector<unsigned char, 4>*)pixels;
const std::size_t y = i / width;
const std::size_t x = i % width;
float2 position =
const float2 position =
{ {
static_cast<float>(x) * scale_x, static_cast<float>(x) * scale_x,
static_cast<float>(y) * scale_y static_cast<float>(y) * scale_y
}; };
//float n = math::noise::simplex<float, 2>(position, &math::noise::hash::pcg3d_1);
//float n = fbm(position);
// auto [sqr_center_distance, displacement, id, sqr_edge_distance] = math::noise::voronoi::f1_edge<float, std::uint32_t>(position, 1.0f, &math::noise::hash::pcg3d_3);
// float center_distance = std::sqrt(sqr_center_distance);
// float edge_distance = std::sqrt(sqr_edge_distance);
auto
const auto
[ [
f1_sqr_distance, f1_sqr_distance,
f1_displacement, f1_displacement,
f1_id,
// f2_sqr_distance,
// f2_displacement,
// f2_id
edge_sqr_distance(
] = math::noise::voronoi::f1_edge<float, 2>(position);
f1_id
] = math::noise::voronoi::f1<float, 2>(position, 1.0f, {frequency, frequency});
float f1_distance = std::sqrt(f1_sqr_distance();
//float f2_distance = std::sqrt(f2_sqr_distance();
float edge_distance = std::sqrt(edge_sqr_distance();
const float f1_distance = std::sqrt(f1_sqr_distance);
pixel = static_cast<unsigned char>(std::min(255.0f, f1_distance * 255.0f));
//pixel = static_cast<unsigned char>(id % 255);
const float2 uv = (position + f1_displacement) / frequency;
pixel =
{
static_cast<unsigned char>(std::min(255.0f, f1_distance * 255.0f)),
static_cast<unsigned char>(std::min(255.0f, uv[0] * 255.0f)),
static_cast<unsigned char>(std::min(255.0f, uv[1] * 255.0f)),
static_cast<unsigned char>(f1_id % 256)
};
} }
); );
stbi_flip_vertically_on_write(1); stbi_flip_vertically_on_write(1);
stbi_write_png((ctx.config_path / "gallery" / "noise.png").string().c_str(), img.get_width(), img.get_height(), img.get_channel_count(), img.data(), img.get_width() * img.get_channel_count());
stbi_write_tga((ctx.config_path / "gallery" / "voronoi-f1-400-nc8-2k.tga").string().c_str(), img.get_width(), img.get_height(), img.get_channel_count(), img.data());
*/ */
try try
@ -195,44 +169,21 @@ void biome(game::context& ctx, const std::filesystem::path& path)
( (
[](float x, float z) -> float [](float x, float z) -> float
{ {
/*
float frequency = 0.01f;
std::size_t octaves = 4;
float lacunarity = 3.0f;
float gain = 0.5f;
float2 position = float2{x, z} * frequency;
const float2 position = float2{x, z};
const std::size_t octaves = 3;
const float lacunarity = 1.5f;
const float gain = 0.5f;
float fbm = math::noise::fbm
const float fbm = math::noise::fbm
( (
position,
position * 0.005f,
octaves, octaves,
lacunarity, lacunarity,
gain gain
); );
auto
[
f1_sqr_distance,
f1_displacement,
f1_id
] = math::noise::voronoi::f1(position);
float f1_distance = std::sqrt(f1_sqr_distance();
float y = f1_distance * 5.0f + fbm * 0.5f;
*/
float2 position = float2{x, z} * 0.05f;
auto
[
f1_sqr_distance,
f1_displacement,
f1_id
] = math::noise::voronoi::f1(position);
float f1_distance = std::sqrt(f1_sqr_distance);
float y = f1_distance * 3.0f;
float y = fbm * 4.0f;
return y; return y;
} }

+ 1
- 1
src/game/state/boot.cpp View File

@ -888,7 +888,7 @@ void boot::setup_systems()
ctx.blackbody_system->set_illuminant(color::illuminant::deg2::d55<double>); ctx.blackbody_system->set_illuminant(color::illuminant::deg2::d55<double>);
// RGB wavelengths for atmospheric scatteering // RGB wavelengths for atmospheric scatteering
ctx.rgb_wavelengths = {640, 575, 440};
ctx.rgb_wavelengths = {680, 550, 440};
// Setup atmosphere system // Setup atmosphere system
ctx.atmosphere_system = new game::system::atmosphere(*ctx.entity_registry); ctx.atmosphere_system = new game::system::atmosphere(*ctx.entity_registry);

+ 1
- 0
src/game/state/gamepad-config-menu.hpp View File

@ -22,6 +22,7 @@
#include "game/state/base.hpp" #include "game/state/base.hpp"
#include "input/control.hpp" #include "input/control.hpp"
#include <string>
namespace game { namespace game {
namespace state { namespace state {

+ 53
- 82
src/game/state/nest-selection.cpp View File

@ -46,8 +46,6 @@
#include "state-machine.hpp" #include "state-machine.hpp"
#include "config.hpp" #include "config.hpp"
#include "game/load.hpp" #include "game/load.hpp"
#include "game/ant/breed.hpp"
#include "game/ant/morphogenesis.hpp"
#include "math/interpolation.hpp" #include "math/interpolation.hpp"
#include "physics/light/exposure.hpp" #include "physics/light/exposure.hpp"
#include "application.hpp" #include "application.hpp"
@ -55,6 +53,9 @@
#include "math/projection.hpp" #include "math/projection.hpp"
#include <iostream> #include <iostream>
#include "game/ant/morphogenesis.hpp"
#include "game/ant/species.hpp"
using namespace game::ant; using namespace game::ant;
namespace game { namespace game {
@ -65,6 +66,49 @@ nest_selection::nest_selection(game::context& ctx):
{ {
ctx.logger->push_task("Entering nest selection state"); ctx.logger->push_task("Entering nest selection state");
ctx.logger->push_task("Loading worker caste");
ant::species species;
ant::caste& worker_caste = *species.worker_caste;
worker_caste.type = ant::caste_type::worker;
worker_caste.antennae = ctx.resource_manager->load<ant::trait::antennae>("pogonomyrmex-female-antennae.dna");
worker_caste.eyes = ctx.resource_manager->load<ant::trait::eyes>("pogonomyrmex-eyes.dna");
worker_caste.gaster = ctx.resource_manager->load<ant::trait::gaster>("pogonomyrmex-worker-gaster.dna");
worker_caste.head = ctx.resource_manager->load<ant::trait::head>("pogonomyrmex-head.dna");
worker_caste.legs = ctx.resource_manager->load<ant::trait::legs>("pogonomyrmex-legs.dna");
worker_caste.mandibles = ctx.resource_manager->load<ant::trait::mandibles>("pogonomyrmex-mandibles.dna");
worker_caste.mesosoma = ctx.resource_manager->load<ant::trait::mesosoma>("pogonomyrmex-worker-mesosoma.dna");
worker_caste.ocelli = ctx.resource_manager->load<ant::trait::ocelli>("ocelli-absent.dna");
worker_caste.pigmentation = ctx.resource_manager->load<ant::trait::pigmentation>("rust-pigmentation.dna");
worker_caste.sculpturing = ctx.resource_manager->load<ant::trait::sculpturing>("politus-sculpturing.dna");
//worker_caste.size_variation = ctx.resource_manager->load<ant::trait::size_variation>(...);
worker_caste.sting = ctx.resource_manager->load<ant::trait::sting>("pogonomyrmex-sting.dna");
worker_caste.waist = ctx.resource_manager->load<ant::trait::waist>("pogonomyrmex-waist.dna");
worker_caste.wings = ctx.resource_manager->load<ant::trait::wings>("wings-absent.dna");
render::model* worker_model = ant::morphogenesis(worker_caste);
ctx.logger->pop_task(EXIT_SUCCESS);
// Create worker entity(s)
entity::id worker_eid = ctx.entity_registry->create();
component::transform worker_transform_component;
worker_transform_component.local = math::transform<float>::identity;
worker_transform_component.local.translation = {0, 0, -20};
worker_transform_component.world = worker_transform_component.local;
worker_transform_component.warp = true;
ctx.entity_registry->emplace<component::transform>(worker_eid, worker_transform_component);
component::model worker_model_component;
worker_model_component.render_model = worker_model;
worker_model_component.instance_count = 0;
worker_model_component.layers = ~0;
ctx.entity_registry->emplace<component::model>(worker_eid, worker_model_component);
// Disable UI color clear // Disable UI color clear
ctx.ui_clear_pass->set_cleared_buffers(false, true, false); ctx.ui_clear_pass->set_cleared_buffers(false, true, false);
@ -132,8 +176,11 @@ nest_selection::nest_selection(game::context& ctx):
// Satisfy first person camera rig constraints // Satisfy first person camera rig constraints
satisfy_first_person_camera_rig_constraints(); satisfy_first_person_camera_rig_constraints();
auto ruler_archetype = ctx.resource_manager->load<entity::archetype>("ruler-10cm.ent");
ruler_archetype->create(*ctx.entity_registry);
auto color_checker_archetype = ctx.resource_manager->load<entity::archetype>("color-checker.ent");
color_checker_archetype->create(*ctx.entity_registry);
// auto ruler_archetype = ctx.resource_manager->load<entity::archetype>("ruler-10cm.ent");
// ruler_archetype->create(*ctx.entity_registry);
// Queue control setup // Queue control setup
ctx.function_queue.push(std::bind(&nest_selection::enable_controls, this)); ctx.function_queue.push(std::bind(&nest_selection::enable_controls, this));
@ -653,7 +700,7 @@ void nest_selection::enable_controls()
[&ctx = this->ctx](float) [&ctx = this->ctx](float)
{ {
//ctx.astronomy_system->set_exposure_offset(ctx.astronomy_system->get_exposure_offset() - 1.0f); //ctx.astronomy_system->set_exposure_offset(ctx.astronomy_system->get_exposure_offset() - 1.0f);
ctx.surface_camera->set_exposure(ctx.surface_camera->get_exposure() + 3.0f * static_cast<float>(ctx.loop.get_update_period()));
ctx.surface_camera->set_exposure(ctx.surface_camera->get_exposure() + 0.5f * static_cast<float>(ctx.loop.get_update_period()));
ctx.logger->log("EV100: " + std::to_string(ctx.surface_camera->get_exposure())); ctx.logger->log("EV100: " + std::to_string(ctx.surface_camera->get_exposure()));
} }
); );
@ -663,80 +710,10 @@ void nest_selection::enable_controls()
[&ctx = this->ctx](float) [&ctx = this->ctx](float)
{ {
//ctx.astronomy_system->set_exposure_offset(ctx.astronomy_system->get_exposure_offset() + 1.0f); //ctx.astronomy_system->set_exposure_offset(ctx.astronomy_system->get_exposure_offset() + 1.0f);
ctx.surface_camera->set_exposure(ctx.surface_camera->get_exposure() - 3.0f * static_cast<float>(ctx.loop.get_update_period()));
ctx.surface_camera->set_exposure(ctx.surface_camera->get_exposure() - 0.5f * static_cast<float>(ctx.loop.get_update_period()));
ctx.logger->log("EV100: " + std::to_string(ctx.surface_camera->get_exposure())); ctx.logger->log("EV100: " + std::to_string(ctx.surface_camera->get_exposure()));
} }
); );
const float wavelength_speed = 20.0;
ctx.controls["dec_red"]->set_active_callback
(
[&ctx = this->ctx, wavelength_speed](float)
{
ctx.rgb_wavelengths.x() -= wavelength_speed * ctx.loop.get_update_period();
ctx.atmosphere_system->set_rgb_wavelengths(ctx.rgb_wavelengths * 1e-9);
std::stringstream stream;
stream << ctx.rgb_wavelengths;
ctx.logger->log("wavelengths: " + stream.str());
}
);
ctx.controls["inc_red"]->set_active_callback
(
[&ctx = this->ctx, wavelength_speed](float)
{
ctx.rgb_wavelengths.x() += wavelength_speed * ctx.loop.get_update_period();
ctx.atmosphere_system->set_rgb_wavelengths(ctx.rgb_wavelengths * 1e-9);
std::stringstream stream;
stream << ctx.rgb_wavelengths;
ctx.logger->log("wavelengths: " + stream.str());
}
);
ctx.controls["dec_green"]->set_active_callback
(
[&ctx = this->ctx, wavelength_speed](float)
{
ctx.rgb_wavelengths.y() -= wavelength_speed * ctx.loop.get_update_period();
ctx.atmosphere_system->set_rgb_wavelengths(ctx.rgb_wavelengths * 1e-9);
std::stringstream stream;
stream << ctx.rgb_wavelengths;
ctx.logger->log("wavelengths: " + stream.str());
}
);
ctx.controls["inc_green"]->set_active_callback
(
[&ctx = this->ctx, wavelength_speed](float)
{
ctx.rgb_wavelengths.y() += wavelength_speed * ctx.loop.get_update_period();
ctx.atmosphere_system->set_rgb_wavelengths(ctx.rgb_wavelengths * 1e-9);
std::stringstream stream;
stream << ctx.rgb_wavelengths;
ctx.logger->log("wavelengths: " + stream.str());
}
);
ctx.controls["dec_blue"]->set_active_callback
(
[&ctx = this->ctx, wavelength_speed](float)
{
ctx.rgb_wavelengths.z() -= wavelength_speed * ctx.loop.get_update_period();
ctx.atmosphere_system->set_rgb_wavelengths(ctx.rgb_wavelengths * 1e-9);
std::stringstream stream;
stream << ctx.rgb_wavelengths;
ctx.logger->log("wavelengths: " + stream.str());
}
);
ctx.controls["inc_blue"]->set_active_callback
(
[&ctx = this->ctx, wavelength_speed](float)
{
ctx.rgb_wavelengths.z() += wavelength_speed * ctx.loop.get_update_period();
ctx.atmosphere_system->set_rgb_wavelengths(ctx.rgb_wavelengths * 1e-9);
std::stringstream stream;
stream << ctx.rgb_wavelengths;
ctx.logger->log("wavelengths: " + stream.str());
}
);
} }
void nest_selection::disable_controls() void nest_selection::disable_controls()
@ -772,12 +749,6 @@ void nest_selection::disable_controls()
ctx.controls["pause"]->set_activated_callback(nullptr); ctx.controls["pause"]->set_activated_callback(nullptr);
ctx.controls["increase_exposure"]->set_active_callback(nullptr); ctx.controls["increase_exposure"]->set_active_callback(nullptr);
ctx.controls["decrease_exposure"]->set_active_callback(nullptr); ctx.controls["decrease_exposure"]->set_active_callback(nullptr);
ctx.controls["dec_red"]->set_active_callback(nullptr);
ctx.controls["inc_red"]->set_active_callback(nullptr);
ctx.controls["dec_green"]->set_active_callback(nullptr);
ctx.controls["inc_green"]->set_active_callback(nullptr);
ctx.controls["dec_blue"]->set_active_callback(nullptr);
ctx.controls["inc_blue"]->set_active_callback(nullptr);
} }
} // namespace state } // namespace state

+ 0
- 80
src/game/state/nuptial-flight.cpp View File

@ -49,8 +49,6 @@
#include "state-machine.hpp" #include "state-machine.hpp"
#include "config.hpp" #include "config.hpp"
#include "game/load.hpp" #include "game/load.hpp"
#include "game/ant/breed.hpp"
#include "game/ant/morphogenesis.hpp"
#include "math/interpolation.hpp" #include "math/interpolation.hpp"
#include "physics/light/exposure.hpp" #include "physics/light/exposure.hpp"
#include "color/color.hpp" #include "color/color.hpp"
@ -61,8 +59,6 @@
#include "geom/primitive/hyperplane.hpp" #include "geom/primitive/hyperplane.hpp"
#include <iostream> #include <iostream>
using namespace game::ant;
namespace game { namespace game {
namespace state { namespace state {
@ -775,76 +771,6 @@ void nuptial_flight::enable_controls()
ctx.logger->log("EV100: " + std::to_string(ctx.surface_camera->get_exposure())); ctx.logger->log("EV100: " + std::to_string(ctx.surface_camera->get_exposure()));
} }
); );
const float wavelength_speed = 20.0;
ctx.controls["dec_red"]->set_active_callback
(
[&ctx = this->ctx, wavelength_speed](float)
{
ctx.rgb_wavelengths.x() -= wavelength_speed * ctx.loop.get_update_period();
ctx.atmosphere_system->set_rgb_wavelengths(ctx.rgb_wavelengths * 1e-9);
std::stringstream stream;
stream << ctx.rgb_wavelengths;
ctx.logger->log("wavelengths: " + stream.str());
}
);
ctx.controls["inc_red"]->set_active_callback
(
[&ctx = this->ctx, wavelength_speed](float)
{
ctx.rgb_wavelengths.x() += wavelength_speed * ctx.loop.get_update_period();
ctx.atmosphere_system->set_rgb_wavelengths(ctx.rgb_wavelengths * 1e-9);
std::stringstream stream;
stream << ctx.rgb_wavelengths;
ctx.logger->log("wavelengths: " + stream.str());
}
);
ctx.controls["dec_green"]->set_active_callback
(
[&ctx = this->ctx, wavelength_speed](float)
{
ctx.rgb_wavelengths.y() -= wavelength_speed * ctx.loop.get_update_period();
ctx.atmosphere_system->set_rgb_wavelengths(ctx.rgb_wavelengths * 1e-9);
std::stringstream stream;
stream << ctx.rgb_wavelengths;
ctx.logger->log("wavelengths: " + stream.str());
}
);
ctx.controls["inc_green"]->set_active_callback
(
[&ctx = this->ctx, wavelength_speed](float)
{
ctx.rgb_wavelengths.y() += wavelength_speed * ctx.loop.get_update_period();
ctx.atmosphere_system->set_rgb_wavelengths(ctx.rgb_wavelengths * 1e-9);
std::stringstream stream;
stream << ctx.rgb_wavelengths;
ctx.logger->log("wavelengths: " + stream.str());
}
);
ctx.controls["dec_blue"]->set_active_callback
(
[&ctx = this->ctx, wavelength_speed](float)
{
ctx.rgb_wavelengths.z() -= wavelength_speed * ctx.loop.get_update_period();
ctx.atmosphere_system->set_rgb_wavelengths(ctx.rgb_wavelengths * 1e-9);
std::stringstream stream;
stream << ctx.rgb_wavelengths;
ctx.logger->log("wavelengths: " + stream.str());
}
);
ctx.controls["inc_blue"]->set_active_callback
(
[&ctx = this->ctx, wavelength_speed](float)
{
ctx.rgb_wavelengths.z() += wavelength_speed * ctx.loop.get_update_period();
ctx.atmosphere_system->set_rgb_wavelengths(ctx.rgb_wavelengths * 1e-9);
std::stringstream stream;
stream << ctx.rgb_wavelengths;
ctx.logger->log("wavelengths: " + stream.str());
}
);
} }
void nuptial_flight::disable_controls() void nuptial_flight::disable_controls()
@ -880,12 +806,6 @@ void nuptial_flight::disable_controls()
ctx.controls["pause"]->set_activated_callback(nullptr); ctx.controls["pause"]->set_activated_callback(nullptr);
ctx.controls["increase_exposure"]->set_active_callback(nullptr); ctx.controls["increase_exposure"]->set_active_callback(nullptr);
ctx.controls["decrease_exposure"]->set_active_callback(nullptr); ctx.controls["decrease_exposure"]->set_active_callback(nullptr);
ctx.controls["dec_red"]->set_active_callback(nullptr);
ctx.controls["inc_red"]->set_active_callback(nullptr);
ctx.controls["dec_green"]->set_active_callback(nullptr);
ctx.controls["inc_green"]->set_active_callback(nullptr);
ctx.controls["dec_blue"]->set_active_callback(nullptr);
ctx.controls["inc_blue"]->set_active_callback(nullptr);
} }
void nuptial_flight::select_entity(entity::id entity_id) void nuptial_flight::select_entity(entity::id entity_id)

+ 0
- 1
src/game/state/splash.cpp View File

@ -30,7 +30,6 @@
#include "resources/resource-manager.hpp" #include "resources/resource-manager.hpp"
#include "render/material-flags.hpp" #include "render/material-flags.hpp"
#include "math/linear-algebra.hpp" #include "math/linear-algebra.hpp"
#include <iostream>
namespace game { namespace game {
namespace state { namespace state {

+ 34
- 96
src/game/system/terrain.cpp View File

@ -55,7 +55,10 @@ terrain::terrain(entity::registry& registry):
// Init quadtee node sizes at each depth // Init quadtee node sizes at each depth
for (std::size_t i = 0; i <= quadtree_type::max_depth; ++i) for (std::size_t i = 0; i <= quadtree_type::max_depth; ++i)
{
quadtree_node_size[i] = 0.0f; quadtree_node_size[i] = 0.0f;
quadtree_node_resolution[i] = static_cast<quadtree_node_type>(std::exp2(i));
}
registry.on_construct<component::terrain>().connect<&terrain::on_terrain_construct>(this); registry.on_construct<component::terrain>().connect<&terrain::on_terrain_construct>(this);
registry.on_update<component::terrain>().connect<&terrain::on_terrain_update>(this); registry.on_update<component::terrain>().connect<&terrain::on_terrain_update>(this);
@ -87,11 +90,16 @@ void terrain::update(double t, double dt)
// Determine camera node location // Determine camera node location
const auto [x, y, z] = cam.get_translation(); const auto [x, y, z] = cam.get_translation();
quadtree_node_type node_x = static_cast<quadtree_node_type>((x / patch_side_length) + quadtree.resolution / 4);
quadtree_node_type node_y = static_cast<quadtree_node_type>((z / patch_side_length) + quadtree.resolution / 4);
quadtree_node_type node_depth = quadtree.max_depth;
const float node_size = quadtree_node_size[node_depth];
quadtree_node_type node_resolution = quadtree_node_resolution[node_depth];
quadtree_node_type node_x = static_cast<quadtree_node_type>(x / node_size + node_resolution / 2);
quadtree_node_type node_y = static_cast<quadtree_node_type>(z / node_size + node_resolution / 2);
quadtree_node_type node_location = geom::morton::encode<quadtree_node_type>(node_x, node_y); quadtree_node_type node_location = geom::morton::encode<quadtree_node_type>(node_x, node_y);
quadtree.insert(quadtree.node(quadtree.max_depth, node_location));
//quadtree.insert(quadtree.node(node_depth, node_location));
node_stack.push(quadtree.node(node_depth, node_location));
balance_quadtree(); balance_quadtree();
for (const quadtree_node_type& node: quadtree) for (const quadtree_node_type& node: quadtree)
@ -111,21 +119,12 @@ void terrain::update(double t, double dt)
//std::cout << "qsize: " << quadtree.size() << std::endl;
std::size_t qvis = 0;
/// Toggle visibility of terrain scene objects /// Toggle visibility of terrain scene objects
for (auto it = patches.begin(); it != patches.end(); ++it) for (auto it = patches.begin(); it != patches.end(); ++it)
{ {
bool active = (quadtree.contains(it->first) && quadtree.is_leaf(it->first)); bool active = (quadtree.contains(it->first) && quadtree.is_leaf(it->first));
it->second->model_instance->set_active(active); it->second->model_instance->set_active(active);
if (active)
++qvis;
} }
//std::cout << "qvis: " << qvis << std::endl;
} }
void terrain::set_patch_side_length(float length) void terrain::set_patch_side_length(float length)
@ -136,7 +135,6 @@ void terrain::set_patch_side_length(float length)
for (std::size_t i = 0; i <= quadtree_type::max_depth; ++i) for (std::size_t i = 0; i <= quadtree_type::max_depth; ++i)
{ {
quadtree_node_size[i] = std::exp2(quadtree_type::max_depth - i) * patch_side_length; quadtree_node_size[i] = std::exp2(quadtree_type::max_depth - i) * patch_side_length;
//std::cout << quadtree_node_size[i] << std::endl;
} }
} }
@ -245,105 +243,48 @@ void terrain::rebuild_patch_base_mesh()
} }
} }
void terrain::visit_quadtree(const geom::bounding_volume<float>& volume, quadtree_node_type node)
{
const float root_offset = quadtree_node_size[0] * -0.5f;
// Extract node depth
quadtree_type::node_type node_depth = quadtree_type::depth(node);
const float node_size = get_patch_size(node);
const float3 node_center = get_patch_center(node);
// Build node bounds AABB
geom::aabb<float> node_bounds;
node_bounds.min_point =
{
node_center.x() - node_size * 0.5f,
-std::numeric_limits<float>::infinity(),
node_center.z() - node_size * 0.5f
};
node_bounds.max_point =
{
node_bounds.min_point.x() + node_size,
std::numeric_limits<float>::infinity(),
node_bounds.min_point.z() + node_size
};
// If volume intersects node
if (volume.intersects(node_bounds))
{
// Subdivide leaf nodes
if (quadtree.is_leaf(node))
{
quadtree.insert(quadtree_type::child(node, 0));
for (quadtree_node_type i = 0; i < quadtree_type::children_per_node; ++i)
{
quadtree_node_type child = quadtree_type::child(node, i);
if (patches.find(child) == patches.end())
{
patch* child_patch = generate_patch(child);
patches[child] = child_patch;
scene_collection->add_object(child_patch->model_instance);
}
}
}
// Visit children
if (node_depth < quadtree_type::max_depth - 1)
{
for (quadtree_node_type i = 0; i < quadtree_type::children_per_node; ++i)
visit_quadtree(volume, quadtree_type::child(node, i));
}
}
}
void terrain::balance_quadtree() void terrain::balance_quadtree()
{ {
std::unordered_set<quadtree_node_type> nodes;
for (const auto& node: quadtree)
while (!node_stack.empty())
{ {
auto [depth, location] = quadtree.split(node);
quadtree_node_type node = node_stack.top();
node_stack.pop();
// Skip root node
if (depth < 2)
if (quadtree.contains(node))
continue; continue;
quadtree_node_type x, y;
geom::morton::decode(location, x, y);
quadtree.insert(node);
// TODO!!!!
const auto depth = quadtree.depth(node);
if (depth < 2)
continue;
// DONT USE quadtree.resolution, use a depth-specific resolution
const quadtree_node_type parent = quadtree.parent(node);
const quadtree_node_type parent_depth = depth - 1;
const quadtree_node_type parent_resolution = quadtree_node_resolution[parent_depth];
if (!quadtree.is_leaf(node))
for (quadtree_node_type i = 0; i < quadtree.children_per_node; ++i)
{ {
if (x < (quadtree.resolution / 4) - 1)
const auto location = quadtree.location(quadtree.sibling(parent, i));
quadtree_node_type x, y;
geom::morton::decode(location, x, y);
if (x < parent_resolution - 1)
{ {
if (y < (quadtree.resolution / 4) - 1)
nodes.insert(quadtree.node(depth, geom::morton::encode<quadtree_node_type>(x + 1, y + 1)));
if (y < parent_resolution - 1)
node_stack.push(quadtree.node(parent_depth, geom::morton::encode<quadtree_node_type>(x + 1, y + 1)));
if (y > 0) if (y > 0)
nodes.insert(quadtree.node(depth, geom::morton::encode<quadtree_node_type>(x + 1, y - 1)));
node_stack.push(quadtree.node(parent_depth, geom::morton::encode<quadtree_node_type>(x + 1, y - 1)));
} }
if (x > 0) if (x > 0)
{ {
if (y < (quadtree.resolution / 4) - 1)
nodes.insert(quadtree.node(depth, geom::morton::encode<quadtree_node_type>(x - 1, y + 1)));
if (y < parent_resolution - 1)
node_stack.push(quadtree.node(parent_depth, geom::morton::encode<quadtree_node_type>(x - 1, y + 1)));
if (y > 0) if (y > 0)
nodes.insert(quadtree.node(depth, geom::morton::encode<quadtree_node_type>(x - 1, y - 1)));
node_stack.push(quadtree.node(parent_depth, geom::morton::encode<quadtree_node_type>(x - 1, y - 1)));
} }
} }
}
for (const auto& node: nodes)
{
quadtree.insert(node);
} }
} }
@ -392,7 +333,6 @@ geom::mesh* terrain::generate_patch_mesh(quadtree_node_type node) const
// Calculate size of a patch cell // Calculate size of a patch cell
const float cell_size = patch_size / static_cast<float>(patch_subdivisions + 1); const float cell_size = patch_size / static_cast<float>(patch_subdivisions + 1);
const float half_cell_size = cell_size * 0.5f;
// Init patch bounds // Init patch bounds
geom::aabb<float> patch_bounds; geom::aabb<float> patch_bounds;
@ -696,8 +636,6 @@ geom::mesh* terrain::generate_patch_mesh(quadtree_node_type node) const
// Set patch model bounds // Set patch model bounds
patch_model->set_bounds(patch_bounds); patch_model->set_bounds(patch_bounds);
//std::cout << "depth: " << quadtree_type::depth(node) << "; size: " << (patch_bounds.max_point + patch_bounds.min_point) * 0.5f << std::endl;
return patch_model; return patch_model;
} }

+ 4
- 4
src/game/system/terrain.hpp View File

@ -33,6 +33,7 @@
#include "scene/collection.hpp" #include "scene/collection.hpp"
#include "geom/view-frustum.hpp" #include "geom/view-frustum.hpp"
#include <unordered_map> #include <unordered_map>
#include <stack>
namespace game { namespace game {
namespace system { namespace system {
@ -103,10 +104,6 @@ private:
void rebuild_patch_base_mesh(); void rebuild_patch_base_mesh();
void visit_quadtree(const geom::bounding_volume<float>& volume, quadtree_node_type node);
/** /**
* Generates a mesh for a terrain patch given the patch's quadtree node * Generates a mesh for a terrain patch given the patch's quadtree node
*/ */
@ -149,9 +146,12 @@ private:
/// Quadtree describing level of detail /// Quadtree describing level of detail
quadtree_type quadtree; quadtree_type quadtree;
float quadtree_node_size[quadtree_type::max_depth + 1]; float quadtree_node_size[quadtree_type::max_depth + 1];
quadtree_node_type quadtree_node_resolution[quadtree_type::max_depth + 1];
/// Map linking quadtree nodes to terrain patches /// Map linking quadtree nodes to terrain patches
std::unordered_map<quadtree_node_type, patch*> patches; std::unordered_map<quadtree_node_type, patch*> patches;
std::stack<quadtree_node_type> node_stack;
}; };
} // namespace system } // namespace system

+ 9
- 9
src/geom/hyperoctree.hpp View File

@ -172,10 +172,10 @@ public:
static constexpr node_type siblings_per_node = children_per_node - 1; static constexpr node_type siblings_per_node = children_per_node - 1;
/// Resolution in each dimension. /// Resolution in each dimension.
static constexpr node_type resolution = math::compile::exp2<node_type>(max_depth + 1);
static constexpr node_type resolution = math::compile::exp2<node_type>(max_depth);
/// Number of nodes in a full hyperoctree. /// Number of nodes in a full hyperoctree.
static constexpr std::size_t max_node_count = (math::compile::pow<std::size_t>(resolution, N) - 1) / siblings_per_node;
static constexpr std::size_t max_node_count = (math::compile::pow<std::size_t>(resolution * 2, N) - 1) / siblings_per_node;
/// Node identifier of the persistent root node. /// Node identifier of the persistent root node.
static constexpr node_type root = 0; static constexpr node_type root = 0;
@ -204,7 +204,7 @@ public:
* *
* @return Depth of the node. * @return Depth of the node.
*/ */
static constexpr inline node_type depth(node_type node) noexcept
static inline constexpr node_type depth(node_type node) noexcept
{ {
constexpr node_type mask = math::compile::exp2<node_type>(depth_bits) - 1; constexpr node_type mask = math::compile::exp2<node_type>(depth_bits) - 1;
return node & mask; return node & mask;
@ -217,7 +217,7 @@ public:
* *
* @return Morton location code of the node. * @return Morton location code of the node.
*/ */
static constexpr inline node_type location(node_type node) noexcept
static inline constexpr node_type location(node_type node) noexcept
{ {
return node >> ((node_bits - 1) - depth(node) * N); return node >> ((node_bits - 1) - depth(node) * N);
} }
@ -246,7 +246,7 @@ public:
* *
* @warning If @p depth exceeds `max_depth`, the returned node identifier is not valid. * @warning If @p depth exceeds `max_depth`, the returned node identifier is not valid.
*/ */
static constexpr inline node_type node(node_type depth, node_type location) noexcept
static inline constexpr node_type node(node_type depth, node_type location) noexcept
{ {
return (location << ((node_bits - 1) - depth * N)) | depth; return (location << ((node_bits - 1) - depth * N)) | depth;
} }
@ -261,7 +261,7 @@ public:
* *
* @warning If @p depth exceeds the depth of @p node, the returned node identifier is not valid. * @warning If @p depth exceeds the depth of @p node, the returned node identifier is not valid.
*/ */
static constexpr inline node_type ancestor(node_type node, node_type depth) noexcept
static inline constexpr node_type ancestor(node_type node, node_type depth) noexcept
{ {
const node_type mask = (~node_type(0)) << ((node_bits - 1) - depth * N); const node_type mask = (~node_type(0)) << ((node_bits - 1) - depth * N);
return (node & mask) | depth; return (node & mask) | depth;
@ -274,7 +274,7 @@ public:
* *
* @return Identifier of the parent node. * @return Identifier of the parent node.
*/ */
static constexpr inline node_type parent(node_type node) noexcept
static inline constexpr node_type parent(node_type node) noexcept
{ {
return ancestor(node, depth(node) - 1); return ancestor(node, depth(node) - 1);
} }
@ -303,7 +303,7 @@ public:
* *
* @return Identifier of the nth child node. * @return Identifier of the nth child node.
*/ */
static constexpr inline node_type child(node_type node, T n) noexcept
static inline constexpr node_type child(node_type node, T n) noexcept
{ {
return sibling(node + 1, n); return sibling(node + 1, n);
} }
@ -470,7 +470,7 @@ public:
} }
/// Returns the total number of nodes the hyperoctree is capable of containing. /// Returns the total number of nodes the hyperoctree is capable of containing.
consteval std::size_t max_size() const noexcept
constexpr std::size_t max_size() const noexcept
{ {
return max_node_count; return max_node_count;
} }

+ 17
- 14
src/geom/mesh.cpp View File

@ -120,19 +120,19 @@ mesh& mesh::operator=(const mesh& other)
return *this; return *this;
} }
void mesh::clear()
void mesh::clear() noexcept
{ {
// Deallocate vertices // Deallocate vertices
for (mesh::vertex* vertex: vertices) for (mesh::vertex* vertex: vertices)
delete vertex; delete vertex;
// Deallocate edges // Deallocate edges
for (mesh::edge* edge: edges) for (mesh::edge* edge: edges)
{ {
delete edge->symmetric; delete edge->symmetric;
delete edge; delete edge;
} }
// Deallocate faces // Deallocate faces
for (mesh::face* face: faces) for (mesh::face* face: faces)
delete face; delete face;
@ -144,12 +144,15 @@ void mesh::clear()
mesh::vertex* mesh::add_vertex(const float3& position) mesh::vertex* mesh::add_vertex(const float3& position)
{ {
mesh::vertex* vertex = new mesh::vertex();
vertex->edge = nullptr;
vertex->position = position;
vertex->index = vertices.size();
mesh::vertex* vertex = new mesh::vertex
{
vertices.size(),
nullptr,
position
};
vertices.push_back(vertex); vertices.push_back(vertex);
return vertex; return vertex;
} }
@ -158,19 +161,19 @@ mesh::edge* mesh::add_edge(mesh::vertex* a, mesh::vertex* b)
mesh::edge* ab = new mesh::edge(); mesh::edge* ab = new mesh::edge();
mesh::edge* ba = new mesh::edge(); mesh::edge* ba = new mesh::edge();
ab->index = edges.size();
ab->vertex = a; ab->vertex = a;
ab->face = nullptr; ab->face = nullptr;
ab->previous = ba; ab->previous = ba;
ab->next = ba; ab->next = ba;
ab->symmetric = ba; ab->symmetric = ba;
ab->index = edges.size();
ba->index = edges.size();
ba->vertex = b; ba->vertex = b;
ba->face = nullptr; ba->face = nullptr;
ba->previous = ab; ba->previous = ab;
ba->next = ab; ba->next = ab;
ba->symmetric = ab; ba->symmetric = ab;
ba->index = edges.size();
if (!a->edge) if (!a->edge)
{ {
@ -240,21 +243,21 @@ mesh::face* mesh::add_face(const loop& loop)
throw std::runtime_error("Non-manifold mesh 2"); throw std::runtime_error("Non-manifold mesh 2");
} }
} }
// Create face // Create face
mesh::face* face = new mesh::face(); mesh::face* face = new mesh::face();
face->edge = loop[0]; face->edge = loop[0];
face->index = faces.size(); face->index = faces.size();
// Add face // Add face
faces.push_back(face); faces.push_back(face);
// Connect edges to the face // Connect edges to the face
for (mesh::edge* edge: loop) for (mesh::edge* edge: loop)
{ {
edge->face = face; edge->face = face;
} }
return face; return face;
} }

+ 89
- 73
src/geom/mesh.hpp View File

@ -37,45 +37,112 @@ public:
struct edge; struct edge;
struct face; struct face;
/// List of edges which form a face.
/**
* Half-edge mesh vertex, containing its index, a pointer to its parent edge, and its position vector.
*/
struct vertex
{
/// Index of this vertex.
std::size_t index;
/// Pointer to the edge to which this vertex belongs.
mesh::edge* edge;
/// Vertex position.
float3 position;
};
/**
* Half-edge mesh edge, containing its index and pointers to its starting vertex, parent face, and related edges.
*/
struct edge
{
/// Index of this edge.
std::size_t index;
/// Pointer to the vertex at which the edge starts.
mesh::vertex* vertex;
/// Pointer to the face on the left of this edge.
mesh::face* face;
/// Pointer to the previous edge in the parent face.
mesh::edge* previous;
/// Pointer to the next edge in the parent face.
mesh::edge* next;
/// Pointer to the symmetric edge.
mesh::edge* symmetric;
};
/**
* Half-edge mesh face, containing its index and a pointer to its first edge.
*/
struct face
{
/// Index of this face.
std::size_t index;
/// Pointer to the first edge in this face.
mesh::edge* edge;
};
/**
* List of edges which form a face.
*/
typedef std::vector<edge*> loop; typedef std::vector<edge*> loop;
/** /**
* Constructs a mesh. * Constructs a mesh.
*/ */
mesh() = default;
constexpr mesh() noexcept = default;
/// Copy-constructs a mesh.
/**
* Copy-constructs a mesh.
*/
mesh(const mesh& other); mesh(const mesh& other);
/** /**
* Destroys a mesh.
* Destructs a mesh.
*/ */
~mesh();
~mesh() noexcept;
/// Copies another mesh into this mesh.
/**
* Copies another mesh into this mesh.
*
* @param other Mesh to copy.
*
* @return Reference to this mesh.
*/
mesh& operator=(const mesh& other); mesh& operator=(const mesh& other);
/// Removes all vertices, edges, and faces from the mesh.
void clear();
/** /**
* Adds a vertex to the mesh. This vertex initially has a null edge.
* Removes all vertices, edges, and faces from the mesh.
*/
void clear() noexcept;
/**
* Adds a vertex to the mesh.
* *
* @param position Position of the vertex. * @param position Position of the vertex.
*
* @return Pointer to the added vertex. * @return Pointer to the added vertex.
*
* @warning The added vertex will initially have a null edge.
*/ */
mesh::vertex* add_vertex(const float3& position); mesh::vertex* add_vertex(const float3& position);
/** /**
* Adds an edge to the mesh.
* Adds two half edges to the mesh.
*
* @param a Vertex from which the edge originates.
* @param b Vertex at which the edge ends.
* *
* @param a The vertex from which the edge originates.
* @param b The vertex at which the edge ends.
* @return Pointer to the added edge.
* @return Pointer to the half edge `ab`. The symmetric half edge `ba` can be accessed through `ab->symmetric`.
*/ */
mesh::edge* add_edge(mesh::vertex* a, mesh::vertex* b); mesh::edge* add_edge(mesh::vertex* a, mesh::vertex* b);
/** /**
* Adds a face to the mesh. * Adds a face to the mesh.
* *
@ -88,21 +155,21 @@ public:
* @exception std::runtime_error Non-manifold mesh 2. * @exception std::runtime_error Non-manifold mesh 2.
*/ */
mesh::face* add_face(const loop& loop); mesh::face* add_face(const loop& loop);
/** /**
* Removes a face from the mesh. * Removes a face from the mesh.
* *
* @param face Face to be removed. This face will be deallocated after removal. * @param face Face to be removed. This face will be deallocated after removal.
*/ */
void remove_face(mesh::face* face); void remove_face(mesh::face* face);
/** /**
* Removes an edge and all dependent faces from the mesh. * Removes an edge and all dependent faces from the mesh.
* *
* @param edge Edge to be removed. This edge will be deallocated after removal. * @param edge Edge to be removed. This edge will be deallocated after removal.
*/ */
void remove_edge(mesh::edge* edge); void remove_edge(mesh::edge* edge);
/** /**
* Removes a vertex, all dependent edges, and all dependent faces from the mesh. * Removes a vertex, all dependent edges, and all dependent faces from the mesh.
* *
@ -110,66 +177,15 @@ public:
*/ */
void remove_vertex(mesh::vertex* vertex); void remove_vertex(mesh::vertex* vertex);
/// Returns the mesh vertices
/// Returns the mesh vertices.
const std::vector<mesh::vertex*>& get_vertices() const; const std::vector<mesh::vertex*>& get_vertices() const;
/// Returns the mesh edges
/// Returns the mesh edges.
const std::vector<mesh::edge*>& get_edges() const; const std::vector<mesh::edge*>& get_edges() const;
/// Returns the mesh faces
/// Returns the mesh faces.
const std::vector<mesh::face*>& get_faces() const; const std::vector<mesh::face*>& get_faces() const;
/**
* Half-edge vertex which contains its index, a pointer to its parent edge, and its position vector.
*/
struct vertex
{
/// Index of this vertex.
std::size_t index;
/// Pointer to the edge to which this vertex belongs.
mesh::edge* edge;
/// Vertex position.
float3 position;
};
/**
* Half-edge edge which contains its index and pointers to its starting vertex, parent face, and related edges.
*/
struct edge
{
/// Index of this edge.
std::size_t index;
/// Pointer to the vertex at which the edge starts.
mesh::vertex* vertex;
/// Pointer to the face on the left of this edge.
mesh::face* face;
/// Pointer to the previous edge in the parent face.
mesh::edge* previous;
/// Pointer to the next edge in the parent face.
mesh::edge* next;
/// Pointer to the symmetric edge.
mesh::edge* symmetric;
};
/**
* Half-edge face which contains its index and a pointer to its first edge.
*/
struct face
{
/// Index of this face.
std::size_t index;
/// Pointer to the first edge in this face.
mesh::edge* edge;
};
private: private:
mesh::edge* find_free_incident(mesh::vertex* vertex) const; mesh::edge* find_free_incident(mesh::vertex* vertex) const;
mesh::edge* find_free_incident(mesh::edge* start_edge, mesh::edge* end_edge) const; mesh::edge* find_free_incident(mesh::edge* start_edge, mesh::edge* end_edge) const;

+ 5
- 5
src/geom/primitive/intersection.hpp View File

@ -54,7 +54,7 @@ constexpr std::optional intersection(const ray& ray, const hyperplane
} }
template <class T, std::size_t N> template <class T, std::size_t N>
constexpr inline std::optional<T> intersection(const hyperplane<T, N>& hyperplane, const ray<T, N>& ray) noexcept
inline constexpr std::optional<T> intersection(const hyperplane<T, N>& hyperplane, const ray<T, N>& ray) noexcept
{ {
return intersection<T, N>(ray, hyperplane); return intersection<T, N>(ray, hyperplane);
} }
@ -98,7 +98,7 @@ constexpr std::optional> intersection(const ray& ray, con
} }
template <class T, std::size_t N> template <class T, std::size_t N>
constexpr inline std::optional<std::tuple<T, T>> intersection(const hyperrectangle<T, N>& hyperrectangle, const ray<T, N>& ray) noexcept
inline constexpr std::optional<std::tuple<T, T>> intersection(const hyperrectangle<T, N>& hyperrectangle, const ray<T, N>& ray) noexcept
{ {
return intersection<T, N>(ray, hyperrectangle); return intersection<T, N>(ray, hyperrectangle);
} }
@ -145,7 +145,7 @@ std::optional> intersection(const ray& ray, const hypersp
* @return `true` if an intersection occurred, `false` otherwise. * @return `true` if an intersection occurred, `false` otherwise.
*/ */
template <class T, std::size_t N> template <class T, std::size_t N>
constexpr inline bool intersection(const hyperrectangle<T, N>& a, const hyperrectangle<T, N>& b) noexcept
inline constexpr bool intersection(const hyperrectangle<T, N>& a, const hyperrectangle<T, N>& b) noexcept
{ {
return a.intersects(b); return a.intersects(b);
} }
@ -181,7 +181,7 @@ constexpr bool intersection(const hyperrectangle& hyperrectangle, const hy
} }
template <class T, std::size_t N> template <class T, std::size_t N>
constexpr inline bool intersection(const hypersphere<T, N>& hypersphere, const hyperrectangle<T, N>& hyperrectangle) noexcept
inline constexpr bool intersection(const hypersphere<T, N>& hypersphere, const hyperrectangle<T, N>& hyperrectangle) noexcept
{ {
return intersection<T, N>(hyperrectangle, hypersphere); return intersection<T, N>(hyperrectangle, hypersphere);
} }
@ -196,7 +196,7 @@ constexpr inline bool intersection(const hypersphere& hypersphere, const h
* @return `true` if an intersection occurred, `false` otherwise. * @return `true` if an intersection occurred, `false` otherwise.
*/ */
template <class T, std::size_t N> template <class T, std::size_t N>
constexpr inline bool intersection(const hypersphere<T, N>& a, const hypersphere<T, N>& b) noexcept
inline constexpr bool intersection(const hypersphere<T, N>& a, const hypersphere<T, N>& b) noexcept
{ {
return a.intersects(b); return a.intersects(b);
} }

+ 83
- 77
src/math/matrix.hpp View File

@ -42,16 +42,16 @@ namespace math {
template <typename T, std::size_t N, std::size_t M> template <typename T, std::size_t N, std::size_t M>
struct matrix struct matrix
{ {
/// Matrix element data type.
/// Element type.
typedef T element_type; typedef T element_type;
/// Number of matrix columns.
/// Number of columns.
static constexpr std::size_t column_count = N; static constexpr std::size_t column_count = N;
/// Number of matrix rows.
/// Number of rows.
static constexpr std::size_t row_count = M; static constexpr std::size_t row_count = M;
/// Number of matrix elements.
/// Number of elements.
static constexpr std::size_t element_count = column_count * row_count; static constexpr std::size_t element_count = column_count * row_count;
/// Matrix column vector data type. /// Matrix column vector data type.
@ -68,7 +68,7 @@ struct matrix
/// @private /// @private
template <class U, std::size_t... I> template <class U, std::size_t... I>
constexpr inline matrix<U, N, M> type_cast(std::index_sequence<I...>) const noexcept
inline constexpr matrix<U, N, M> type_cast(std::index_sequence<I...>) const noexcept
{ {
return {vector<U, M>(columns[I])...}; return {vector<U, M>(columns[I])...};
} }
@ -81,14 +81,14 @@ struct matrix
* @return Matrix containing the type-casted elements. * @return Matrix containing the type-casted elements.
*/ */
template <class U> template <class U>
constexpr inline explicit operator matrix<U, N, M>() const noexcept
inline constexpr explicit operator matrix<U, N, M>() const noexcept
{ {
return type_cast<U>(std::make_index_sequence<N>{}); return type_cast<U>(std::make_index_sequence<N>{});
} }
/// @private /// @private
template <std::size_t P, std::size_t O, std::size_t... I> template <std::size_t P, std::size_t O, std::size_t... I>
constexpr inline matrix<T, P, O> size_cast(std::index_sequence<I...>) const noexcept
inline constexpr matrix<T, P, O> size_cast(std::index_sequence<I...>) const noexcept
{ {
if constexpr (O == M) if constexpr (O == M)
return {((I < N) ? columns[I] : matrix<T, P, O>::identity()[I]) ...}; return {((I < N) ? columns[I] : matrix<T, P, O>::identity()[I]) ...};
@ -105,7 +105,7 @@ struct matrix
* @return *p* by *o* matrix. * @return *p* by *o* matrix.
*/ */
template <std::size_t P, std::size_t O> template <std::size_t P, std::size_t O>
constexpr inline explicit operator matrix<T, P, O>() const noexcept
inline constexpr explicit operator matrix<T, P, O>() const noexcept
{ {
return size_cast<P, O>(std::make_index_sequence<P>{}); return size_cast<P, O>(std::make_index_sequence<P>{});
} }
@ -123,19 +123,19 @@ struct matrix
* @return Reference to the column vector at index @p i. * @return Reference to the column vector at index @p i.
*/ */
/// @{ /// @{
constexpr inline column_vector_type& operator[](std::size_t i) noexcept
inline constexpr column_vector_type& operator[](std::size_t i) noexcept
{ {
return columns[i]; return columns[i];
} }
constexpr inline const column_vector_type& operator[](std::size_t i) const noexcept
inline constexpr const column_vector_type& operator[](std::size_t i) const noexcept
{ {
return columns[i]; return columns[i];
} }
constexpr inline column_vector_type& column(std::size_t i) noexcept
inline constexpr column_vector_type& column(std::size_t i) noexcept
{ {
return columns[i]; return columns[i];
} }
constexpr inline const column_vector_type& column(std::size_t i) const noexcept
inline constexpr const column_vector_type& column(std::size_t i) const noexcept
{ {
return columns[i]; return columns[i];
} }
@ -145,11 +145,11 @@ struct matrix
* Returns a reference to the first column vector. * Returns a reference to the first column vector.
*/ */
/// @{ /// @{
constexpr inline column_vector_type& front() noexcept
inline constexpr column_vector_type& front() noexcept
{ {
return columns[0]; return columns[0];
} }
constexpr inline const column_vector_type& front() const noexcept
inline constexpr const column_vector_type& front() const noexcept
{ {
return columns[0]; return columns[0];
} }
@ -159,11 +159,11 @@ struct matrix
* Returns a reference to the last column vector. * Returns a reference to the last column vector.
*/ */
/// @{ /// @{
constexpr inline column_vector_type& back() noexcept
inline constexpr column_vector_type& back() noexcept
{ {
return columns[column_count - 1]; return columns[column_count - 1];
} }
constexpr inline const column_vector_type& back() const noexcept
inline constexpr const column_vector_type& back() const noexcept
{ {
return columns[column_count - 1]; return columns[column_count - 1];
} }
@ -182,11 +182,11 @@ struct matrix
* @return Reference to the element at column-major index @p i. * @return Reference to the element at column-major index @p i.
*/ */
/// @{ /// @{
constexpr inline T& element(std::size_t i) noexcept
inline constexpr T& element(std::size_t i) noexcept
{ {
return columns[i / row_count][i % row_count]; return columns[i / row_count][i % row_count];
} }
constexpr inline const T& element(std::size_t i) const noexcept
inline constexpr const T& element(std::size_t i) const noexcept
{ {
return columns[i / row_count][i % row_count]; return columns[i / row_count][i % row_count];
} }
@ -198,11 +198,11 @@ struct matrix
* @warning If matrix::element_type is not a POD type, elements may not be stored contiguously. * @warning If matrix::element_type is not a POD type, elements may not be stored contiguously.
*/ */
/// @{ /// @{
constexpr inline element_type* data() noexcept
inline constexpr element_type* data() noexcept
{ {
return &columns[0][0]; return &columns[0][0];
}; };
constexpr inline const element_type* data() const noexcept
inline constexpr const element_type* data() const noexcept
{ {
return &columns[0][0]; return &columns[0][0];
}; };
@ -217,15 +217,15 @@ struct matrix
* Returns an iterator to the first column vector. * Returns an iterator to the first column vector.
*/ */
/// @{ /// @{
constexpr inline column_vector_type* begin() noexcept
inline constexpr column_vector_type* begin() noexcept
{ {
return columns; return columns;
} }
constexpr inline const column_vector_type* begin() const noexcept
inline constexpr const column_vector_type* begin() const noexcept
{ {
return columns; return columns;
} }
constexpr inline const column_vector_type* cbegin() const noexcept
inline constexpr const column_vector_type* cbegin() const noexcept
{ {
return columns; return columns;
} }
@ -235,15 +235,15 @@ struct matrix
* Returns an iterator to the column vector following the last column vector. * Returns an iterator to the column vector following the last column vector.
*/ */
/// @{ /// @{
constexpr inline column_vector_type* end() noexcept
inline constexpr column_vector_type* end() noexcept
{ {
return columns + column_count; return columns + column_count;
} }
constexpr inline const column_vector_type* end() const noexcept
inline constexpr const column_vector_type* end() const noexcept
{ {
return columns + column_count; return columns + column_count;
} }
constexpr inline const column_vector_type* cend() const noexcept
inline constexpr const column_vector_type* cend() const noexcept
{ {
return columns + column_count; return columns + column_count;
} }
@ -253,15 +253,15 @@ struct matrix
* Returns a reverse iterator to the first column vector of the reversed matrix. * Returns a reverse iterator to the first column vector of the reversed matrix.
*/ */
/// @{ /// @{
constexpr inline std::reverse_iterator<column_vector_type*> rbegin() noexcept
inline constexpr std::reverse_iterator<column_vector_type*> rbegin() noexcept
{ {
return std::reverse_iterator<column_vector_type*>(columns + column_count); return std::reverse_iterator<column_vector_type*>(columns + column_count);
} }
constexpr inline std::reverse_iterator<const column_vector_type*> rbegin() const noexcept
inline constexpr std::reverse_iterator<const column_vector_type*> rbegin() const noexcept
{ {
return std::reverse_iterator<const column_vector_type*>(columns + column_count); return std::reverse_iterator<const column_vector_type*>(columns + column_count);
} }
constexpr inline std::reverse_iterator<const column_vector_type*> crbegin() const noexcept
inline constexpr std::reverse_iterator<const column_vector_type*> crbegin() const noexcept
{ {
return std::reverse_iterator<const column_vector_type*>(columns + column_count); return std::reverse_iterator<const column_vector_type*>(columns + column_count);
} }
@ -271,15 +271,15 @@ struct matrix
* Returns a reverse iterator to the column vector following the last column vector of the reversed matrix. * Returns a reverse iterator to the column vector following the last column vector of the reversed matrix.
*/ */
/// @{ /// @{
constexpr inline std::reverse_iterator<column_vector_type*> rend() noexcept
inline constexpr std::reverse_iterator<column_vector_type*> rend() noexcept
{ {
return std::reverse_iterator<column_vector_type*>(columns); return std::reverse_iterator<column_vector_type*>(columns);
} }
constexpr inline std::reverse_iterator<const column_vector_type*> rend() const noexcept
inline constexpr std::reverse_iterator<const column_vector_type*> rend() const noexcept
{ {
return std::reverse_iterator<const column_vector_type*>(columns); return std::reverse_iterator<const column_vector_type*>(columns);
} }
constexpr inline std::reverse_iterator<const column_vector_type*> crend() const noexcept
inline constexpr std::reverse_iterator<const column_vector_type*> crend() const noexcept
{ {
return std::reverse_iterator<const column_vector_type*>(columns); return std::reverse_iterator<const column_vector_type*>(columns);
} }
@ -293,7 +293,7 @@ struct matrix
/** /**
* Returns the number of elements in the matrix. * Returns the number of elements in the matrix.
*/ */
constexpr inline std::size_t size() const noexcept
inline constexpr std::size_t size() const noexcept
{ {
return element_count; return element_count;
}; };
@ -313,7 +313,7 @@ struct matrix
/// @private /// @private
template <std::size_t... I> template <std::size_t... I>
static constexpr inline matrix one(std::index_sequence<I...>) noexcept
static inline constexpr matrix one(std::index_sequence<I...>) noexcept
{ {
//return {column_vector_type::one() ...}; //return {column_vector_type::one() ...};
@ -331,14 +331,14 @@ struct matrix
/// @private /// @private
template <std::size_t... I> template <std::size_t... I>
static constexpr inline column_vector_type identity_column(std::size_t i, std::index_sequence<I...>) noexcept
static inline constexpr column_vector_type identity_column(std::size_t i, std::index_sequence<I...>) noexcept
{ {
return {(I == i ? T{1} : T{0}) ...}; return {(I == i ? T{1} : T{0}) ...};
} }
/// @private /// @private
template <std::size_t... I> template <std::size_t... I>
static constexpr inline matrix identity(std::index_sequence<I...>) noexcept
static inline constexpr matrix identity(std::index_sequence<I...>) noexcept
{ {
return {identity_column(I, std::make_index_sequence<row_count>{}) ...}; return {identity_column(I, std::make_index_sequence<row_count>{}) ...};
} }
@ -670,7 +670,7 @@ constexpr matrix transpose(const matrix& m) noexcept;
/// @private /// @private
template <class T, std::size_t N, std::size_t M, std::size_t... I> template <class T, std::size_t N, std::size_t M, std::size_t... I>
constexpr inline matrix<T, N, M> add(const matrix<T, N, M>& a, const matrix<T, N, M>& b, std::index_sequence<I...>) noexcept
inline constexpr matrix<T, N, M> add(const matrix<T, N, M>& a, const matrix<T, N, M>& b, std::index_sequence<I...>) noexcept
{ {
return {(a[I] + b[I]) ...}; return {(a[I] + b[I]) ...};
} }
@ -683,7 +683,7 @@ constexpr matrix add(const matrix& a, const matrix& b
/// @private /// @private
template <class T, std::size_t N, std::size_t M, std::size_t... I> template <class T, std::size_t N, std::size_t M, std::size_t... I>
constexpr inline matrix<T, N, M> add(const matrix<T, N, M>& a, T b, std::index_sequence<I...>) noexcept
inline constexpr matrix<T, N, M> add(const matrix<T, N, M>& a, T b, std::index_sequence<I...>) noexcept
{ {
return {(a[I] + b) ...}; return {(a[I] + b) ...};
} }
@ -694,6 +694,7 @@ constexpr matrix add(const matrix& a, T b) noexcept
return add(a, b, std::make_index_sequence<N>{}); return add(a, b, std::make_index_sequence<N>{});
} }
/// @private
template <class T> template <class T>
constexpr T determinant(const matrix<T, 2, 2>& m) noexcept constexpr T determinant(const matrix<T, 2, 2>& m) noexcept
{ {
@ -702,6 +703,7 @@ constexpr T determinant(const matrix& m) noexcept
m[0][1] * m[1][0]; m[0][1] * m[1][0];
} }
/// @private
template <class T> template <class T>
constexpr T determinant(const matrix<T, 3, 3>& m) noexcept constexpr T determinant(const matrix<T, 3, 3>& m) noexcept
{ {
@ -714,6 +716,7 @@ constexpr T determinant(const matrix& m) noexcept
m[0][2] * m[1][1] * m[2][0]; m[0][2] * m[1][1] * m[2][0];
} }
/// @private
template <class T> template <class T>
constexpr T determinant(const matrix<T, 4, 4>& m) noexcept constexpr T determinant(const matrix<T, 4, 4>& m) noexcept
{ {
@ -734,7 +737,7 @@ constexpr T determinant(const matrix& m) noexcept
/// @private /// @private
template <class T, std::size_t N, std::size_t M, std::size_t... I> template <class T, std::size_t N, std::size_t M, std::size_t... I>
constexpr inline matrix<T, N, M> componentwise_mul(const matrix<T, N, M>& a, const matrix<T, N, M>& b, std::index_sequence<I...>) noexcept
inline constexpr matrix<T, N, M> componentwise_mul(const matrix<T, N, M>& a, const matrix<T, N, M>& b, std::index_sequence<I...>) noexcept
{ {
return {(a[I] * b[I]) ...}; return {(a[I] * b[I]) ...};
} }
@ -747,7 +750,7 @@ constexpr matrix componentwise_mul(const matrix& a, const matr
/// @private /// @private
template <class T, std::size_t N, std::size_t M, std::size_t... I> template <class T, std::size_t N, std::size_t M, std::size_t... I>
constexpr inline matrix<T, N, M> div(const matrix<T, N, M>& a, const matrix<T, N, M>& b, std::index_sequence<I...>) noexcept
inline constexpr matrix<T, N, M> div(const matrix<T, N, M>& a, const matrix<T, N, M>& b, std::index_sequence<I...>) noexcept
{ {
return {(a[I] / b[I]) ...}; return {(a[I] / b[I]) ...};
} }
@ -760,7 +763,7 @@ constexpr matrix div(const matrix& a, const matrix& b
/// @private /// @private
template <class T, std::size_t N, std::size_t M, std::size_t... I> template <class T, std::size_t N, std::size_t M, std::size_t... I>
constexpr inline matrix<T, N, M> div(const matrix<T, N, M>& a, T b, std::index_sequence<I...>) noexcept
inline constexpr matrix<T, N, M> div(const matrix<T, N, M>& a, T b, std::index_sequence<I...>) noexcept
{ {
return {(a[I] / b) ...}; return {(a[I] / b) ...};
} }
@ -773,7 +776,7 @@ constexpr matrix div(const matrix& a, T b) noexcept
/// @private /// @private
template <class T, std::size_t N, std::size_t M, std::size_t... I> template <class T, std::size_t N, std::size_t M, std::size_t... I>
constexpr inline matrix<T, N, M> div(T a, const matrix<T, N, M>& b, std::index_sequence<I...>) noexcept
inline constexpr matrix<T, N, M> div(T a, const matrix<T, N, M>& b, std::index_sequence<I...>) noexcept
{ {
return {(a / b[I]) ...}; return {(a / b[I]) ...};
} }
@ -785,33 +788,34 @@ constexpr matrix div(T a, const matrix& b) noexcept
} }
template<std::size_t I, class T, std::size_t N, std::size_t M> template<std::size_t I, class T, std::size_t N, std::size_t M>
constexpr inline typename matrix<T, N, M>::column_vector_type& get(math::matrix<T, N, M>& m) noexcept
inline constexpr typename matrix<T, N, M>::column_vector_type& get(math::matrix<T, N, M>& m) noexcept
{ {
static_assert(I < N); static_assert(I < N);
return m.columns[I]; return m.columns[I];
} }
template<std::size_t I, class T, std::size_t N, std::size_t M> template<std::size_t I, class T, std::size_t N, std::size_t M>
constexpr inline typename matrix<T, N, M>::column_vector_type&& get(math::matrix<T, N, M>&& m) noexcept
inline constexpr typename matrix<T, N, M>::column_vector_type&& get(math::matrix<T, N, M>&& m) noexcept
{ {
static_assert(I < N); static_assert(I < N);
return std::move(m.columns[I]); return std::move(m.columns[I]);
} }
template<std::size_t I, class T, std::size_t N, std::size_t M> template<std::size_t I, class T, std::size_t N, std::size_t M>
constexpr inline const typename matrix<T, N, M>::column_vector_type& get(const math::matrix<T, N, M>& m) noexcept
inline constexpr const typename matrix<T, N, M>::column_vector_type& get(const math::matrix<T, N, M>& m) noexcept
{ {
static_assert(I < N); static_assert(I < N);
return m.columns[I]; return m.columns[I];
} }
template<std::size_t I, class T, std::size_t N, std::size_t M> template<std::size_t I, class T, std::size_t N, std::size_t M>
constexpr inline const typename matrix<T, N, M>::column_vector_type&& get(const math::matrix<T, N, M>&& m) noexcept
inline constexpr const typename matrix<T, N, M>::column_vector_type&& get(const math::matrix<T, N, M>&& m) noexcept
{ {
static_assert(I < N); static_assert(I < N);
return std::move(m.columns[I]); return std::move(m.columns[I]);
} }
/// @private
template <class T> template <class T>
constexpr matrix<T, 2, 2> inverse(const matrix<T, 2, 2>& m) noexcept constexpr matrix<T, 2, 2> inverse(const matrix<T, 2, 2>& m) noexcept
{ {
@ -826,6 +830,7 @@ constexpr matrix inverse(const matrix& m) noexcept
}; };
} }
/// @private
template <class T> template <class T>
constexpr matrix<T, 3, 3> inverse(const matrix<T, 3, 3>& m) noexcept constexpr matrix<T, 3, 3> inverse(const matrix<T, 3, 3>& m) noexcept
{ {
@ -847,6 +852,7 @@ constexpr matrix inverse(const matrix& m) noexcept
}; };
} }
/// @private
template <class T> template <class T>
constexpr matrix<T, 4, 4> inverse(const matrix<T, 4, 4>& m) noexcept constexpr matrix<T, 4, 4> inverse(const matrix<T, 4, 4>& m) noexcept
{ {
@ -915,7 +921,7 @@ constexpr matrix mul(const matrix& a, const matrix& b
/// @private /// @private
template <class T, std::size_t N, std::size_t M, std::size_t... I> template <class T, std::size_t N, std::size_t M, std::size_t... I>
constexpr inline matrix<T, N, M> mul(const matrix<T, N, M>& a, T b, std::index_sequence<I...>) noexcept
inline constexpr matrix<T, N, M> mul(const matrix<T, N, M>& a, T b, std::index_sequence<I...>) noexcept
{ {
return {(a[I] * b) ...}; return {(a[I] * b) ...};
} }
@ -928,7 +934,7 @@ constexpr matrix mul(const matrix& a, T b) noexcept
/// @private /// @private
template <typename T, std::size_t N, std::size_t M, std::size_t... I> template <typename T, std::size_t N, std::size_t M, std::size_t... I>
constexpr inline typename matrix<T, N, M>::column_vector_type mul(const matrix<T, N, M>& a, const typename matrix<T, N, M>::row_vector_type& b, std::index_sequence<I...>) noexcept
inline constexpr typename matrix<T, N, M>::column_vector_type mul(const matrix<T, N, M>& a, const typename matrix<T, N, M>::row_vector_type& b, std::index_sequence<I...>) noexcept
{ {
return ((a[I] * b[I]) + ...); return ((a[I] * b[I]) + ...);
} }
@ -941,7 +947,7 @@ constexpr typename matrix::column_vector_type mul(const matrix
/// @private /// @private
template <typename T, std::size_t N, std::size_t M, std::size_t... I> template <typename T, std::size_t N, std::size_t M, std::size_t... I>
constexpr inline typename matrix<T, N, M>::row_vector_type mul(const typename matrix<T, N, M>::column_vector_type& a, const matrix<T, N, M>& b, std::index_sequence<I...>) noexcept
inline constexpr typename matrix<T, N, M>::row_vector_type mul(const typename matrix<T, N, M>::column_vector_type& a, const matrix<T, N, M>& b, std::index_sequence<I...>) noexcept
{ {
return {dot(a, b[I]) ...}; return {dot(a, b[I]) ...};
} }
@ -1029,7 +1035,7 @@ constexpr matrix scale(const matrix& m, const vector& v)
/// @private /// @private
template <class T, std::size_t N, std::size_t M, std::size_t... I> template <class T, std::size_t N, std::size_t M, std::size_t... I>
constexpr inline matrix<T, N, M> sub(const matrix<T, N, M>& a, const matrix<T, N, M>& b, std::index_sequence<I...>) noexcept
inline constexpr matrix<T, N, M> sub(const matrix<T, N, M>& a, const matrix<T, N, M>& b, std::index_sequence<I...>) noexcept
{ {
return {(a[I] - b[I]) ...}; return {(a[I] - b[I]) ...};
} }
@ -1042,7 +1048,7 @@ constexpr matrix sub(const matrix& a, const matrix& b
/// @private /// @private
template <class T, std::size_t N, std::size_t M, std::size_t... I> template <class T, std::size_t N, std::size_t M, std::size_t... I>
constexpr inline matrix<T, N, M> sub(const matrix<T, N, M>& a, T b, std::index_sequence<I...>) noexcept
inline constexpr matrix<T, N, M> sub(const matrix<T, N, M>& a, T b, std::index_sequence<I...>) noexcept
{ {
return {(a[I] - b) ...}; return {(a[I] - b) ...};
} }
@ -1055,7 +1061,7 @@ constexpr matrix sub(const matrix& a, T b) noexcept
/// @private /// @private
template <class T, std::size_t N, std::size_t M, std::size_t... I> template <class T, std::size_t N, std::size_t M, std::size_t... I>
constexpr inline matrix<T, N, M> sub(T a, const matrix<T, N, M>& b, std::index_sequence<I...>) noexcept
inline constexpr matrix<T, N, M> sub(T a, const matrix<T, N, M>& b, std::index_sequence<I...>) noexcept
{ {
return {(a - b[I]) ...}; return {(a - b[I]) ...};
} }
@ -1068,7 +1074,7 @@ constexpr matrix sub(T a, const matrix& b) noexcept
/// @private /// @private
template <class T, std::size_t N, std::size_t... I> template <class T, std::size_t N, std::size_t... I>
constexpr inline T trace(const matrix<T, N, N>& m, std::index_sequence<I...>) noexcept
inline constexpr T trace(const matrix<T, N, N>& m, std::index_sequence<I...>) noexcept
{ {
return ((m[I][I]) + ...); return ((m[I][I]) + ...);
} }
@ -1093,14 +1099,14 @@ constexpr matrix translate(const matrix& m, const vector
/// @private /// @private
template <typename T, std::size_t N, std::size_t M, std::size_t... I> template <typename T, std::size_t N, std::size_t M, std::size_t... I>
constexpr inline typename matrix<T, M, N>::column_vector_type transpose_column(const matrix<T, N, M>& m, std::size_t i, std::index_sequence<I...>) noexcept
inline constexpr typename matrix<T, M, N>::column_vector_type transpose_column(const matrix<T, N, M>& m, std::size_t i, std::index_sequence<I...>) noexcept
{ {
return {m[I][i] ...}; return {m[I][i] ...};
} }
/// @private /// @private
template <typename T, std::size_t N, std::size_t M, std::size_t... I> template <typename T, std::size_t N, std::size_t M, std::size_t... I>
constexpr inline matrix<T, M, N> transpose(const matrix<T, N, M>& m, std::index_sequence<I...>) noexcept
inline constexpr matrix<T, M, N> transpose(const matrix<T, N, M>& m, std::index_sequence<I...>) noexcept
{ {
return {transpose_column(m, I, std::make_index_sequence<N>{}) ...}; return {transpose_column(m, I, std::make_index_sequence<N>{}) ...};
} }
@ -1115,7 +1121,7 @@ namespace operators {
/// @copydoc add(const matrix<T, N, M>&, const matrix<T, N, M>&) /// @copydoc add(const matrix<T, N, M>&, const matrix<T, N, M>&)
template <class T, std::size_t N, std::size_t M> template <class T, std::size_t N, std::size_t M>
constexpr inline matrix<T, N, M> operator+(const matrix<T, N, M>& a, const matrix<T, N, M>& b) noexcept
inline constexpr matrix<T, N, M> operator+(const matrix<T, N, M>& a, const matrix<T, N, M>& b) noexcept
{ {
return add(a, b); return add(a, b);
} }
@ -1123,12 +1129,12 @@ constexpr inline matrix operator+(const matrix& a, const matri
/// @copydoc add(const matrix<T, N, M>&, T) /// @copydoc add(const matrix<T, N, M>&, T)
/// @{ /// @{
template <class T, std::size_t N, std::size_t M> template <class T, std::size_t N, std::size_t M>
constexpr inline matrix<T, N, M> operator+(const matrix<T, N, M>& a, T b) noexcept
inline constexpr matrix<T, N, M> operator+(const matrix<T, N, M>& a, T b) noexcept
{ {
return add(a, b); return add(a, b);
} }
template <class T, std::size_t N, std::size_t M> template <class T, std::size_t N, std::size_t M>
constexpr inline matrix<T, N, M> operator+(T a, const matrix<T, N, M>& b) noexcept
inline constexpr matrix<T, N, M> operator+(T a, const matrix<T, N, M>& b) noexcept
{ {
return add(b, a); return add(b, a);
} }
@ -1136,28 +1142,28 @@ constexpr inline matrix operator+(T a, const matrix& b) noexce
/// @copydoc div(const matrix<T, N, M>&, const matrix<T, N, M>&) /// @copydoc div(const matrix<T, N, M>&, const matrix<T, N, M>&)
template <class T, std::size_t N, std::size_t M> template <class T, std::size_t N, std::size_t M>
constexpr inline matrix<T, N, M> operator/(const matrix<T, N, M>& a, const matrix<T, N, M>& b) noexcept
inline constexpr matrix<T, N, M> operator/(const matrix<T, N, M>& a, const matrix<T, N, M>& b) noexcept
{ {
return div(a, b); return div(a, b);
} }
/// @copydoc div(const matrix<T, N, M>&, T) /// @copydoc div(const matrix<T, N, M>&, T)
template <class T, std::size_t N, std::size_t M> template <class T, std::size_t N, std::size_t M>
constexpr inline matrix<T, N, M> operator/(const matrix<T, N, M>& a, T b) noexcept
inline constexpr matrix<T, N, M> operator/(const matrix<T, N, M>& a, T b) noexcept
{ {
return div(a, b); return div(a, b);
} }
/// @copydoc div(T, const matrix<T, N, M>&) /// @copydoc div(T, const matrix<T, N, M>&)
template <class T, std::size_t N, std::size_t M> template <class T, std::size_t N, std::size_t M>
constexpr inline matrix<T, N, M> operator/(T a, const matrix<T, N, M>& b) noexcept
inline constexpr matrix<T, N, M> operator/(T a, const matrix<T, N, M>& b) noexcept
{ {
return div(a, b); return div(a, b);
} }
/// @copydoc mul(const matrix<T, N, M>&, const matrix<T, P, N>&) /// @copydoc mul(const matrix<T, N, M>&, const matrix<T, P, N>&)
template <typename T, std::size_t N, std::size_t M, std::size_t P> template <typename T, std::size_t N, std::size_t M, std::size_t P>
constexpr inline matrix<T, P, M> operator*(const matrix<T, N, M>& a, const matrix<T, P, N>& b) noexcept
inline constexpr matrix<T, P, M> operator*(const matrix<T, N, M>& a, const matrix<T, P, N>& b) noexcept
{ {
return mul(a, b); return mul(a, b);
} }
@ -1165,12 +1171,12 @@ constexpr inline matrix operator*(const matrix& a, const matri
/// @copydoc mul(const matrix<T, N, M>&, T) /// @copydoc mul(const matrix<T, N, M>&, T)
/// @{ /// @{
template <class T, std::size_t N, std::size_t M> template <class T, std::size_t N, std::size_t M>
constexpr inline matrix<T, N, M> operator*(const matrix<T, N, M>& a, T b) noexcept
inline constexpr matrix<T, N, M> operator*(const matrix<T, N, M>& a, T b) noexcept
{ {
return mul(a, b); return mul(a, b);
} }
template <class T, std::size_t N, std::size_t M> template <class T, std::size_t N, std::size_t M>
constexpr inline matrix<T, N, M> operator*(T a, const matrix<T, N, M>& b) noexcept
inline constexpr matrix<T, N, M> operator*(T a, const matrix<T, N, M>& b) noexcept
{ {
return mul(b, a); return mul(b, a);
} }
@ -1178,35 +1184,35 @@ constexpr inline matrix operator*(T a, const matrix& b) noexce
/// @copydoc mul(const matrix<T, N, M>&, const typename matrix<T, N, M>::row_vector_type&) /// @copydoc mul(const matrix<T, N, M>&, const typename matrix<T, N, M>::row_vector_type&)
template <typename T, std::size_t N, std::size_t M> template <typename T, std::size_t N, std::size_t M>
constexpr inline typename matrix<T, N, M>::column_vector_type operator*(const matrix<T, N, M>& a, const typename matrix<T, N, M>::row_vector_type& b) noexcept
inline constexpr typename matrix<T, N, M>::column_vector_type operator*(const matrix<T, N, M>& a, const typename matrix<T, N, M>::row_vector_type& b) noexcept
{ {
return mul(a, b); return mul(a, b);
} }
/// @copydoc mul(const typename matrix<T, N, M>::column_vector_type&, const matrix<T, N, M>&) /// @copydoc mul(const typename matrix<T, N, M>::column_vector_type&, const matrix<T, N, M>&)
template <typename T, std::size_t N, std::size_t M> template <typename T, std::size_t N, std::size_t M>
constexpr inline typename matrix<T, N, M>::row_vector_type operator*(const typename matrix<T, N, M>::column_vector_type& a, const matrix<T, N, M>& b) noexcept
inline constexpr typename matrix<T, N, M>::row_vector_type operator*(const typename matrix<T, N, M>::column_vector_type& a, const matrix<T, N, M>& b) noexcept
{ {
return mul(a, b); return mul(a, b);
} }
/// @copydoc sub(const matrix<T, N, M>&, const matrix<T, N, M>&) /// @copydoc sub(const matrix<T, N, M>&, const matrix<T, N, M>&)
template <class T, std::size_t N, std::size_t M> template <class T, std::size_t N, std::size_t M>
constexpr inline matrix<T, N, M> operator-(const matrix<T, N, M>& a, const matrix<T, N, M>& b) noexcept
inline constexpr matrix<T, N, M> operator-(const matrix<T, N, M>& a, const matrix<T, N, M>& b) noexcept
{ {
return sub(a, b); return sub(a, b);
} }
/// @copydoc sub(const matrix<T, N, M>&, T) /// @copydoc sub(const matrix<T, N, M>&, T)
template <class T, std::size_t N, std::size_t M> template <class T, std::size_t N, std::size_t M>
constexpr inline matrix<T, N, M> operator-(const matrix<T, N, M>& a, T b) noexcept
inline constexpr matrix<T, N, M> operator-(const matrix<T, N, M>& a, T b) noexcept
{ {
return sub(a, b); return sub(a, b);
} }
/// @copydoc sub(T, const matrix<T, N, M>&) /// @copydoc sub(T, const matrix<T, N, M>&)
template <class T, std::size_t N, std::size_t M> template <class T, std::size_t N, std::size_t M>
constexpr inline matrix<T, N, M> operator-(T a, const matrix<T, N, M>& b) noexcept
inline constexpr matrix<T, N, M> operator-(T a, const matrix<T, N, M>& b) noexcept
{ {
return sub(a, b); return sub(a, b);
} }
@ -1221,12 +1227,12 @@ constexpr inline matrix operator-(T a, const matrix& b) noexce
*/ */
/// @{ /// @{
template <class T, std::size_t N, std::size_t M> template <class T, std::size_t N, std::size_t M>
constexpr inline matrix<T, N, M>& operator+=(matrix<T, N, M>& a, const matrix<T, N, M>& b) noexcept
inline constexpr matrix<T, N, M>& operator+=(matrix<T, N, M>& a, const matrix<T, N, M>& b) noexcept
{ {
return (a = a + b); return (a = a + b);
} }
template <class T, std::size_t N, std::size_t M> template <class T, std::size_t N, std::size_t M>
constexpr inline matrix<T, N, M>& operator+=(matrix<T, N, M>& a, T b) noexcept
inline constexpr matrix<T, N, M>& operator+=(matrix<T, N, M>& a, T b) noexcept
{ {
return (a = a + b); return (a = a + b);
} }
@ -1242,12 +1248,12 @@ constexpr inline matrix& operator+=(matrix& a, T b) noexcept
*/ */
/// @{ /// @{
template <class T, std::size_t N, std::size_t M> template <class T, std::size_t N, std::size_t M>
constexpr inline matrix<T, N, M>& operator-=(matrix<T, N, M>& a, const matrix<T, N, M>& b) noexcept
inline constexpr matrix<T, N, M>& operator-=(matrix<T, N, M>& a, const matrix<T, N, M>& b) noexcept
{ {
return (a = a - b); return (a = a - b);
} }
template <class T, std::size_t N, std::size_t M> template <class T, std::size_t N, std::size_t M>
constexpr inline matrix<T, N, M>& operator-=(matrix<T, N, M>& a, T b) noexcept
inline constexpr matrix<T, N, M>& operator-=(matrix<T, N, M>& a, T b) noexcept
{ {
return (a = a - b); return (a = a - b);
} }
@ -1263,12 +1269,12 @@ constexpr inline matrix& operator-=(matrix& a, T b) noexcept
*/ */
/// @{ /// @{
template <class T, std::size_t N> template <class T, std::size_t N>
constexpr inline matrix<T, N, N>& operator*=(matrix<T, N, N>& a, const matrix<T, N, N>& b) noexcept
inline constexpr matrix<T, N, N>& operator*=(matrix<T, N, N>& a, const matrix<T, N, N>& b) noexcept
{ {
return (a = a * b); return (a = a * b);
} }
template <class T, std::size_t N, std::size_t M> template <class T, std::size_t N, std::size_t M>
constexpr inline matrix<T, N, M>& operator*=(matrix<T, N, M>& a, T b) noexcept
inline constexpr matrix<T, N, M>& operator*=(matrix<T, N, M>& a, T b) noexcept
{ {
return (a = a * b); return (a = a * b);
} }
@ -1284,12 +1290,12 @@ constexpr inline matrix& operator*=(matrix& a, T b) noexcept
*/ */
/// @{ /// @{
template <class T, std::size_t N, std::size_t M> template <class T, std::size_t N, std::size_t M>
constexpr inline matrix<T, N, M>& operator/=(matrix<T, N, M>& a, const matrix<T, N, M>& b) noexcept
inline constexpr matrix<T, N, M>& operator/=(matrix<T, N, M>& a, const matrix<T, N, M>& b) noexcept
{ {
return (a = a / b); return (a = a / b);
} }
template <class T, std::size_t N, std::size_t M> template <class T, std::size_t N, std::size_t M>
constexpr inline matrix<T, N, M>& operator/=(matrix<T, N, M>& a, T b) noexcept
inline constexpr matrix<T, N, M>& operator/=(matrix<T, N, M>& a, T b) noexcept
{ {
return (a = a / b); return (a = a / b);
} }

+ 48
- 48
src/math/quaternion.hpp View File

@ -54,11 +54,11 @@ struct quaternion
/// Returns a reference to the quaternion real part. /// Returns a reference to the quaternion real part.
/// @{ /// @{
constexpr inline scalar_type& w() noexcept
inline constexpr scalar_type& w() noexcept
{ {
return r; return r;
} }
constexpr inline const scalar_type& w() const noexcept
inline constexpr const scalar_type& w() const noexcept
{ {
return r; return r;
} }
@ -66,11 +66,11 @@ struct quaternion
/// Returns a reference to the first element of the quaternion imaginary part. /// Returns a reference to the first element of the quaternion imaginary part.
/// @{ /// @{
constexpr inline scalar_type& x() noexcept
inline constexpr scalar_type& x() noexcept
{ {
return i.x(); return i.x();
} }
constexpr inline const scalar_type& x() const noexcept
inline constexpr const scalar_type& x() const noexcept
{ {
return i.x(); return i.x();
} }
@ -78,11 +78,11 @@ struct quaternion
/// Returns a reference to the second element of the quaternion imaginary part. /// Returns a reference to the second element of the quaternion imaginary part.
/// @{ /// @{
constexpr inline scalar_type& y() noexcept
inline constexpr scalar_type& y() noexcept
{ {
return i.y(); return i.y();
} }
constexpr inline const scalar_type& y() const noexcept
inline constexpr const scalar_type& y() const noexcept
{ {
return i.y(); return i.y();
} }
@ -90,11 +90,11 @@ struct quaternion
/// Returns a reference to the third element of the quaternion imaginary part. /// Returns a reference to the third element of the quaternion imaginary part.
/// @{ /// @{
constexpr inline scalar_type& z() noexcept
inline constexpr scalar_type& z() noexcept
{ {
return i.z(); return i.z();
} }
constexpr inline const scalar_type& z() const noexcept
inline constexpr const scalar_type& z() const noexcept
{ {
return i.z(); return i.z();
} }
@ -143,7 +143,7 @@ struct quaternion
* @return Type-casted quaternion. * @return Type-casted quaternion.
*/ */
template <class U> template <class U>
constexpr inline explicit operator quaternion<U>() const noexcept
inline constexpr explicit operator quaternion<U>() const noexcept
{ {
return {static_cast<U>(r), vector<U, 3>(i)}; return {static_cast<U>(r), vector<U, 3>(i)};
} }
@ -178,7 +178,7 @@ struct quaternion
* *
* @return Vector containing the real and imaginary parts of the quaternion. * @return Vector containing the real and imaginary parts of the quaternion.
*/ */
constexpr inline explicit operator vector<T, 4>() const noexcept
inline constexpr explicit operator vector<T, 4>() const noexcept
{ {
return {r, i[0], i[1], i[2]}; return {r, i[0], i[1], i[2]};
} }
@ -479,43 +479,43 @@ template
quaternion<T> quaternion_cast(const matrix<T, 3, 3>& m); quaternion<T> quaternion_cast(const matrix<T, 3, 3>& m);
template <class T> template <class T>
constexpr inline quaternion<T> add(const quaternion<T>& a, const quaternion<T>& b) noexcept
inline constexpr quaternion<T> add(const quaternion<T>& a, const quaternion<T>& b) noexcept
{ {
return {a.r + b.r, a.i + b.i}; return {a.r + b.r, a.i + b.i};
} }
template <class T> template <class T>
constexpr inline quaternion<T> add(const quaternion<T>& a, T b) noexcept
inline constexpr quaternion<T> add(const quaternion<T>& a, T b) noexcept
{ {
return {a.r + b, a.i + b}; return {a.r + b, a.i + b};
} }
template <class T> template <class T>
constexpr inline quaternion<T> conjugate(const quaternion<T>& q) noexcept
inline constexpr quaternion<T> conjugate(const quaternion<T>& q) noexcept
{ {
return {q.r, -q.i}; return {q.r, -q.i};
} }
template <class T> template <class T>
constexpr inline T dot(const quaternion<T>& a, const quaternion<T>& b) noexcept
inline constexpr T dot(const quaternion<T>& a, const quaternion<T>& b) noexcept
{ {
return a.r * b.r + dot(a.i, b.i); return a.r * b.r + dot(a.i, b.i);
} }
template <class T> template <class T>
constexpr inline quaternion<T> div(const quaternion<T>& a, const quaternion<T>& b) noexcept
inline constexpr quaternion<T> div(const quaternion<T>& a, const quaternion<T>& b) noexcept
{ {
return {a.r / b.r, a.i / b.i}; return {a.r / b.r, a.i / b.i};
} }
template <class T> template <class T>
constexpr inline quaternion<T> div(const quaternion<T>& a, T b) noexcept
inline constexpr quaternion<T> div(const quaternion<T>& a, T b) noexcept
{ {
return {a.r / b, a.i / b}; return {a.r / b, a.i / b};
} }
template <class T> template <class T>
constexpr inline quaternion<T> div(T a, const quaternion<T>& b) noexcept
inline constexpr quaternion<T> div(T a, const quaternion<T>& b) noexcept
{ {
return {a / b.r, a / b.i}; return {a / b.r, a / b.i};
} }
@ -533,7 +533,7 @@ inline T length(const quaternion& q)
} }
template <class T> template <class T>
constexpr inline quaternion<T> lerp(const quaternion<T>& a, const quaternion<T>& b, T t) noexcept
inline constexpr quaternion<T> lerp(const quaternion<T>& a, const quaternion<T>& b, T t) noexcept
{ {
return return
{ {
@ -572,7 +572,7 @@ constexpr quaternion mul(const quaternion& a, const quaternion& b) noex
} }
template <class T> template <class T>
constexpr inline quaternion<T> mul(const quaternion<T>& a, T b) noexcept
inline constexpr quaternion<T> mul(const quaternion<T>& a, T b) noexcept
{ {
return {a.r * b, a.i * b}; return {a.r * b, a.i * b};
} }
@ -584,13 +584,13 @@ constexpr vector mul(const quaternion& a, const vector& b) noexce
} }
template <class T> template <class T>
constexpr inline vector<T, 3> mul(const vector<T, 3>& a, const quaternion<T>& b) noexcept
inline constexpr vector<T, 3> mul(const vector<T, 3>& a, const quaternion<T>& b) noexcept
{ {
return mul(conjugate(b), a); return mul(conjugate(b), a);
} }
template <class T> template <class T>
constexpr inline quaternion<T> negate(const quaternion<T>& q) noexcept
inline constexpr quaternion<T> negate(const quaternion<T>& q) noexcept
{ {
return {-q.r, -q.i}; return {-q.r, -q.i};
} }
@ -639,25 +639,25 @@ quaternion slerp(const quaternion& a, const quaternion& b, T t, T error
} }
template <class T> template <class T>
constexpr inline T sqr_length(const quaternion<T>& q) noexcept
inline constexpr T sqr_length(const quaternion<T>& q) noexcept
{ {
return q.r * q.r + sqr_length(q.i); return q.r * q.r + sqr_length(q.i);
} }
template <class T> template <class T>
constexpr inline quaternion<T> sub(const quaternion<T>& a, const quaternion<T>& b) noexcept
inline constexpr quaternion<T> sub(const quaternion<T>& a, const quaternion<T>& b) noexcept
{ {
return {a.r - b.r, a.i - b.i}; return {a.r - b.r, a.i - b.i};
} }
template <class T> template <class T>
constexpr inline quaternion<T> sub(const quaternion<T>& a, T b) noexcept
inline constexpr quaternion<T> sub(const quaternion<T>& a, T b) noexcept
{ {
return {a.r - b, a.i - b}; return {a.r - b, a.i - b};
} }
template <class T> template <class T>
constexpr inline quaternion<T> sub(T a, const quaternion<T>& b) noexcept
inline constexpr quaternion<T> sub(T a, const quaternion<T>& b) noexcept
{ {
return {a - b.r, a - b.i}; return {a - b.r, a - b.i};
} }
@ -742,7 +742,7 @@ namespace operators {
/// @copydoc add(const quaternion<T>&, const quaternion<T>&) /// @copydoc add(const quaternion<T>&, const quaternion<T>&)
template <class T> template <class T>
constexpr inline quaternion<T> operator+(const quaternion<T>& a, const quaternion<T>& b) noexcept
inline constexpr quaternion<T> operator+(const quaternion<T>& a, const quaternion<T>& b) noexcept
{ {
return add(a, b); return add(a, b);
} }
@ -750,12 +750,12 @@ constexpr inline quaternion operator+(const quaternion& a, const quaternio
/// @copydoc add(const quaternion<T>&, T) /// @copydoc add(const quaternion<T>&, T)
/// @{ /// @{
template <class T> template <class T>
constexpr inline quaternion<T> operator+(const quaternion<T>& a, T b) noexcept
inline constexpr quaternion<T> operator+(const quaternion<T>& a, T b) noexcept
{ {
return add(a, b); return add(a, b);
} }
template <class T> template <class T>
constexpr inline quaternion<T> operator+(T a, const quaternion<T>& b) noexcept
inline constexpr quaternion<T> operator+(T a, const quaternion<T>& b) noexcept
{ {
return add(b, a); return add(b, a);
} }
@ -763,28 +763,28 @@ constexpr inline quaternion operator+(T a, const quaternion& b) noexcept
/// @copydoc div(const quaternion<T>&, const quaternion<T>&) /// @copydoc div(const quaternion<T>&, const quaternion<T>&)
template <class T> template <class T>
constexpr inline quaternion<T> operator/(const quaternion<T>& a, const quaternion<T>& b) noexcept
inline constexpr quaternion<T> operator/(const quaternion<T>& a, const quaternion<T>& b) noexcept
{ {
return div(a, b); return div(a, b);
} }
/// @copydoc div(const quaternion<T>&, T) /// @copydoc div(const quaternion<T>&, T)
template <class T> template <class T>
constexpr inline quaternion<T> operator/(const quaternion<T>& a, T b) noexcept
inline constexpr quaternion<T> operator/(const quaternion<T>& a, T b) noexcept
{ {
return div(a, b); return div(a, b);
} }
/// @copydoc div(T, const quaternion<T>&) /// @copydoc div(T, const quaternion<T>&)
template <class T> template <class T>
constexpr inline quaternion<T> operator/(T a, const quaternion<T>& b) noexcept
inline constexpr quaternion<T> operator/(T a, const quaternion<T>& b) noexcept
{ {
return div(a, b); return div(a, b);
} }
/// @copydoc mul(const quaternion<T>&, const quaternion<T>&) /// @copydoc mul(const quaternion<T>&, const quaternion<T>&)
template <class T> template <class T>
constexpr inline quaternion<T> operator*(const quaternion<T>& a, const quaternion<T>& b) noexcept
inline constexpr quaternion<T> operator*(const quaternion<T>& a, const quaternion<T>& b) noexcept
{ {
return mul(a, b); return mul(a, b);
} }
@ -792,12 +792,12 @@ constexpr inline quaternion operator*(const quaternion& a, const quaternio
/// @copydoc mul(const quaternion<T>&, T) /// @copydoc mul(const quaternion<T>&, T)
/// @{ /// @{
template <class T> template <class T>
constexpr inline quaternion<T> operator*(const quaternion<T>& a, T b) noexcept
inline constexpr quaternion<T> operator*(const quaternion<T>& a, T b) noexcept
{ {
return mul(a, b); return mul(a, b);
} }
template <class T> template <class T>
constexpr inline quaternion<T> operator*(T a, const quaternion<T>& b) noexcept
inline constexpr quaternion<T> operator*(T a, const quaternion<T>& b) noexcept
{ {
return mul(b, a); return mul(b, a);
} }
@ -805,21 +805,21 @@ constexpr inline quaternion operator*(T a, const quaternion& b) noexcept
/// @copydoc mul(const quaternion<T>&, const vector<T, 3>&) /// @copydoc mul(const quaternion<T>&, const vector<T, 3>&)
template <class T> template <class T>
constexpr inline vector<T, 3> operator*(const quaternion<T>& a, const vector<T, 3>& b) noexcept
inline constexpr vector<T, 3> operator*(const quaternion<T>& a, const vector<T, 3>& b) noexcept
{ {
return mul(a, b); return mul(a, b);
} }
/// @copydoc mul(const vector<T, 3>&, const quaternion<T>&) /// @copydoc mul(const vector<T, 3>&, const quaternion<T>&)
template <class T> template <class T>
constexpr inline vector<T, 3> operator*(const vector<T, 3>& a, const quaternion<T>& b) noexcept
inline constexpr vector<T, 3> operator*(const vector<T, 3>& a, const quaternion<T>& b) noexcept
{ {
return mul(a, b); return mul(a, b);
} }
/// @copydoc sub(const quaternion<T>&, const quaternion<T>&) /// @copydoc sub(const quaternion<T>&, const quaternion<T>&)
template <class T> template <class T>
constexpr inline quaternion<T> operator-(const quaternion<T>& a, const quaternion<T>& b) noexcept
inline constexpr quaternion<T> operator-(const quaternion<T>& a, const quaternion<T>& b) noexcept
{ {
return sub(a, b); return sub(a, b);
} }
@ -827,12 +827,12 @@ constexpr inline quaternion operator-(const quaternion& a, const quaternio
/// @copydoc sub(const quaternion<T>&, T) /// @copydoc sub(const quaternion<T>&, T)
/// @{ /// @{
template <class T> template <class T>
constexpr inline quaternion<T> operator-(const quaternion<T>& a, T b) noexcept
inline constexpr quaternion<T> operator-(const quaternion<T>& a, T b) noexcept
{ {
return sub(a, b); return sub(a, b);
} }
template <class T> template <class T>
constexpr inline quaternion<T> operator-(T a, const quaternion<T>& b) noexcept
inline constexpr quaternion<T> operator-(T a, const quaternion<T>& b) noexcept
{ {
return sub(a, b); return sub(a, b);
} }
@ -840,7 +840,7 @@ constexpr inline quaternion operator-(T a, const quaternion& b) noexcept
/// @copydoc negate(const quaternion<T>&) /// @copydoc negate(const quaternion<T>&)
template <class T> template <class T>
constexpr inline quaternion<T> operator-(const quaternion<T>& q) noexcept
inline constexpr quaternion<T> operator-(const quaternion<T>& q) noexcept
{ {
return negate(q); return negate(q);
} }
@ -855,12 +855,12 @@ constexpr inline quaternion operator-(const quaternion& q) noexcept
*/ */
/// @{ /// @{
template <class T> template <class T>
constexpr inline quaternion<T>& operator+=(quaternion<T>& a, const quaternion<T>& b) noexcept
inline constexpr quaternion<T>& operator+=(quaternion<T>& a, const quaternion<T>& b) noexcept
{ {
return (a = a + b); return (a = a + b);
} }
template <class T> template <class T>
constexpr inline quaternion<T>& operator+=(quaternion<T>& a, T b) noexcept
inline constexpr quaternion<T>& operator+=(quaternion<T>& a, T b) noexcept
{ {
return (a = a + b); return (a = a + b);
} }
@ -876,12 +876,12 @@ constexpr inline quaternion& operator+=(quaternion& a, T b) noexcept
*/ */
/// @{ /// @{
template <class T> template <class T>
constexpr inline quaternion<T>& operator-=(quaternion<T>& a, const quaternion<T>& b) noexcept
inline constexpr quaternion<T>& operator-=(quaternion<T>& a, const quaternion<T>& b) noexcept
{ {
return (a = a - b); return (a = a - b);
} }
template <class T> template <class T>
constexpr inline quaternion<T>& operator-=(quaternion<T>& a, T b) noexcept
inline constexpr quaternion<T>& operator-=(quaternion<T>& a, T b) noexcept
{ {
return (a = a - b); return (a = a - b);
} }
@ -897,12 +897,12 @@ constexpr inline quaternion& operator-=(quaternion& a, T b) noexcept
*/ */
/// @{ /// @{
template <class T> template <class T>
constexpr inline quaternion<T>& operator*=(quaternion<T>& a, const quaternion<T>& b) noexcept
inline constexpr quaternion<T>& operator*=(quaternion<T>& a, const quaternion<T>& b) noexcept
{ {
return (a = a * b); return (a = a * b);
} }
template <class T> template <class T>
constexpr inline quaternion<T>& operator*=(quaternion<T>& a, T b) noexcept
inline constexpr quaternion<T>& operator*=(quaternion<T>& a, T b) noexcept
{ {
return (a = a * b); return (a = a * b);
} }
@ -918,12 +918,12 @@ constexpr inline quaternion& operator*=(quaternion& a, T b) noexcept
*/ */
/// @{ /// @{
template <class T> template <class T>
constexpr inline quaternion<T>& operator/=(quaternion<T>& a, const quaternion<T>& b) noexcept
inline constexpr quaternion<T>& operator/=(quaternion<T>& a, const quaternion<T>& b) noexcept
{ {
return (a = a / b); return (a = a / b);
} }
template <class T> template <class T>
constexpr inline quaternion<T>& operator/=(quaternion<T>& a, T b) noexcept
inline constexpr quaternion<T>& operator/=(quaternion<T>& a, T b) noexcept
{ {
return (a = a / b); return (a = a / b);
} }

+ 137
- 137
src/math/vector.hpp View File

@ -41,13 +41,13 @@ namespace math {
template <typename T, std::size_t N> template <typename T, std::size_t N>
struct vector struct vector
{ {
/// Vector element data type.
/// Element type.
typedef T element_type; typedef T element_type;
/// Number of vector elements.
/// Number of elements.
static constexpr std::size_t element_count = N; static constexpr std::size_t element_count = N;
/// Array of vector elements.
/// Array of elements.
element_type elements[N]; element_type elements[N];
/// @name Conversion /// @name Conversion
@ -55,7 +55,7 @@ struct vector
/// @private /// @private
template <class U, std::size_t... I> template <class U, std::size_t... I>
constexpr inline vector<U, N> type_cast(std::index_sequence<I...>) const noexcept
inline constexpr vector<U, N> type_cast(std::index_sequence<I...>) const noexcept
{ {
return {static_cast<U>(elements[I])...}; return {static_cast<U>(elements[I])...};
} }
@ -68,14 +68,14 @@ struct vector
* @return Vector containing the type-casted elements. * @return Vector containing the type-casted elements.
*/ */
template <class U> template <class U>
constexpr inline explicit operator vector<U, N>() const noexcept
inline constexpr explicit operator vector<U, N>() const noexcept
{ {
return type_cast<U>(std::make_index_sequence<N>{}); return type_cast<U>(std::make_index_sequence<N>{});
} }
/// @private /// @private
template <std::size_t M, std::size_t... I> template <std::size_t M, std::size_t... I>
constexpr inline vector<T, M> size_cast(std::index_sequence<I...>) const noexcept
inline constexpr vector<T, M> size_cast(std::index_sequence<I...>) const noexcept
{ {
return {(I < N) ? elements[I] : T{0} ...}; return {(I < N) ? elements[I] : T{0} ...};
} }
@ -88,7 +88,7 @@ struct vector
* @return *m*-dimensional vector. * @return *m*-dimensional vector.
*/ */
template <std::size_t M> template <std::size_t M>
constexpr inline explicit operator vector<T, M>() const noexcept
inline constexpr explicit operator vector<T, M>() const noexcept
{ {
return size_cast<M>(std::make_index_sequence<M>{}); return size_cast<M>(std::make_index_sequence<M>{});
} }
@ -106,11 +106,11 @@ struct vector
* @return Reference to the element at index @p i. * @return Reference to the element at index @p i.
*/ */
/// @{ /// @{
constexpr inline element_type& operator[](std::size_t i) noexcept
inline constexpr element_type& operator[](std::size_t i) noexcept
{ {
return elements[i]; return elements[i];
} }
constexpr inline const element_type& operator[](std::size_t i) const noexcept
inline constexpr const element_type& operator[](std::size_t i) const noexcept
{ {
return elements[i]; return elements[i];
} }
@ -120,11 +120,11 @@ struct vector
* Returns a reference to the first element. * Returns a reference to the first element.
*/ */
/// @{ /// @{
constexpr inline element_type& front() noexcept
inline constexpr element_type& front() noexcept
{ {
return elements[0]; return elements[0];
} }
constexpr inline const element_type& front() const noexcept
inline constexpr const element_type& front() const noexcept
{ {
return elements[0]; return elements[0];
} }
@ -134,11 +134,11 @@ struct vector
* Returns a reference to the last element. * Returns a reference to the last element.
*/ */
/// @{ /// @{
constexpr inline element_type& back() noexcept
inline constexpr element_type& back() noexcept
{ {
return elements[N - 1]; return elements[N - 1];
} }
constexpr inline const element_type& back() const noexcept
inline constexpr const element_type& back() const noexcept
{ {
return elements[N - 1]; return elements[N - 1];
} }
@ -148,11 +148,11 @@ struct vector
* Returns a pointer to the element array. * Returns a pointer to the element array.
*/ */
/// @{ /// @{
constexpr inline element_type* data() noexcept
inline constexpr element_type* data() noexcept
{ {
return elements; return elements;
}; };
constexpr inline const element_type* data() const noexcept
inline constexpr const element_type* data() const noexcept
{ {
return elements; return elements;
}; };
@ -160,12 +160,12 @@ struct vector
/// Returns a reference to the first element. /// Returns a reference to the first element.
/// @{ /// @{
constexpr inline element_type& x() noexcept
inline constexpr element_type& x() noexcept
{ {
static_assert(N > 0, "Vector does not contain an x element."); static_assert(N > 0, "Vector does not contain an x element.");
return elements[0]; return elements[0];
} }
constexpr inline const element_type& x() const noexcept
inline constexpr const element_type& x() const noexcept
{ {
static_assert(N > 0, "Vector does not contain an x element."); static_assert(N > 0, "Vector does not contain an x element.");
return elements[0]; return elements[0];
@ -176,12 +176,12 @@ struct vector
* Returns a reference to the second element. * Returns a reference to the second element.
*/ */
/// @{ /// @{
constexpr inline element_type& y() noexcept
inline constexpr element_type& y() noexcept
{ {
static_assert(N > 1, "Vector does not contain a y element."); static_assert(N > 1, "Vector does not contain a y element.");
return elements[1]; return elements[1];
} }
constexpr inline const element_type& y() const noexcept
inline constexpr const element_type& y() const noexcept
{ {
static_assert(N > 1, "Vector does not contain a y element."); static_assert(N > 1, "Vector does not contain a y element.");
return elements[1]; return elements[1];
@ -192,12 +192,12 @@ struct vector
* Returns a reference to the third element. * Returns a reference to the third element.
*/ */
/// @{ /// @{
constexpr inline element_type& z() noexcept
inline constexpr element_type& z() noexcept
{ {
static_assert(N > 2, "Vector does not contain a z element."); static_assert(N > 2, "Vector does not contain a z element.");
return elements[2]; return elements[2];
} }
constexpr inline const element_type& z() const noexcept
inline constexpr const element_type& z() const noexcept
{ {
static_assert(N > 2, "Vector does not contain a z element."); static_assert(N > 2, "Vector does not contain a z element.");
return elements[2]; return elements[2];
@ -213,15 +213,15 @@ struct vector
* Returns an iterator to the first element. * Returns an iterator to the first element.
*/ */
/// @{ /// @{
constexpr inline element_type* begin() noexcept
inline constexpr element_type* begin() noexcept
{ {
return elements; return elements;
} }
constexpr inline const element_type* begin() const noexcept
inline constexpr const element_type* begin() const noexcept
{ {
return elements; return elements;
} }
constexpr inline const element_type* cbegin() const noexcept
inline constexpr const element_type* cbegin() const noexcept
{ {
return elements; return elements;
} }
@ -231,15 +231,15 @@ struct vector
* Returns an iterator to the element following the last element. * Returns an iterator to the element following the last element.
*/ */
/// @{ /// @{
constexpr inline element_type* end() noexcept
inline constexpr element_type* end() noexcept
{ {
return elements + N; return elements + N;
} }
constexpr inline const element_type* end() const noexcept
inline constexpr const element_type* end() const noexcept
{ {
return elements + N; return elements + N;
} }
constexpr inline const element_type* cend() const noexcept
inline constexpr const element_type* cend() const noexcept
{ {
return elements + N; return elements + N;
} }
@ -249,15 +249,15 @@ struct vector
* Returns a reverse iterator to the first element of the reversed vector. * Returns a reverse iterator to the first element of the reversed vector.
*/ */
/// @{ /// @{
constexpr inline std::reverse_iterator<element_type*> rbegin() noexcept
inline constexpr std::reverse_iterator<element_type*> rbegin() noexcept
{ {
return std::reverse_iterator<element_type*>(elements + N); return std::reverse_iterator<element_type*>(elements + N);
} }
constexpr inline std::reverse_iterator<const element_type*> rbegin() const noexcept
inline constexpr std::reverse_iterator<const element_type*> rbegin() const noexcept
{ {
return std::reverse_iterator<const element_type*>(elements + N); return std::reverse_iterator<const element_type*>(elements + N);
} }
constexpr inline std::reverse_iterator<const element_type*> crbegin() const noexcept
inline constexpr std::reverse_iterator<const element_type*> crbegin() const noexcept
{ {
return std::reverse_iterator<const element_type*>(elements + N); return std::reverse_iterator<const element_type*>(elements + N);
} }
@ -267,15 +267,15 @@ struct vector
* Returns a reverse iterator to the element following the last element of the reversed vector. * Returns a reverse iterator to the element following the last element of the reversed vector.
*/ */
/// @{ /// @{
constexpr inline std::reverse_iterator<element_type*> rend() noexcept
inline constexpr std::reverse_iterator<element_type*> rend() noexcept
{ {
return std::reverse_iterator<element_type*>(elements); return std::reverse_iterator<element_type*>(elements);
} }
constexpr inline std::reverse_iterator<const element_type*> rend() const noexcept
inline constexpr std::reverse_iterator<const element_type*> rend() const noexcept
{ {
return std::reverse_iterator<const element_type*>(elements); return std::reverse_iterator<const element_type*>(elements);
} }
constexpr inline std::reverse_iterator<const element_type*> crend() const noexcept
inline constexpr std::reverse_iterator<const element_type*> crend() const noexcept
{ {
return std::reverse_iterator<const element_type*>(elements); return std::reverse_iterator<const element_type*>(elements);
} }
@ -289,7 +289,7 @@ struct vector
/** /**
* Returns the number of elements in the vector. * Returns the number of elements in the vector.
*/ */
constexpr inline std::size_t size() const noexcept
inline constexpr std::size_t size() const noexcept
{ {
return N; return N;
}; };
@ -834,104 +834,104 @@ constexpr vector trunc(const vector& x);
/// @private /// @private
template <class T, std::size_t N, std::size_t... I> template <class T, std::size_t N, std::size_t... I>
constexpr inline vector<T, N> abs(const vector<T, N>& x, std::index_sequence<I...>)
inline constexpr vector<T, N> abs(const vector<T, N>& x, std::index_sequence<I...>)
{ {
return {std::abs(x[I])...}; return {std::abs(x[I])...};
} }
template <class T, std::size_t N> template <class T, std::size_t N>
constexpr inline vector<T, N> abs(const vector<T, N>& x)
inline constexpr vector<T, N> abs(const vector<T, N>& x)
{ {
return abs(x, std::make_index_sequence<N>{}); return abs(x, std::make_index_sequence<N>{});
} }
/// @private /// @private
template <class T, std::size_t N, std::size_t... I> template <class T, std::size_t N, std::size_t... I>
constexpr inline vector<T, N> add(const vector<T, N>& x, const vector<T, N>& y, std::index_sequence<I...>) noexcept
inline constexpr vector<T, N> add(const vector<T, N>& x, const vector<T, N>& y, std::index_sequence<I...>) noexcept
{ {
return {(x[I] + y[I])...}; return {(x[I] + y[I])...};
} }
template <class T, std::size_t N> template <class T, std::size_t N>
constexpr inline vector<T, N> add(const vector<T, N>& x, const vector<T, N>& y) noexcept
inline constexpr vector<T, N> add(const vector<T, N>& x, const vector<T, N>& y) noexcept
{ {
return add(x, y, std::make_index_sequence<N>{}); return add(x, y, std::make_index_sequence<N>{});
} }
/// @private /// @private
template <class T, std::size_t N, std::size_t... I> template <class T, std::size_t N, std::size_t... I>
constexpr inline vector<T, N> add(const vector<T, N>& x, T y, std::index_sequence<I...>) noexcept
inline constexpr vector<T, N> add(const vector<T, N>& x, T y, std::index_sequence<I...>) noexcept
{ {
return {(x[I] + y)...}; return {(x[I] + y)...};
} }
template <class T, std::size_t N> template <class T, std::size_t N>
constexpr inline vector<T, N> add(const vector<T, N>& x, T y) noexcept
inline constexpr vector<T, N> add(const vector<T, N>& x, T y) noexcept
{ {
return add(x, y, std::make_index_sequence<N>{}); return add(x, y, std::make_index_sequence<N>{});
} }
/// @private /// @private
template <std::size_t N, std::size_t... I> template <std::size_t N, std::size_t... I>
constexpr inline bool all(const vector<bool, N>& x, std::index_sequence<I...>) noexcept
inline constexpr bool all(const vector<bool, N>& x, std::index_sequence<I...>) noexcept
{ {
return (x[I] && ...); return (x[I] && ...);
} }
template <std::size_t N> template <std::size_t N>
constexpr inline bool all(const vector<bool, N>& x) noexcept
inline constexpr bool all(const vector<bool, N>& x) noexcept
{ {
return all(x, std::make_index_sequence<N>{}); return all(x, std::make_index_sequence<N>{});
} }
/// @private /// @private
template <std::size_t N, std::size_t... I> template <std::size_t N, std::size_t... I>
constexpr inline bool any(const vector<bool, N>& x, std::index_sequence<I...>) noexcept
inline constexpr bool any(const vector<bool, N>& x, std::index_sequence<I...>) noexcept
{ {
return (x[I] || ...); return (x[I] || ...);
} }
template <std::size_t N> template <std::size_t N>
constexpr inline bool any(const vector<bool, N>& x) noexcept
inline constexpr bool any(const vector<bool, N>& x) noexcept
{ {
return any(x, std::make_index_sequence<N>{}); return any(x, std::make_index_sequence<N>{});
} }
/// @private /// @private
template <std::floating_point T, std::size_t N, std::size_t... I> template <std::floating_point T, std::size_t N, std::size_t... I>
constexpr inline vector<T, N> ceil(const vector<T, N>& x, std::index_sequence<I...>)
inline constexpr vector<T, N> ceil(const vector<T, N>& x, std::index_sequence<I...>)
{ {
return {std::ceil(x[I])...}; return {std::ceil(x[I])...};
} }
template <std::floating_point T, std::size_t N> template <std::floating_point T, std::size_t N>
constexpr inline vector<T, N> ceil(const vector<T, N>& x)
inline constexpr vector<T, N> ceil(const vector<T, N>& x)
{ {
return ceil(x, std::make_index_sequence<N>{}); return ceil(x, std::make_index_sequence<N>{});
} }
/// @private /// @private
template <class T, std::size_t N, std::size_t... I> template <class T, std::size_t N, std::size_t... I>
constexpr inline vector<T, N> clamp(const vector<T, N>& x, const vector<T, N>& min_val, const vector<T, N>& max_val, std::index_sequence<I...>)
inline constexpr vector<T, N> clamp(const vector<T, N>& x, const vector<T, N>& min_val, const vector<T, N>& max_val, std::index_sequence<I...>)
{ {
return {std::min<T>(max_val[I], std::max<T>(min_val[I], x[I]))...}; return {std::min<T>(max_val[I], std::max<T>(min_val[I], x[I]))...};
} }
template <class T, std::size_t N> template <class T, std::size_t N>
constexpr inline vector<T, N> clamp(const vector<T, N>& x, const vector<T, N>& min, const vector<T, N>& max)
inline constexpr vector<T, N> clamp(const vector<T, N>& x, const vector<T, N>& min, const vector<T, N>& max)
{ {
return clamp(x, min, max, std::make_index_sequence<N>{}); return clamp(x, min, max, std::make_index_sequence<N>{});
} }
/// @private /// @private
template <class T, std::size_t N, std::size_t... I> template <class T, std::size_t N, std::size_t... I>
constexpr inline vector<T, N> clamp(const vector<T, N>& x, T min, T max, std::index_sequence<I...>)
inline constexpr vector<T, N> clamp(const vector<T, N>& x, T min, T max, std::index_sequence<I...>)
{ {
return {std::min<T>(max, std::max<T>(min, x[I]))...}; return {std::min<T>(max, std::max<T>(min, x[I]))...};
} }
template <class T, std::size_t N> template <class T, std::size_t N>
constexpr inline vector<T, N> clamp(const vector<T, N>& x, T min, T max)
inline constexpr vector<T, N> clamp(const vector<T, N>& x, T min, T max)
{ {
return clamp(x, min, max, std::make_index_sequence<N>{}); return clamp(x, min, max, std::make_index_sequence<N>{});
} }
@ -944,7 +944,7 @@ vector clamp_length(const vector& x, T max_length)
} }
template <class T> template <class T>
constexpr inline vector<T, 3> cross(const vector<T, 3>& x, const vector<T, 3>& y) noexcept
inline constexpr vector<T, 3> cross(const vector<T, 3>& x, const vector<T, 3>& y) noexcept
{ {
return return
{ {
@ -962,144 +962,144 @@ inline T distance(const vector& p0, const vector& p1)
/// @private /// @private
template <class T, std::size_t N, std::size_t... I> template <class T, std::size_t N, std::size_t... I>
constexpr inline vector<T, N> div(const vector<T, N>& x, const vector<T, N>& y, std::index_sequence<I...>) noexcept
inline constexpr vector<T, N> div(const vector<T, N>& x, const vector<T, N>& y, std::index_sequence<I...>) noexcept
{ {
return {(x[I] / y[I])...}; return {(x[I] / y[I])...};
} }
template <class T, std::size_t N> template <class T, std::size_t N>
constexpr inline vector<T, N> div(const vector<T, N>& x, const vector<T, N>& y) noexcept
inline constexpr vector<T, N> div(const vector<T, N>& x, const vector<T, N>& y) noexcept
{ {
return div(x, y, std::make_index_sequence<N>{}); return div(x, y, std::make_index_sequence<N>{});
} }
/// @private /// @private
template <class T, std::size_t N, std::size_t... I> template <class T, std::size_t N, std::size_t... I>
constexpr inline vector<T, N> div(const vector<T, N>& x, T y, std::index_sequence<I...>) noexcept
inline constexpr vector<T, N> div(const vector<T, N>& x, T y, std::index_sequence<I...>) noexcept
{ {
return {(x[I] / y)...}; return {(x[I] / y)...};
} }
template <class T, std::size_t N> template <class T, std::size_t N>
constexpr inline vector<T, N> div(const vector<T, N>& x, T y) noexcept
inline constexpr vector<T, N> div(const vector<T, N>& x, T y) noexcept
{ {
return div(x, y, std::make_index_sequence<N>{}); return div(x, y, std::make_index_sequence<N>{});
} }
/// @private /// @private
template <class T, std::size_t N, std::size_t... I> template <class T, std::size_t N, std::size_t... I>
constexpr inline vector<T, N> div(T x, const vector<T, N>& y, std::index_sequence<I...>) noexcept
inline constexpr vector<T, N> div(T x, const vector<T, N>& y, std::index_sequence<I...>) noexcept
{ {
return {(x / y[I])...}; return {(x / y[I])...};
} }
template <class T, std::size_t N> template <class T, std::size_t N>
constexpr inline vector<T, N> div(T x, const vector<T, N>& y) noexcept
inline constexpr vector<T, N> div(T x, const vector<T, N>& y) noexcept
{ {
return div(x, y, std::make_index_sequence<N>{}); return div(x, y, std::make_index_sequence<N>{});
} }
/// @private /// @private
template <class T, std::size_t N, std::size_t... I> template <class T, std::size_t N, std::size_t... I>
constexpr inline T dot(const vector<T, N>& x, const vector<T, N>& y, std::index_sequence<I...>) noexcept
inline constexpr T dot(const vector<T, N>& x, const vector<T, N>& y, std::index_sequence<I...>) noexcept
{ {
return ((x[I] * y[I]) + ...); return ((x[I] * y[I]) + ...);
} }
template <class T, std::size_t N> template <class T, std::size_t N>
constexpr inline T dot(const vector<T, N>& x, const vector<T, N>& y) noexcept
inline constexpr T dot(const vector<T, N>& x, const vector<T, N>& y) noexcept
{ {
return dot(x, y, std::make_index_sequence<N>{}); return dot(x, y, std::make_index_sequence<N>{});
} }
/// @private /// @private
template <class T, std::size_t N, std::size_t... I> template <class T, std::size_t N, std::size_t... I>
constexpr inline vector<bool, N> equal(const vector<T, N>& x, const vector<T, N>& y, std::index_sequence<I...>) noexcept
inline constexpr vector<bool, N> equal(const vector<T, N>& x, const vector<T, N>& y, std::index_sequence<I...>) noexcept
{ {
return {(x[I] == y[I])...}; return {(x[I] == y[I])...};
} }
template <class T, std::size_t N> template <class T, std::size_t N>
constexpr inline vector<bool, N> equal(const vector<T, N>& x, const vector<T, N>& y) noexcept
inline constexpr vector<bool, N> equal(const vector<T, N>& x, const vector<T, N>& y) noexcept
{ {
return equal(x, y, std::make_index_sequence<N>{}); return equal(x, y, std::make_index_sequence<N>{});
} }
/// @private /// @private
template <std::floating_point T, std::size_t N, std::size_t... I> template <std::floating_point T, std::size_t N, std::size_t... I>
constexpr inline vector<T, N> floor(const vector<T, N>& x, std::index_sequence<I...>)
inline constexpr vector<T, N> floor(const vector<T, N>& x, std::index_sequence<I...>)
{ {
return {std::floor(x[I])...}; return {std::floor(x[I])...};
} }
template <std::floating_point T, std::size_t N> template <std::floating_point T, std::size_t N>
constexpr inline vector<T, N> floor(const vector<T, N>& x)
inline constexpr vector<T, N> floor(const vector<T, N>& x)
{ {
return floor(x, std::make_index_sequence<N>{}); return floor(x, std::make_index_sequence<N>{});
} }
/// @private /// @private
template <std::floating_point T, std::size_t N, std::size_t... I> template <std::floating_point T, std::size_t N, std::size_t... I>
constexpr inline vector<T, N> fma(const vector<T, N>& x, const vector<T, N>& y, const vector<T, N>& z, std::index_sequence<I...>)
inline constexpr vector<T, N> fma(const vector<T, N>& x, const vector<T, N>& y, const vector<T, N>& z, std::index_sequence<I...>)
{ {
return {std::fma(x[I], y[I], z[I])...}; return {std::fma(x[I], y[I], z[I])...};
} }
template <std::floating_point T, std::size_t N> template <std::floating_point T, std::size_t N>
constexpr inline vector<T, N> fma(const vector<T, N>& x, const vector<T, N>& y, const vector<T, N>& z)
inline constexpr vector<T, N> fma(const vector<T, N>& x, const vector<T, N>& y, const vector<T, N>& z)
{ {
return fma(x, y, z, std::make_index_sequence<N>{}); return fma(x, y, z, std::make_index_sequence<N>{});
} }
/// @private /// @private
template <std::floating_point T, std::size_t N, std::size_t... I> template <std::floating_point T, std::size_t N, std::size_t... I>
constexpr inline vector<T, N> fma(const vector<T, N>& x, T y, T z, std::index_sequence<I...>)
inline constexpr vector<T, N> fma(const vector<T, N>& x, T y, T z, std::index_sequence<I...>)
{ {
return {std::fma(x[I], y, z)...}; return {std::fma(x[I], y, z)...};
} }
template <std::floating_point T, std::size_t N> template <std::floating_point T, std::size_t N>
constexpr inline vector<T, N> fma(const vector<T, N>& x, T y, T z)
inline constexpr vector<T, N> fma(const vector<T, N>& x, T y, T z)
{ {
return fma(x, y, z, std::make_index_sequence<N>{}); return fma(x, y, z, std::make_index_sequence<N>{});
} }
/// @private /// @private
template <std::floating_point T, std::size_t N, std::size_t... I> template <std::floating_point T, std::size_t N, std::size_t... I>
constexpr inline vector<T, N> fract(const vector<T, N>& x, std::index_sequence<I...>)
inline constexpr vector<T, N> fract(const vector<T, N>& x, std::index_sequence<I...>)
{ {
return {x[I] - std::floor(x[I])...}; return {x[I] - std::floor(x[I])...};
} }
template <std::floating_point T, std::size_t N> template <std::floating_point T, std::size_t N>
constexpr inline vector<T, N> fract(const vector<T, N>& x)
inline constexpr vector<T, N> fract(const vector<T, N>& x)
{ {
return fract(x, std::make_index_sequence<N>{}); return fract(x, std::make_index_sequence<N>{});
} }
template<std::size_t I, class T, std::size_t N> template<std::size_t I, class T, std::size_t N>
constexpr inline T& get(math::vector<T, N>& v) noexcept
inline constexpr T& get(math::vector<T, N>& v) noexcept
{ {
static_assert(I < N); static_assert(I < N);
return v.elements[I]; return v.elements[I];
} }
template<std::size_t I, class T, std::size_t N> template<std::size_t I, class T, std::size_t N>
constexpr inline T&& get(math::vector<T, N>&& v) noexcept
inline constexpr T&& get(math::vector<T, N>&& v) noexcept
{ {
static_assert(I < N); static_assert(I < N);
return std::move(v.elements[I]); return std::move(v.elements[I]);
} }
template<std::size_t I, class T, std::size_t N> template<std::size_t I, class T, std::size_t N>
constexpr inline const T& get(const math::vector<T, N>& v) noexcept
inline constexpr const T& get(const math::vector<T, N>& v) noexcept
{ {
static_assert(I < N); static_assert(I < N);
return v.elements[I]; return v.elements[I];
} }
template<std::size_t I, class T, std::size_t N> template<std::size_t I, class T, std::size_t N>
constexpr inline const T&& get(const math::vector<T, N>&& v) noexcept
inline constexpr const T&& get(const math::vector<T, N>&& v) noexcept
{ {
static_assert(I < N); static_assert(I < N);
return std::move(v.elements[I]); return std::move(v.elements[I]);
@ -1107,26 +1107,26 @@ constexpr inline const T&& get(const math::vector&& v) noexcept
/// @private /// @private
template <class T, std::size_t N, std::size_t... I> template <class T, std::size_t N, std::size_t... I>
constexpr inline vector<bool, N> greater_than(const vector<T, N>& x, const vector<T, N>& y, std::index_sequence<I...>) noexcept
inline constexpr vector<bool, N> greater_than(const vector<T, N>& x, const vector<T, N>& y, std::index_sequence<I...>) noexcept
{ {
return {(x[I] > y[I])...}; return {(x[I] > y[I])...};
} }
template <class T, std::size_t N> template <class T, std::size_t N>
constexpr inline vector<bool, N> greater_than(const vector<T, N>& x, const vector<T, N>& y) noexcept
inline constexpr vector<bool, N> greater_than(const vector<T, N>& x, const vector<T, N>& y) noexcept
{ {
return greater_than(x, y, std::make_index_sequence<N>{}); return greater_than(x, y, std::make_index_sequence<N>{});
} }
/// @private /// @private
template <class T, std::size_t N, std::size_t... I> template <class T, std::size_t N, std::size_t... I>
constexpr inline vector<bool, N> greater_than_equal(const vector<T, N>& x, const vector<T, N>& y, std::index_sequence<I...>) noexcept
inline constexpr vector<bool, N> greater_than_equal(const vector<T, N>& x, const vector<T, N>& y, std::index_sequence<I...>) noexcept
{ {
return {(x[I] >= y[I])...}; return {(x[I] >= y[I])...};
} }
template <class T, std::size_t N> template <class T, std::size_t N>
constexpr inline vector<bool, N> greater_than_equal(const vector<T, N>& x, const vector<T, N>& y) noexcept
inline constexpr vector<bool, N> greater_than_equal(const vector<T, N>& x, const vector<T, N>& y) noexcept
{ {
return greater_than_equal(x, y, std::make_index_sequence<N>{}); return greater_than_equal(x, y, std::make_index_sequence<N>{});
} }
@ -1145,33 +1145,33 @@ inline T length(const vector& x)
/// @private /// @private
template <class T, std::size_t N, std::size_t... I> template <class T, std::size_t N, std::size_t... I>
constexpr inline vector<bool, N> less_than(const vector<T, N>& x, const vector<T, N>& y, std::index_sequence<I...>) noexcept
inline constexpr vector<bool, N> less_than(const vector<T, N>& x, const vector<T, N>& y, std::index_sequence<I...>) noexcept
{ {
return {(x[I] < y[I])...}; return {(x[I] < y[I])...};
} }
template <class T, std::size_t N> template <class T, std::size_t N>
constexpr inline vector<bool, N> less_than(const vector<T, N>& x, const vector<T, N>& y) noexcept
inline constexpr vector<bool, N> less_than(const vector<T, N>& x, const vector<T, N>& y) noexcept
{ {
return less_than(x, y, std::make_index_sequence<N>{}); return less_than(x, y, std::make_index_sequence<N>{});
} }
/// @private /// @private
template <class T, std::size_t N, std::size_t... I> template <class T, std::size_t N, std::size_t... I>
constexpr inline vector<bool, N> less_than_equal(const vector<T, N>& x, const vector<T, N>& y, std::index_sequence<I...>) noexcept
inline constexpr vector<bool, N> less_than_equal(const vector<T, N>& x, const vector<T, N>& y, std::index_sequence<I...>) noexcept
{ {
return {(x[I] <= y[I])...}; return {(x[I] <= y[I])...};
} }
template <class T, std::size_t N> template <class T, std::size_t N>
constexpr inline vector<bool, N> less_than_equal(const vector<T, N>& x, const vector<T, N>& y) noexcept
inline constexpr vector<bool, N> less_than_equal(const vector<T, N>& x, const vector<T, N>& y) noexcept
{ {
return less_than_equal(x, y, std::make_index_sequence<N>{}); return less_than_equal(x, y, std::make_index_sequence<N>{});
} }
/// @private /// @private
template <class T, std::size_t N, std::size_t... I> template <class T, std::size_t N, std::size_t... I>
constexpr inline vector<T, N> max(const vector<T, N>& x, const vector<T, N>& y, std::index_sequence<I...>)
inline constexpr vector<T, N> max(const vector<T, N>& x, const vector<T, N>& y, std::index_sequence<I...>)
{ {
return {std::max<T>(x[I], y[I])...}; return {std::max<T>(x[I], y[I])...};
} }
@ -1183,14 +1183,14 @@ constexpr vector max(const vector& x, const vector& y)
} }
template <class T, std::size_t N> template <class T, std::size_t N>
constexpr inline T max(const vector<T, N>& x)
inline constexpr T max(const vector<T, N>& x)
{ {
return *std::max_element(x.elements, x.elements + N); return *std::max_element(x.elements, x.elements + N);
} }
/// @private /// @private
template <class T, std::size_t N, std::size_t... I> template <class T, std::size_t N, std::size_t... I>
constexpr inline vector<T, N> min(const vector<T, N>& x, const vector<T, N>& y, std::index_sequence<I...>)
inline constexpr vector<T, N> min(const vector<T, N>& x, const vector<T, N>& y, std::index_sequence<I...>)
{ {
return {std::min<T>(x[I], y[I])...}; return {std::min<T>(x[I], y[I])...};
} }
@ -1202,72 +1202,72 @@ constexpr vector min(const vector& x, const vector& y)
} }
template <class T, std::size_t N> template <class T, std::size_t N>
constexpr inline T min(const vector<T, N>& x)
inline constexpr T min(const vector<T, N>& x)
{ {
return *std::min_element(x.elements, x.elements + N); return *std::min_element(x.elements, x.elements + N);
} }
/// @private /// @private
template <std::floating_point T, std::size_t N, std::size_t... I> template <std::floating_point T, std::size_t N, std::size_t... I>
constexpr inline vector<T, N> mod(const vector<T, N>& x, const vector<T, N>& y, std::index_sequence<I...>)
inline constexpr vector<T, N> mod(const vector<T, N>& x, const vector<T, N>& y, std::index_sequence<I...>)
{ {
return {std::fmod(x[I], y[I])...}; return {std::fmod(x[I], y[I])...};
} }
template <std::floating_point T, std::size_t N> template <std::floating_point T, std::size_t N>
constexpr inline vector<T, N> mod(const vector<T, N>& x, const vector<T, N>& y)
inline constexpr vector<T, N> mod(const vector<T, N>& x, const vector<T, N>& y)
{ {
return mod(x, y, std::make_index_sequence<N>{}); return mod(x, y, std::make_index_sequence<N>{});
} }
/// @private /// @private
template <std::floating_point T, std::size_t N, std::size_t... I> template <std::floating_point T, std::size_t N, std::size_t... I>
constexpr inline vector<T, N> mod(const vector<T, N>& x, T y, std::index_sequence<I...>)
inline constexpr vector<T, N> mod(const vector<T, N>& x, T y, std::index_sequence<I...>)
{ {
return {std::fmod(x[I], y)...}; return {std::fmod(x[I], y)...};
} }
template <std::floating_point T, std::size_t N> template <std::floating_point T, std::size_t N>
constexpr inline vector<T, N> mod(const vector<T, N>& x, T y)
inline constexpr vector<T, N> mod(const vector<T, N>& x, T y)
{ {
return mod(x, y, std::make_index_sequence<N>{}); return mod(x, y, std::make_index_sequence<N>{});
} }
/// @private /// @private
template <class T, std::size_t N, std::size_t... I> template <class T, std::size_t N, std::size_t... I>
constexpr inline vector<T, N> mul(const vector<T, N>& x, const vector<T, N>& y, std::index_sequence<I...>) noexcept
inline constexpr vector<T, N> mul(const vector<T, N>& x, const vector<T, N>& y, std::index_sequence<I...>) noexcept
{ {
return {(x[I] * y[I])...}; return {(x[I] * y[I])...};
} }
template <class T, std::size_t N> template <class T, std::size_t N>
constexpr inline vector<T, N> mul(const vector<T, N>& x, const vector<T, N>& y) noexcept
inline constexpr vector<T, N> mul(const vector<T, N>& x, const vector<T, N>& y) noexcept
{ {
return mul(x, y, std::make_index_sequence<N>{}); return mul(x, y, std::make_index_sequence<N>{});
} }
/// @private /// @private
template <class T, std::size_t N, std::size_t... I> template <class T, std::size_t N, std::size_t... I>
constexpr inline vector<T, N> mul(const vector<T, N>& x, T y, std::index_sequence<I...>) noexcept
inline constexpr vector<T, N> mul(const vector<T, N>& x, T y, std::index_sequence<I...>) noexcept
{ {
return {(x[I] * y)...}; return {(x[I] * y)...};
} }
template <class T, std::size_t N> template <class T, std::size_t N>
constexpr inline vector<T, N> mul(const vector<T, N>& x, T y) noexcept
inline constexpr vector<T, N> mul(const vector<T, N>& x, T y) noexcept
{ {
return mul(x, y, std::make_index_sequence<N>{}); return mul(x, y, std::make_index_sequence<N>{});
} }
/// @private /// @private
template <class T, std::size_t N, std::size_t... I> template <class T, std::size_t N, std::size_t... I>
constexpr inline vector<T, N> negate(const vector<T, N>& x, std::index_sequence<I...>) noexcept
inline constexpr vector<T, N> negate(const vector<T, N>& x, std::index_sequence<I...>) noexcept
{ {
return {(-x[I])...}; return {(-x[I])...};
} }
template <class T, std::size_t N> template <class T, std::size_t N>
constexpr inline vector<T, N> negate(const vector<T, N>& x) noexcept
inline constexpr vector<T, N> negate(const vector<T, N>& x) noexcept
{ {
return negate(x, std::make_index_sequence<N>{}); return negate(x, std::make_index_sequence<N>{});
} }
@ -1280,26 +1280,26 @@ inline vector normalize(const vector& x)
/// @private /// @private
template <class T, std::size_t N, std::size_t... I> template <class T, std::size_t N, std::size_t... I>
constexpr inline vector<bool, N> logical_not(const vector<T, N>& x, std::index_sequence<I...>) noexcept
inline constexpr vector<bool, N> logical_not(const vector<T, N>& x, std::index_sequence<I...>) noexcept
{ {
return {!x[I]...}; return {!x[I]...};
} }
template <class T, std::size_t N> template <class T, std::size_t N>
constexpr inline vector<bool, N> logical_not(const vector<T, N>& x) noexcept
inline constexpr vector<bool, N> logical_not(const vector<T, N>& x) noexcept
{ {
return logical_not(x, std::make_index_sequence<N>{}); return logical_not(x, std::make_index_sequence<N>{});
} }
/// @private /// @private
template <class T, std::size_t N, std::size_t... I> template <class T, std::size_t N, std::size_t... I>
constexpr inline vector<bool, N> not_equal(const vector<T, N>& x, const vector<T, N>& y, std::index_sequence<I...>) noexcept
inline constexpr vector<bool, N> not_equal(const vector<T, N>& x, const vector<T, N>& y, std::index_sequence<I...>) noexcept
{ {
return {(x[I] != y[I])...}; return {(x[I] != y[I])...};
} }
template <class T, std::size_t N> template <class T, std::size_t N>
constexpr inline vector<bool, N> not_equal(const vector<T, N>& x, const vector<T, N>& y) noexcept
inline constexpr vector<bool, N> not_equal(const vector<T, N>& x, const vector<T, N>& y) noexcept
{ {
return not_equal(x, y, std::make_index_sequence<N>{}); return not_equal(x, y, std::make_index_sequence<N>{});
} }
@ -1332,38 +1332,38 @@ inline vector pow(const vector& x, T y)
/// @private /// @private
template <std::floating_point T, std::size_t N, std::size_t... I> template <std::floating_point T, std::size_t N, std::size_t... I>
constexpr inline vector<T, N> round(const vector<T, N>& x, std::index_sequence<I...>)
inline constexpr vector<T, N> round(const vector<T, N>& x, std::index_sequence<I...>)
{ {
return {std::round(x[I])...}; return {std::round(x[I])...};
} }
template <std::floating_point T, std::size_t N> template <std::floating_point T, std::size_t N>
constexpr inline vector<T, N> round(const vector<T, N>& x)
inline constexpr vector<T, N> round(const vector<T, N>& x)
{ {
return round(x, std::make_index_sequence<N>{}); return round(x, std::make_index_sequence<N>{});
} }
/// @private /// @private
template <std::floating_point T, std::size_t N, std::size_t... I> template <std::floating_point T, std::size_t N, std::size_t... I>
constexpr inline vector<T, N> sign(const vector<T, N>& x, std::index_sequence<I...>)
inline constexpr vector<T, N> sign(const vector<T, N>& x, std::index_sequence<I...>)
{ {
return {std::copysign(T{1}, x[I])...}; return {std::copysign(T{1}, x[I])...};
} }
template <std::floating_point T, std::size_t N> template <std::floating_point T, std::size_t N>
constexpr inline vector<T, N> sign(const vector<T, N>& x)
inline constexpr vector<T, N> sign(const vector<T, N>& x)
{ {
return sign(x, std::make_index_sequence<N>{}); return sign(x, std::make_index_sequence<N>{});
} }
template <class T, std::size_t N> template <class T, std::size_t N>
constexpr inline T sqr_distance(const vector<T, N>& p0, const vector<T, N>& p1) noexcept
inline constexpr T sqr_distance(const vector<T, N>& p0, const vector<T, N>& p1) noexcept
{ {
return sqr_length(sub(p0, p1)); return sqr_length(sub(p0, p1));
} }
template <class T, std::size_t N> template <class T, std::size_t N>
constexpr inline T sqr_length(const vector<T, N>& x) noexcept
inline constexpr T sqr_length(const vector<T, N>& x) noexcept
{ {
return dot(x, x); return dot(x, x);
} }
@ -1383,71 +1383,71 @@ inline vector sqrt(const vector& x, const vector& y)
/// @private /// @private
template <class T, std::size_t N, std::size_t... I> template <class T, std::size_t N, std::size_t... I>
constexpr inline vector<T, N> sub(const vector<T, N>& x, const vector<T, N>& y, std::index_sequence<I...>) noexcept
inline constexpr vector<T, N> sub(const vector<T, N>& x, const vector<T, N>& y, std::index_sequence<I...>) noexcept
{ {
return {(x[I] - y[I])...}; return {(x[I] - y[I])...};
} }
template <class T, std::size_t N> template <class T, std::size_t N>
constexpr inline vector<T, N> sub(const vector<T, N>& x, const vector<T, N>& y) noexcept
inline constexpr vector<T, N> sub(const vector<T, N>& x, const vector<T, N>& y) noexcept
{ {
return sub(x, y, std::make_index_sequence<N>{}); return sub(x, y, std::make_index_sequence<N>{});
} }
/// @private /// @private
template <class T, std::size_t N, std::size_t... I> template <class T, std::size_t N, std::size_t... I>
constexpr inline vector<T, N> sub(const vector<T, N>& x, T y, std::index_sequence<I...>) noexcept
inline constexpr vector<T, N> sub(const vector<T, N>& x, T y, std::index_sequence<I...>) noexcept
{ {
return {(x[I] - y)...}; return {(x[I] - y)...};
} }
template <class T, std::size_t N> template <class T, std::size_t N>
constexpr inline vector<T, N> sub(const vector<T, N>& x, T y) noexcept
inline constexpr vector<T, N> sub(const vector<T, N>& x, T y) noexcept
{ {
return sub(x, y, std::make_index_sequence<N>{}); return sub(x, y, std::make_index_sequence<N>{});
} }
/// @private /// @private
template <class T, std::size_t N, std::size_t... I> template <class T, std::size_t N, std::size_t... I>
constexpr inline vector<T, N> sub(T x, const vector<T, N>& y, std::index_sequence<I...>) noexcept
inline constexpr vector<T, N> sub(T x, const vector<T, N>& y, std::index_sequence<I...>) noexcept
{ {
return {(x - y[I])...}; return {(x - y[I])...};
} }
template <class T, std::size_t N> template <class T, std::size_t N>
constexpr inline vector<T, N> sub(T x, const vector<T, N>& y) noexcept
inline constexpr vector<T, N> sub(T x, const vector<T, N>& y) noexcept
{ {
return sub(x, y, std::make_index_sequence<N>{}); return sub(x, y, std::make_index_sequence<N>{});
} }
/// @private /// @private
template <class T, std::size_t N, std::size_t... I> template <class T, std::size_t N, std::size_t... I>
constexpr inline T sum(const vector<T, N>& x, std::index_sequence<I...>) noexcept
inline constexpr T sum(const vector<T, N>& x, std::index_sequence<I...>) noexcept
{ {
return (x[I] + ...); return (x[I] + ...);
} }
template <class T, std::size_t N> template <class T, std::size_t N>
constexpr inline T sum(const vector<T, N>& x) noexcept
inline constexpr T sum(const vector<T, N>& x) noexcept
{ {
return sum(x, std::make_index_sequence<N>{}); return sum(x, std::make_index_sequence<N>{});
} }
template <std::size_t... Indices, class T, std::size_t N> template <std::size_t... Indices, class T, std::size_t N>
constexpr inline vector<T, sizeof...(Indices)> swizzle(const vector<T, N>& x) noexcept
inline constexpr vector<T, sizeof...(Indices)> swizzle(const vector<T, N>& x) noexcept
{ {
return {x[Indices]...}; return {x[Indices]...};
} }
/// @private /// @private
template <std::floating_point T, std::size_t N, std::size_t... I> template <std::floating_point T, std::size_t N, std::size_t... I>
constexpr inline vector<T, N> trunc(const vector<T, N>& x, std::index_sequence<I...>)
inline constexpr vector<T, N> trunc(const vector<T, N>& x, std::index_sequence<I...>)
{ {
return {std::trunc(x[I])...}; return {std::trunc(x[I])...};
} }
template <std::floating_point T, std::size_t N> template <std::floating_point T, std::size_t N>
constexpr inline vector<T, N> trunc(const vector<T, N>& x)
inline constexpr vector<T, N> trunc(const vector<T, N>& x)
{ {
return trunc(x, std::make_index_sequence<N>{}); return trunc(x, std::make_index_sequence<N>{});
} }
@ -1456,7 +1456,7 @@ namespace operators {
/// @copydoc add(const vector<T, N>&, const vector<T, N>&) /// @copydoc add(const vector<T, N>&, const vector<T, N>&)
template <class T, std::size_t N> template <class T, std::size_t N>
constexpr inline vector<T, N> operator+(const vector<T, N>& x, const vector<T, N>& y) noexcept
inline constexpr vector<T, N> operator+(const vector<T, N>& x, const vector<T, N>& y) noexcept
{ {
return add(x, y); return add(x, y);
} }
@ -1464,12 +1464,12 @@ constexpr inline vector operator+(const vector& x, const vector
/// @copydoc add(const vector<T, N>&, T) /// @copydoc add(const vector<T, N>&, T)
/// @{ /// @{
template <class T, std::size_t N> template <class T, std::size_t N>
constexpr inline vector<T, N> operator+(const vector<T, N>& x, T y) noexcept
inline constexpr vector<T, N> operator+(const vector<T, N>& x, T y) noexcept
{ {
return add(x, y); return add(x, y);
} }
template <class T, std::size_t N> template <class T, std::size_t N>
constexpr inline vector<T, N> operator+(T x, const vector<T, N>& y) noexcept
inline constexpr vector<T, N> operator+(T x, const vector<T, N>& y) noexcept
{ {
return add(y, x); return add(y, x);
} }
@ -1477,28 +1477,28 @@ constexpr inline vector operator+(T x, const vector& y) noexcept
/// @copydoc div(const vector<T, N>&, const vector<T, N>&) /// @copydoc div(const vector<T, N>&, const vector<T, N>&)
template <class T, std::size_t N> template <class T, std::size_t N>
constexpr inline vector<T, N> operator/(const vector<T, N>& x, const vector<T, N>& y) noexcept
inline constexpr vector<T, N> operator/(const vector<T, N>& x, const vector<T, N>& y) noexcept
{ {
return div(x, y); return div(x, y);
} }
/// @copydoc div(const vector<T, N>&, T) /// @copydoc div(const vector<T, N>&, T)
template <class T, std::size_t N> template <class T, std::size_t N>
constexpr inline vector<T, N> operator/(const vector<T, N>& x, T y) noexcept
inline constexpr vector<T, N> operator/(const vector<T, N>& x, T y) noexcept
{ {
return div(x, y); return div(x, y);
} }
/// @copydoc div(T, const vector<T, N>&) /// @copydoc div(T, const vector<T, N>&)
template <class T, std::size_t N> template <class T, std::size_t N>
constexpr inline vector<T, N> operator/(T x, const vector<T, N>& y) noexcept
inline constexpr vector<T, N> operator/(T x, const vector<T, N>& y) noexcept
{ {
return div(x, y); return div(x, y);
} }
/// @copydoc mul(const vector<T, N>&, const vector<T, N>&) /// @copydoc mul(const vector<T, N>&, const vector<T, N>&)
template <class T, std::size_t N> template <class T, std::size_t N>
constexpr inline vector<T, N> operator*(const vector<T, N>& x, const vector<T, N>& y) noexcept
inline constexpr vector<T, N> operator*(const vector<T, N>& x, const vector<T, N>& y) noexcept
{ {
return mul(x, y); return mul(x, y);
} }
@ -1506,12 +1506,12 @@ constexpr inline vector operator*(const vector& x, const vector
/// @copydoc mul(const vector<T, N>&, T) /// @copydoc mul(const vector<T, N>&, T)
/// @{ /// @{
template <class T, std::size_t N> template <class T, std::size_t N>
constexpr inline vector<T, N> operator*(const vector<T, N>& x, T y) noexcept
inline constexpr vector<T, N> operator*(const vector<T, N>& x, T y) noexcept
{ {
return mul(x, y); return mul(x, y);
} }
template <class T, std::size_t N> template <class T, std::size_t N>
constexpr inline vector<T, N> operator*(T x, const vector<T, N>& y) noexcept
inline constexpr vector<T, N> operator*(T x, const vector<T, N>& y) noexcept
{ {
return mul(y, x); return mul(y, x);
} }
@ -1519,28 +1519,28 @@ constexpr inline vector operator*(T x, const vector& y) noexcept
/// @copydoc negate(const vector<T, N>&) /// @copydoc negate(const vector<T, N>&)
template <class T, std::size_t N> template <class T, std::size_t N>
constexpr inline vector<T, N> operator-(const vector<T, N>& x) noexcept
inline constexpr vector<T, N> operator-(const vector<T, N>& x) noexcept
{ {
return negate(x); return negate(x);
} }
/// @copydoc sub(const vector<T, N>&, const vector<T, N>&) /// @copydoc sub(const vector<T, N>&, const vector<T, N>&)
template <class T, std::size_t N> template <class T, std::size_t N>
constexpr inline vector<T, N> operator-(const vector<T, N>& x, const vector<T, N>& y) noexcept
inline constexpr vector<T, N> operator-(const vector<T, N>& x, const vector<T, N>& y) noexcept
{ {
return sub(x, y); return sub(x, y);
} }
/// @copydoc sub(const vector<T, N>&, T) /// @copydoc sub(const vector<T, N>&, T)
template <class T, std::size_t N> template <class T, std::size_t N>
constexpr inline vector<T, N> operator-(const vector<T, N>& x, T y) noexcept
inline constexpr vector<T, N> operator-(const vector<T, N>& x, T y) noexcept
{ {
return sub(x, y); return sub(x, y);
} }
/// @copydoc sub(T, const vector<T, N>&) /// @copydoc sub(T, const vector<T, N>&)
template <class T, std::size_t N> template <class T, std::size_t N>
constexpr inline vector<T, N> operator-(T x, const vector<T, N>& y) noexcept
inline constexpr vector<T, N> operator-(T x, const vector<T, N>& y) noexcept
{ {
return sub(x, y); return sub(x, y);
} }
@ -1555,12 +1555,12 @@ constexpr inline vector operator-(T x, const vector& y) noexcept
*/ */
/// @{ /// @{
template <class T, std::size_t N> template <class T, std::size_t N>
constexpr inline vector<T, N>& operator+=(vector<T, N>& x, const vector<T, N>& y) noexcept
inline constexpr vector<T, N>& operator+=(vector<T, N>& x, const vector<T, N>& y) noexcept
{ {
return (x = x + y); return (x = x + y);
} }
template <class T, std::size_t N> template <class T, std::size_t N>
constexpr inline vector<T, N>& operator+=(vector<T, N>& x, T y) noexcept
inline constexpr vector<T, N>& operator+=(vector<T, N>& x, T y) noexcept
{ {
return (x = x + y); return (x = x + y);
} }
@ -1576,12 +1576,12 @@ constexpr inline vector& operator+=(vector& x, T y) noexcept
*/ */
/// @{ /// @{
template <class T, std::size_t N> template <class T, std::size_t N>
constexpr inline vector<T, N>& operator-=(vector<T, N>& x, const vector<T, N>& y) noexcept
inline constexpr vector<T, N>& operator-=(vector<T, N>& x, const vector<T, N>& y) noexcept
{ {
return (x = x - y); return (x = x - y);
} }
template <class T, std::size_t N> template <class T, std::size_t N>
constexpr inline vector<T, N>& operator-=(vector<T, N>& x, T y) noexcept
inline constexpr vector<T, N>& operator-=(vector<T, N>& x, T y) noexcept
{ {
return (x = x - y); return (x = x - y);
} }
@ -1597,12 +1597,12 @@ constexpr inline vector& operator-=(vector& x, T y) noexcept
*/ */
/// @{ /// @{
template <class T, std::size_t N> template <class T, std::size_t N>
constexpr inline vector<T, N>& operator*=(vector<T, N>& x, const vector<T, N>& y) noexcept
inline constexpr vector<T, N>& operator*=(vector<T, N>& x, const vector<T, N>& y) noexcept
{ {
return (x = x * y); return (x = x * y);
} }
template <class T, std::size_t N> template <class T, std::size_t N>
constexpr inline vector<T, N>& operator*=(vector<T, N>& x, T y) noexcept
inline constexpr vector<T, N>& operator*=(vector<T, N>& x, T y) noexcept
{ {
return (x = x * y); return (x = x * y);
} }
@ -1618,12 +1618,12 @@ constexpr inline vector& operator*=(vector& x, T y) noexcept
*/ */
/// @{ /// @{
template <class T, std::size_t N> template <class T, std::size_t N>
constexpr inline vector<T, N>& operator/=(vector<T, N>& x, const vector<T, N>& y) noexcept
inline constexpr vector<T, N>& operator/=(vector<T, N>& x, const vector<T, N>& y) noexcept
{ {
return (x = x / y); return (x = x / y);
} }
template <class T, std::size_t N> template <class T, std::size_t N>
constexpr inline vector<T, N>& operator/=(vector<T, N>& x, T y) noexcept
inline constexpr vector<T, N>& operator/=(vector<T, N>& x, T y) noexcept
{ {
return (x = x / y); return (x = x / y);
} }

+ 1
- 0
src/render/renderer.cpp View File

@ -32,6 +32,7 @@
#include "geom/projection.hpp" #include "geom/projection.hpp"
#include "config.hpp" #include "config.hpp"
#include "math/quaternion.hpp" #include "math/quaternion.hpp"
#include "math/constants.hpp"
#include <functional> #include <functional>
#include <set> #include <set>

+ 9
- 9
src/resources/image.hpp View File

@ -57,21 +57,21 @@ public:
*/ */
/// @{ /// @{
template <class T> template <class T>
constexpr inline T* begin() noexcept
inline constexpr T* begin() noexcept
{ {
static_assert(std::is_standard_layout<T>::value, "Pixel iterator type is not standard-layout."); static_assert(std::is_standard_layout<T>::value, "Pixel iterator type is not standard-layout.");
static_assert(std::is_trivial<T>::value, "Pixel iterator type is not trivial."); static_assert(std::is_trivial<T>::value, "Pixel iterator type is not trivial.");
return static_cast<T*>(pixels); return static_cast<T*>(pixels);
} }
template <class T> template <class T>
constexpr inline const T* begin() const noexcept
inline constexpr const T* begin() const noexcept
{ {
static_assert(std::is_standard_layout<T>::value, "Pixel iterator type is not standard-layout."); static_assert(std::is_standard_layout<T>::value, "Pixel iterator type is not standard-layout.");
static_assert(std::is_trivial<T>::value, "Pixel iterator type is not trivial."); static_assert(std::is_trivial<T>::value, "Pixel iterator type is not trivial.");
return static_cast<const T*>(pixels); return static_cast<const T*>(pixels);
} }
template <class T> template <class T>
constexpr inline const T* cbegin() const noexcept
inline constexpr const T* cbegin() const noexcept
{ {
static_assert(std::is_standard_layout<T>::value, "Pixel iterator type is not standard-layout."); static_assert(std::is_standard_layout<T>::value, "Pixel iterator type is not standard-layout.");
static_assert(std::is_trivial<T>::value, "Pixel iterator type is not trivial."); static_assert(std::is_trivial<T>::value, "Pixel iterator type is not trivial.");
@ -86,25 +86,25 @@ public:
*/ */
/// @{ /// @{
template <class T> template <class T>
constexpr inline T* end() noexcept
inline constexpr T* end() noexcept
{ {
static_assert(std::is_standard_layout<T>::value, "Pixel iterator type is not standard-layout."); static_assert(std::is_standard_layout<T>::value, "Pixel iterator type is not standard-layout.");
static_assert(std::is_trivial<T>::value, "Pixel iterator type is not trivial."); static_assert(std::is_trivial<T>::value, "Pixel iterator type is not trivial.");
return static_cast<T*>(static_cast<unsigned char*>(pixels) + size);
return reinterpret_cast<T*>(static_cast<unsigned char*>(pixels) + size);
} }
template <class T> template <class T>
constexpr inline const T* end() const noexcept
inline constexpr const T* end() const noexcept
{ {
static_assert(std::is_standard_layout<T>::value, "Pixel iterator type is not standard-layout."); static_assert(std::is_standard_layout<T>::value, "Pixel iterator type is not standard-layout.");
static_assert(std::is_trivial<T>::value, "Pixel iterator type is not trivial."); static_assert(std::is_trivial<T>::value, "Pixel iterator type is not trivial.");
return static_cast<const T*>(static_cast<const unsigned char*>(pixels) + size);
return reinterpret_cast<const T*>(static_cast<const unsigned char*>(pixels) + size);
} }
template <class T> template <class T>
constexpr inline const T* cend() const noexcept
inline constexpr const T* cend() const noexcept
{ {
static_assert(std::is_standard_layout<T>::value, "Pixel iterator type is not standard-layout."); static_assert(std::is_standard_layout<T>::value, "Pixel iterator type is not standard-layout.");
static_assert(std::is_trivial<T>::value, "Pixel iterator type is not trivial."); static_assert(std::is_trivial<T>::value, "Pixel iterator type is not trivial.");
return static_cast<const T*>(static_cast<const unsigned char*>(pixels) + size);
return reinterpret_cast<const T*>(static_cast<const unsigned char*>(pixels) + size);
} }
/// @} /// @}

Loading…
Cancel
Save