diff --git a/mplot/CartGridVisual.h b/mplot/CartGridVisual.h index 9e594b61..bab729e9 100644 --- a/mplot/CartGridVisual.h +++ b/mplot/CartGridVisual.h @@ -35,8 +35,8 @@ #define R_NSW(hi) (this->cg->d_nsw[hi]) #define R_HAS_NSW(hi) (this->cg->d_nsw[hi] == -1 ? false : true) -namespace mplot { - +namespace mplot +{ enum class CartVisMode { Triangles, // Render triangles with a triangle vertex at the centre of each Rect. diff --git a/mplot/ColourBarVisual.h b/mplot/ColourBarVisual.h index 2d4e6bea..7e1537d7 100644 --- a/mplot/ColourBarVisual.h +++ b/mplot/ColourBarVisual.h @@ -13,8 +13,8 @@ #include #include -namespace mplot { - +namespace mplot +{ // Should our colourbar be horizontal or vertical? Horizontal bars always have // min->max from left to right. Vertical bars always have min->max from bottom to // top. Make your own ColourBarVisual if you need reversed mappings! diff --git a/mplot/ColourMap.h b/mplot/ColourMap.h index 208362dc..78f4b8a2 100644 --- a/mplot/ColourMap.h +++ b/mplot/ColourMap.h @@ -16,8 +16,8 @@ #include #include -namespace mplot { - +namespace mplot +{ //! Different colour maps types. enum class ColourMapType : uint32_t { diff --git a/mplot/ColourMap_Lists.h b/mplot/ColourMap_Lists.h index c7e6e47b..0d330114 100644 --- a/mplot/ColourMap_Lists.h +++ b/mplot/ColourMap_Lists.h @@ -5,8 +5,8 @@ /*! * Listed colour maps, copied from _cm_listed.py */ -namespace mplot { - +namespace mplot +{ /*! * Magma */ diff --git a/mplot/ConeVisual.h b/mplot/ConeVisual.h index 36f89e47..abe45ca6 100644 --- a/mplot/ConeVisual.h +++ b/mplot/ConeVisual.h @@ -9,8 +9,8 @@ #include #include -namespace mplot { - +namespace mplot +{ //! A class to visualize a single vector template struct ConeVisual : public VisualModel @@ -34,5 +34,4 @@ namespace mplot { // compromise. You can set this before calling finalize(). int shapesides = 12; }; - -} // namespace mplot +} diff --git a/mplot/CoordArrows.h b/mplot/CoordArrows.h index 73f4d417..c64877f9 100644 --- a/mplot/CoordArrows.h +++ b/mplot/CoordArrows.h @@ -14,8 +14,8 @@ #include #include -namespace mplot { - +namespace mplot +{ //! This class creates the vertices for a set of coordinate arrows to be rendered //! in a 3-D scene. template diff --git a/mplot/DatasetStyle.h b/mplot/DatasetStyle.h index 17a78428..731f0c80 100644 --- a/mplot/DatasetStyle.h +++ b/mplot/DatasetStyle.h @@ -8,8 +8,8 @@ #include #include -namespace mplot { - +namespace mplot +{ // Boolean flags relating to quiver plots that form part of a DatasetStyle enum class quiver_flags : unsigned int { diff --git a/mplot/GeodesicVisual.h b/mplot/GeodesicVisual.h index 7d727781..d6b6ea18 100644 --- a/mplot/GeodesicVisual.h +++ b/mplot/GeodesicVisual.h @@ -8,8 +8,8 @@ #include #include -namespace mplot { - +namespace mplot +{ /*! * This class creates the vertices for an geodesic polyhedron in a 3D scene. * diff --git a/mplot/GeodesicVisualCE.h b/mplot/GeodesicVisualCE.h index 584e30ea..37d62696 100644 --- a/mplot/GeodesicVisualCE.h +++ b/mplot/GeodesicVisualCE.h @@ -5,8 +5,8 @@ #include #include -namespace mplot { - +namespace mplot +{ /*! * This class creates the vertices for an geodesic polyhedron in a 3D scene using * the constexpr function. diff --git a/mplot/GraphVisual.h b/mplot/GraphVisual.h index 253fea99..899541c7 100644 --- a/mplot/GraphVisual.h +++ b/mplot/GraphVisual.h @@ -34,8 +34,8 @@ #include #include -namespace mplot { - +namespace mplot +{ /*! * A VisualModel for showing a 2D graph. */ diff --git a/mplot/GratingVisual.h b/mplot/GratingVisual.h index 46704287..03833421 100644 --- a/mplot/GratingVisual.h +++ b/mplot/GratingVisual.h @@ -19,9 +19,10 @@ #include #include -namespace mplot { - - enum class border_id { +namespace mplot +{ + enum class border_id + { top, bottom, left, diff --git a/mplot/GridFeatures.h b/mplot/GridFeatures.h index 0e1b7127..fc21aa65 100644 --- a/mplot/GridFeatures.h +++ b/mplot/GridFeatures.h @@ -9,16 +9,18 @@ */ #pragma once -namespace mplot { - +namespace mplot +{ //! The shape of the cartesian grid. Only used by CartGrid.h as Grid.h only specifies rectangular grids. - enum class GridDomainShape { + enum class GridDomainShape + { Rectangle, Boundary // The shape of the arbitrary boundary set with CartGrid::setBoundary }; //! The wrapping employed for the Cartesian grid. - enum class GridDomainWrap { + enum class GridDomainWrap + { None, // No wrapping Horizontal, // The eastern neighbour of the most eastern element is the most western element on that row Vertical, // The northern neighbour of the most northern element is the most southern element on that col diff --git a/mplot/GridVisual.h b/mplot/GridVisual.h index 77811ae0..7e4faedb 100644 --- a/mplot/GridVisual.h +++ b/mplot/GridVisual.h @@ -12,8 +12,8 @@ #include #include -namespace mplot { - +namespace mplot +{ /*! * How to visualize a grid. You could draw a triangle map with vertices at the centres of the * elements or you could draw a rectangular pixel for each element. Triangles is diff --git a/mplot/HSVWheelVisual.h b/mplot/HSVWheelVisual.h index 9d12605f..561d4346 100644 --- a/mplot/HSVWheelVisual.h +++ b/mplot/HSVWheelVisual.h @@ -10,8 +10,8 @@ #include #include -namespace mplot { - +namespace mplot +{ template class HSVWheelVisual : public VisualModel { diff --git a/mplot/HealpixVisual.h b/mplot/HealpixVisual.h index 99514361..d5974969 100644 --- a/mplot/HealpixVisual.h +++ b/mplot/HealpixVisual.h @@ -8,7 +8,8 @@ #include #include -namespace mplot { +namespace mplot +{ /* * Type T for the data. A HEALPix VisualModel which visualizes the values in * pixeldata, which should be indexed with the Healpix NEST index scheme. diff --git a/mplot/HexGridVisual.h b/mplot/HexGridVisual.h index 27ee04e9..b4b77d84 100644 --- a/mplot/HexGridVisual.h +++ b/mplot/HexGridVisual.h @@ -48,8 +48,8 @@ #define IF_HAS_NSW(hi, yesval, noval) (HAS_NSW(hi) ? yesval : noval) #define IF_HAS_NSE(hi, yesval, noval) (HAS_NSE(hi) ? yesval : noval) -namespace mplot { - +namespace mplot +{ enum class HexVisMode { Triangles, // Render triangles with a triangle vertex at the centre of each Hex. Fast (x3.7 cf. HexInterp). diff --git a/mplot/IcosaVisual.h b/mplot/IcosaVisual.h index 7022b205..fd293658 100644 --- a/mplot/IcosaVisual.h +++ b/mplot/IcosaVisual.h @@ -5,8 +5,8 @@ #include #include -namespace mplot { - +namespace mplot +{ //! This class creates the vertices for an icosahedron in a 3D scene. template class IcosaVisual : public VisualModel diff --git a/mplot/NormalsVisual.h b/mplot/NormalsVisual.h index 4a92e8cb..dfeb1a48 100644 --- a/mplot/NormalsVisual.h +++ b/mplot/NormalsVisual.h @@ -9,8 +9,8 @@ #include #include -namespace mplot { - +namespace mplot +{ //! A class to visualize normals for another model template class NormalsVisual : public VisualModel diff --git a/mplot/PointRowsMeshVisual.h b/mplot/PointRowsMeshVisual.h index f06d0f63..6a31f474 100644 --- a/mplot/PointRowsMeshVisual.h +++ b/mplot/PointRowsMeshVisual.h @@ -12,8 +12,8 @@ #include #include -namespace mplot { - +namespace mplot +{ /*! * The template argument Flt is the type of the data which this PointRowsMeshVisual * will visualize. diff --git a/mplot/PointRowsVisual.h b/mplot/PointRowsVisual.h index ca66c5d6..492c3866 100644 --- a/mplot/PointRowsVisual.h +++ b/mplot/PointRowsVisual.h @@ -11,8 +11,8 @@ #include #include -namespace mplot { - +namespace mplot +{ /*! * The template argument Flt is the type of the data which this PointRowsVisual will visualize. * diff --git a/mplot/PolygonVisual.h b/mplot/PolygonVisual.h index d84fdf18..360e37b5 100644 --- a/mplot/PolygonVisual.h +++ b/mplot/PolygonVisual.h @@ -4,8 +4,8 @@ #include #include -namespace mplot { - +namespace mplot +{ //! This class creates the vertices for a polygonal object in a 3D scene template class PolygonVisual : public VisualModel diff --git a/mplot/QuadsMeshVisual.h b/mplot/QuadsMeshVisual.h index 1809a1e1..6d751be6 100644 --- a/mplot/QuadsMeshVisual.h +++ b/mplot/QuadsMeshVisual.h @@ -13,8 +13,8 @@ #include #include -namespace mplot { - +namespace mplot +{ template class QuadsMeshVisual : public VisualDataModel { diff --git a/mplot/QuadsVisual.h b/mplot/QuadsVisual.h index 397384ca..d4e3c417 100644 --- a/mplot/QuadsVisual.h +++ b/mplot/QuadsVisual.h @@ -12,8 +12,8 @@ #include #include -namespace mplot { - +namespace mplot +{ template class QuadsVisual : public VisualDataModel { diff --git a/mplot/QuiverVisual.h b/mplot/QuiverVisual.h index 75aff18c..52f9edec 100644 --- a/mplot/QuiverVisual.h +++ b/mplot/QuiverVisual.h @@ -15,8 +15,8 @@ #include #include -namespace mplot { - +namespace mplot +{ //! A class to make quiver plots template class QuiverVisual : public VisualDataModel diff --git a/mplot/RectangleVisual.h b/mplot/RectangleVisual.h index c1bc479c..e8934b10 100644 --- a/mplot/RectangleVisual.h +++ b/mplot/RectangleVisual.h @@ -6,8 +6,8 @@ #include #include -namespace mplot { - +namespace mplot +{ //! This class creates the vertices for a simple flat rectangle in a 3D scene. template class RectangleVisual : public VisualModel diff --git a/mplot/RhomboVisual.h b/mplot/RhomboVisual.h index 392f7f6f..a06b2694 100644 --- a/mplot/RhomboVisual.h +++ b/mplot/RhomboVisual.h @@ -5,8 +5,8 @@ #include #include -namespace mplot { - +namespace mplot +{ //! This class creates the vertices for a rhombohedron template class RhomboVisual : public VisualModel diff --git a/mplot/RingVisual.h b/mplot/RingVisual.h index cc0a2b19..a6e8ec90 100644 --- a/mplot/RingVisual.h +++ b/mplot/RingVisual.h @@ -4,8 +4,8 @@ #include #include -namespace mplot { - +namespace mplot +{ // A simple ring class that uses the primitive VisualModel::computeRing template struct RingVisual : public mplot::VisualModel diff --git a/mplot/RodVisual.h b/mplot/RodVisual.h index 8bf95b7d..c15a2738 100644 --- a/mplot/RodVisual.h +++ b/mplot/RodVisual.h @@ -5,8 +5,8 @@ #include #include -namespace mplot { - +namespace mplot +{ //! This class creates the vertices for a cylindrical 'rod' in a 3D scene. template class RodVisual : public VisualModel diff --git a/mplot/ScatterVisual.h b/mplot/ScatterVisual.h index 6a5fac3c..98d3e9af 100644 --- a/mplot/ScatterVisual.h +++ b/mplot/ScatterVisual.h @@ -14,8 +14,8 @@ #include #include -namespace mplot { - +namespace mplot +{ //! The template argument Flt is the type of the data which this ScatterVisual //! will visualize. template diff --git a/mplot/TextFeatures.h b/mplot/TextFeatures.h index 66f13a28..e8d73664 100644 --- a/mplot/TextFeatures.h +++ b/mplot/TextFeatures.h @@ -4,8 +4,8 @@ #include #include -namespace mplot { - +namespace mplot +{ // A way to bundle up font size, colour, etc into a single object. Constructors chosen for max convenience. struct TextFeatures { diff --git a/mplot/TextGeometry.h b/mplot/TextGeometry.h index c0e6f945..9cc9815a 100644 --- a/mplot/TextGeometry.h +++ b/mplot/TextGeometry.h @@ -1,6 +1,7 @@ #pragma once -namespace mplot { +namespace mplot +{ /*! * A class containing information about a text string, as it would be displayed on * the screen in some font, at a given size. The units should be the same as those diff --git a/mplot/TriFrameVisual.h b/mplot/TriFrameVisual.h index f65aaf32..5baf8e00 100644 --- a/mplot/TriFrameVisual.h +++ b/mplot/TriFrameVisual.h @@ -11,8 +11,8 @@ #include #include -namespace mplot { - +namespace mplot +{ /*! * The template argument Flt is the type of the data which this PointRowsMeshVisual * will visualize. diff --git a/mplot/TriangleVisual.h b/mplot/TriangleVisual.h index 6b457158..d25bef26 100644 --- a/mplot/TriangleVisual.h +++ b/mplot/TriangleVisual.h @@ -4,8 +4,8 @@ #include #include -namespace mplot { - +namespace mplot +{ //! This class creates the vertices for a simple triangle in a 3D scene. template class TriangleVisual : public VisualModel diff --git a/mplot/TriaxesVisual.h b/mplot/TriaxesVisual.h index 051d587c..dbec4d7e 100644 --- a/mplot/TriaxesVisual.h +++ b/mplot/TriaxesVisual.h @@ -13,8 +13,8 @@ #include #include // Share tickstyle, axestyle -namespace mplot { - +namespace mplot +{ template class TriaxesVisual : public VisualModel { diff --git a/mplot/TxtVisual.h b/mplot/TxtVisual.h index 3a6b9ec5..5cbbdcd7 100644 --- a/mplot/TxtVisual.h +++ b/mplot/TxtVisual.h @@ -14,8 +14,8 @@ #include #include -namespace mplot { - +namespace mplot +{ template class TxtVisual : public VisualModel { @@ -38,5 +38,4 @@ namespace mplot { std::string text; mplot::TextFeatures tfeatures; }; - -} // namespace mplot +} diff --git a/mplot/VectorVisual.h b/mplot/VectorVisual.h index e7407f7c..af405b43 100644 --- a/mplot/VectorVisual.h +++ b/mplot/VectorVisual.h @@ -10,12 +10,13 @@ #include #include -namespace mplot { - +namespace mplot +{ //! How should the visualized vector go? Does it start at the origin? If so, it goes 'from' //! the origin; FromOrigin. Does it instead sit on top of the origin (OnOrigin)? //! Alternatively, it could go 'to' the origin; ToOrigin. - enum class VectorGoes { + enum class VectorGoes + { FromOrigin, ToOrigin, OnOrigin diff --git a/mplot/Visual.h b/mplot/Visual.h index b851d09a..f0960bde 100644 --- a/mplot/Visual.h +++ b/mplot/Visual.h @@ -15,8 +15,8 @@ #include -namespace mplot { - +namespace mplot +{ /*! * Visual 'scene' class * diff --git a/mplot/VisualBase.h b/mplot/VisualBase.h index 25940c46..de7dff63 100644 --- a/mplot/VisualBase.h +++ b/mplot/VisualBase.h @@ -44,8 +44,8 @@ #define LODEPNG_NO_COMPILE_ANCILLARY_CHUNKS 1 #include -namespace mplot { - +namespace mplot +{ //! Here are our boolean state flags enum class visual_state : uint32_t { diff --git a/mplot/VisualCommon.h b/mplot/VisualCommon.h index 5607c467..e20aad04 100644 --- a/mplot/VisualCommon.h +++ b/mplot/VisualCommon.h @@ -12,47 +12,43 @@ #include #include -namespace mplot { - - namespace visgl { - - // A container struct for the shader program identifiers used in a mplot::Visual. Separate - // from mplot::Visual so that it can be used in mplot::VisualModel as well, which does not - // #include mplot/Visual.h. - struct visual_shaderprogs - { - //! An OpenGL shader program for graphical objects - unsigned int /*GLuint*/ gprog = 0; - //! A text shader program, which uses textures to draw text on quads. - unsigned int /*GLuint*/ tprog = 0; - }; - - // This defines different graphics shader types, as used in mplot::Visual. The essential - // difference between the current shaders is that they render different projection types - enum class graphics_shader_type - { - none, // Unset/unknown graphics shader type - projection2d, // both orthographic and perspective projections to a 2D surface - cylindrical, // A cylindrical projection - spherical // not implemented, but we could have a spherical projection - }; - - //! The locations for the position, normal and colour vertex attributes in the - //! mplot::Visual GLSL programs - enum AttribLocn { posnLoc = 0, normLoc = 1, colLoc = 2, textureLoc = 3 }; - - //! A struct to hold information about font glyph properties - struct CharInfo - { - //! ID handle of the glyph texture - unsigned int textureID; - //! Size of glyph - sm::vec size; - //! Offset from baseline to left/top of glyph - sm::vec bearing; - //! Offset to advance to next glyph - unsigned int advance; - }; - - } // namespace gl +namespace mplot::visgl +{ + // A container struct for the shader program identifiers used in a mplot::Visual. Separate + // from mplot::Visual so that it can be used in mplot::VisualModel as well, which does not + // #include mplot/Visual.h. + struct visual_shaderprogs + { + //! An OpenGL shader program for graphical objects + unsigned int /*GLuint*/ gprog = 0; + //! A text shader program, which uses textures to draw text on quads. + unsigned int /*GLuint*/ tprog = 0; + }; + + // This defines different graphics shader types, as used in mplot::Visual. The essential + // difference between the current shaders is that they render different projection types + enum class graphics_shader_type + { + none, // Unset/unknown graphics shader type + projection2d, // both orthographic and perspective projections to a 2D surface + cylindrical, // A cylindrical projection + spherical // not implemented, but we could have a spherical projection + }; + + //! The locations for the position, normal and colour vertex attributes in the + //! mplot::Visual GLSL programs + enum AttribLocn { posnLoc = 0, normLoc = 1, colLoc = 2, textureLoc = 3 }; + + //! A struct to hold information about font glyph properties + struct CharInfo + { + //! ID handle of the glyph texture + unsigned int textureID; + //! Size of glyph + sm::vec size; + //! Offset from baseline to left/top of glyph + sm::vec bearing; + //! Offset to advance to next glyph + unsigned int advance; + }; } // namespace diff --git a/mplot/VisualDefaultShaders.h b/mplot/VisualDefaultShaders.h index 169bdfe6..e88c68d7 100644 --- a/mplot/VisualDefaultShaders.h +++ b/mplot/VisualDefaultShaders.h @@ -95,8 +95,8 @@ OpenGL 4.5 #include -namespace mplot { - +namespace mplot +{ // The default vertex shader. To study this GLSL, see Visual.vert.glsl, which has // some code comments. const char* defaultVtxShader = "uniform mat4 m_matrix;\n" diff --git a/mplot/VisualFaceBase.h b/mplot/VisualFaceBase.h index 7574ae36..b1f11841 100644 --- a/mplot/VisualFaceBase.h +++ b/mplot/VisualFaceBase.h @@ -161,256 +161,253 @@ extern const char __start_dvsansbi_ttf[]; extern const char __stop_dvsansbi_ttf[]; #endif -namespace mplot { +namespace mplot::visgl +{ + struct VisualFaceBase + { + VisualFaceBase () {} + ~VisualFaceBase () {} - namespace visgl { + //! Set true for informational/debug messages + static constexpr bool debug_visualface = false; - struct VisualFaceBase - { - VisualFaceBase () {} - ~VisualFaceBase () {} - - //! Set true for informational/debug messages - static constexpr bool debug_visualface = false; + //! The FT_Face that we're managing + FT_Face face; - //! The FT_Face that we're managing - FT_Face face; + //! The OpenGL character info stuff + std::map glchars; - //! The OpenGL character info stuff - std::map glchars; + protected: - protected: + void init_common (const mplot::VisualFont _font, unsigned int fontpixels, FT_Library& ft_freetype) + { + std::string fontpath = ""; +#ifdef _MSC_VER + char* userprofile = getenv ("USERPROFILE"); + std::string uppath(""); + if (userprofile != nullptr) { + uppath = std::string (userprofile); + } - void init_common (const mplot::VisualFont _font, unsigned int fontpixels, FT_Library& ft_freetype) + switch (_font) { + case VisualFont::DVSans: { - std::string fontpath = ""; -#ifdef _MSC_VER - char* userprofile = getenv ("USERPROFILE"); - std::string uppath(""); - if (userprofile != nullptr) { - uppath = std::string (userprofile); - } - - switch (_font) { - case VisualFont::DVSans: - { - fontpath = uppath + "\\AppData\\Local\\Temp\\DejaVuSans.ttf"; - this->makeTempFontFile (fontpath, vf_dvsansData, vf_dvsansEnd); - break; - } - case VisualFont::DVSansItalic: - { - fontpath = uppath + "\\AppData\\Local\\Temp\\DejaVuSans-Oblique.ttf"; - this->makeTempFontFile (fontpath, vf_dvsansitData, vf_dvsansitEnd); - break; - } - case VisualFont::DVSansBold: - { - fontpath = uppath + "\\AppData\\Local\\Temp\\DejaVuSans-Bold.ttf"; - this->makeTempFontFile (fontpath, vf_dvsansbdData, vf_dvsansbdEnd); - break; - } - case VisualFont::DVSansBoldItalic: - { - fontpath = uppath + "\\AppData\\Local\\Temp\\DejaVuSans-BoldOblique.ttf"; - this->makeTempFontFile (fontpath, vf_dvsansbiData, vf_dvsansbiEnd); - break; - } - case VisualFont::Vera: - { - fontpath = uppath + "\\AppData\\Local\\Temp\\Vera.ttf"; - this->makeTempFontFile (fontpath, vf_veraData, vf_veraEnd); - break; - } - case VisualFont::VeraItalic: - { - fontpath = uppath + "\\AppData\\Local\\Temp\\VeraIt.ttf"; - this->makeTempFontFile (fontpath, vf_veraitData, vf_veraitEnd); - break; - } - case VisualFont::VeraBold: - { - fontpath = uppath + "\\AppData\\Local\\Temp\\VeraBd.ttf"; - this->makeTempFontFile (fontpath, vf_verabdData, vf_verabdEnd); - break; - } - case VisualFont::VeraBoldItalic: - { - fontpath = uppath + "\\AppData\\Local\\Temp\\VeraBI.ttf"; - this->makeTempFontFile (fontpath, vf_verabiData, vf_verabiEnd); - break; - } - case VisualFont::VeraMono: - { - fontpath = uppath + "\\AppData\\Local\\Temp\\VeraMono.ttf"; - this->makeTempFontFile (fontpath, vf_veramonoData, vf_veramonoEnd); - break; - } - case VisualFont::VeraMonoBold: - { - fontpath = uppath + "\\AppData\\Local\\Temp\\VeraMoBd.ttf"; - this->makeTempFontFile (fontpath, vf_veramobdData, vf_veramobdEnd); - break; - } - case VisualFont::VeraMonoItalic: - { - fontpath = uppath + "\\AppData\\Local\\Temp\\VeraMoIt.ttf"; - this->makeTempFontFile (fontpath, vf_veramoitData, vf_veramoitEnd); - break; - } - case VisualFont::VeraMonoBoldItalic: - { - fontpath = uppath + "\\AppData\\Local\\Temp\\VeraMoBI.ttf"; - this->makeTempFontFile (fontpath, vf_veramobiData, vf_veramobiEnd); - break; - } - case VisualFont::VeraSerif: - { - fontpath = uppath + "\\AppData\\Local\\Temp\\VeraSe.ttf"; - this->makeTempFontFile (fontpath, vf_veraseData, vf_veraseEnd); - break; - } - case VisualFont::VeraSerifBold: - { - fontpath = uppath + "\\AppData\\Local\\Temp\\VeraSeBd.ttf"; - this->makeTempFontFile (fontpath, vf_verasebdData, vf_verasebdEnd); - break; - } - default: - { - std::cout << "ERROR::Unsupported mplot font\n"; - break; - } - } + fontpath = uppath + "\\AppData\\Local\\Temp\\DejaVuSans.ttf"; + this->makeTempFontFile (fontpath, vf_dvsansData, vf_dvsansEnd); + break; + } + case VisualFont::DVSansItalic: + { + fontpath = uppath + "\\AppData\\Local\\Temp\\DejaVuSans-Oblique.ttf"; + this->makeTempFontFile (fontpath, vf_dvsansitData, vf_dvsansitEnd); + break; + } + case VisualFont::DVSansBold: + { + fontpath = uppath + "\\AppData\\Local\\Temp\\DejaVuSans-Bold.ttf"; + this->makeTempFontFile (fontpath, vf_dvsansbdData, vf_dvsansbdEnd); + break; + } + case VisualFont::DVSansBoldItalic: + { + fontpath = uppath + "\\AppData\\Local\\Temp\\DejaVuSans-BoldOblique.ttf"; + this->makeTempFontFile (fontpath, vf_dvsansbiData, vf_dvsansbiEnd); + break; + } + case VisualFont::Vera: + { + fontpath = uppath + "\\AppData\\Local\\Temp\\Vera.ttf"; + this->makeTempFontFile (fontpath, vf_veraData, vf_veraEnd); + break; + } + case VisualFont::VeraItalic: + { + fontpath = uppath + "\\AppData\\Local\\Temp\\VeraIt.ttf"; + this->makeTempFontFile (fontpath, vf_veraitData, vf_veraitEnd); + break; + } + case VisualFont::VeraBold: + { + fontpath = uppath + "\\AppData\\Local\\Temp\\VeraBd.ttf"; + this->makeTempFontFile (fontpath, vf_verabdData, vf_verabdEnd); + break; + } + case VisualFont::VeraBoldItalic: + { + fontpath = uppath + "\\AppData\\Local\\Temp\\VeraBI.ttf"; + this->makeTempFontFile (fontpath, vf_verabiData, vf_verabiEnd); + break; + } + case VisualFont::VeraMono: + { + fontpath = uppath + "\\AppData\\Local\\Temp\\VeraMono.ttf"; + this->makeTempFontFile (fontpath, vf_veramonoData, vf_veramonoEnd); + break; + } + case VisualFont::VeraMonoBold: + { + fontpath = uppath + "\\AppData\\Local\\Temp\\VeraMoBd.ttf"; + this->makeTempFontFile (fontpath, vf_veramobdData, vf_veramobdEnd); + break; + } + case VisualFont::VeraMonoItalic: + { + fontpath = uppath + "\\AppData\\Local\\Temp\\VeraMoIt.ttf"; + this->makeTempFontFile (fontpath, vf_veramoitData, vf_veramoitEnd); + break; + } + case VisualFont::VeraMonoBoldItalic: + { + fontpath = uppath + "\\AppData\\Local\\Temp\\VeraMoBI.ttf"; + this->makeTempFontFile (fontpath, vf_veramobiData, vf_veramobiEnd); + break; + } + case VisualFont::VeraSerif: + { + fontpath = uppath + "\\AppData\\Local\\Temp\\VeraSe.ttf"; + this->makeTempFontFile (fontpath, vf_veraseData, vf_veraseEnd); + break; + } + case VisualFont::VeraSerifBold: + { + fontpath = uppath + "\\AppData\\Local\\Temp\\VeraSeBd.ttf"; + this->makeTempFontFile (fontpath, vf_verasebdData, vf_verasebdEnd); + break; + } + default: + { + std::cout << "ERROR::Unsupported mplot font\n"; + break; + } + } #else // Non-windows: - switch (_font) { - case VisualFont::DVSans: - { - fontpath = "/tmp/DejaVuSans.ttf"; - this->makeTempFontFile (fontpath, __start_dvsans_ttf, __stop_dvsans_ttf); - break; - } - case VisualFont::DVSansItalic: - { - fontpath = "/tmp/DejaVuSans-Oblique.ttf"; - this->makeTempFontFile (fontpath, __start_dvsansit_ttf, __stop_dvsansit_ttf); - break; - } - case VisualFont::DVSansBold: - { - fontpath = "/tmp/DejaVuSans-Bold.ttf"; - this->makeTempFontFile (fontpath, __start_dvsansbd_ttf, __stop_dvsansbd_ttf); - break; - } - case VisualFont::DVSansBoldItalic: - { - fontpath = "/tmp/DejaVuSans-BoldOblique.ttf"; - this->makeTempFontFile (fontpath, __start_dvsansbi_ttf, __stop_dvsansbi_ttf); - break; - } - case VisualFont::Vera: - { - fontpath = "/tmp/Vera.ttf"; - this->makeTempFontFile (fontpath, __start_vera_ttf, __stop_vera_ttf); - break; - } - case VisualFont::VeraItalic: - { - fontpath = "/tmp/VeraIt.ttf"; - this->makeTempFontFile (fontpath, __start_verait_ttf, __stop_verait_ttf); - break; - } - case VisualFont::VeraBold: - { - fontpath = "/tmp/VeraBd.ttf"; - this->makeTempFontFile (fontpath, __start_verabd_ttf, __stop_verabd_ttf); - break; - } - case VisualFont::VeraBoldItalic: - { - fontpath = "/tmp/VeraBI.ttf"; - this->makeTempFontFile (fontpath, __start_verabi_ttf, __stop_verabi_ttf); - break; - } - case VisualFont::VeraMono: - { - fontpath = "/tmp/VeraMono.ttf"; - this->makeTempFontFile (fontpath, __start_veramono_ttf, __stop_veramono_ttf); - break; - } - case VisualFont::VeraMonoBold: - { - fontpath = "/tmp/VeraMoBd.ttf"; - this->makeTempFontFile (fontpath, __start_veramobd_ttf, __stop_veramobd_ttf); - break; - } - case VisualFont::VeraMonoItalic: - { - fontpath = "/tmp/VeraMoIt.ttf"; - this->makeTempFontFile (fontpath, __start_veramoit_ttf, __stop_veramoit_ttf); - break; - } - case VisualFont::VeraMonoBoldItalic: - { - fontpath = "/tmp/VeraMoBI.ttf"; - this->makeTempFontFile (fontpath, __start_veramobi_ttf, __stop_veramobi_ttf); - break; - } - case VisualFont::VeraSerif: - { - fontpath = "/tmp/VeraSe.ttf"; - this->makeTempFontFile (fontpath, __start_verase_ttf, __stop_verase_ttf); - break; - } - case VisualFont::VeraSerifBold: - { - fontpath = "/tmp/VeraSeBd.ttf"; - this->makeTempFontFile (fontpath, __start_verasebd_ttf, __stop_verasebd_ttf); - break; - } - default: - { - std::cout << "ERROR::Unsupported mplot font\n"; - break; - } - } + switch (_font) { + case VisualFont::DVSans: + { + fontpath = "/tmp/DejaVuSans.ttf"; + this->makeTempFontFile (fontpath, __start_dvsans_ttf, __stop_dvsans_ttf); + break; + } + case VisualFont::DVSansItalic: + { + fontpath = "/tmp/DejaVuSans-Oblique.ttf"; + this->makeTempFontFile (fontpath, __start_dvsansit_ttf, __stop_dvsansit_ttf); + break; + } + case VisualFont::DVSansBold: + { + fontpath = "/tmp/DejaVuSans-Bold.ttf"; + this->makeTempFontFile (fontpath, __start_dvsansbd_ttf, __stop_dvsansbd_ttf); + break; + } + case VisualFont::DVSansBoldItalic: + { + fontpath = "/tmp/DejaVuSans-BoldOblique.ttf"; + this->makeTempFontFile (fontpath, __start_dvsansbi_ttf, __stop_dvsansbi_ttf); + break; + } + case VisualFont::Vera: + { + fontpath = "/tmp/Vera.ttf"; + this->makeTempFontFile (fontpath, __start_vera_ttf, __stop_vera_ttf); + break; + } + case VisualFont::VeraItalic: + { + fontpath = "/tmp/VeraIt.ttf"; + this->makeTempFontFile (fontpath, __start_verait_ttf, __stop_verait_ttf); + break; + } + case VisualFont::VeraBold: + { + fontpath = "/tmp/VeraBd.ttf"; + this->makeTempFontFile (fontpath, __start_verabd_ttf, __stop_verabd_ttf); + break; + } + case VisualFont::VeraBoldItalic: + { + fontpath = "/tmp/VeraBI.ttf"; + this->makeTempFontFile (fontpath, __start_verabi_ttf, __stop_verabi_ttf); + break; + } + case VisualFont::VeraMono: + { + fontpath = "/tmp/VeraMono.ttf"; + this->makeTempFontFile (fontpath, __start_veramono_ttf, __stop_veramono_ttf); + break; + } + case VisualFont::VeraMonoBold: + { + fontpath = "/tmp/VeraMoBd.ttf"; + this->makeTempFontFile (fontpath, __start_veramobd_ttf, __stop_veramobd_ttf); + break; + } + case VisualFont::VeraMonoItalic: + { + fontpath = "/tmp/VeraMoIt.ttf"; + this->makeTempFontFile (fontpath, __start_veramoit_ttf, __stop_veramoit_ttf); + break; + } + case VisualFont::VeraMonoBoldItalic: + { + fontpath = "/tmp/VeraMoBI.ttf"; + this->makeTempFontFile (fontpath, __start_veramobi_ttf, __stop_veramobi_ttf); + break; + } + case VisualFont::VeraSerif: + { + fontpath = "/tmp/VeraSe.ttf"; + this->makeTempFontFile (fontpath, __start_verase_ttf, __stop_verase_ttf); + break; + } + case VisualFont::VeraSerifBold: + { + fontpath = "/tmp/VeraSeBd.ttf"; + this->makeTempFontFile (fontpath, __start_verasebd_ttf, __stop_verasebd_ttf); + break; + } + default: + { + std::cout << "ERROR::Unsupported mplot font\n"; + break; + } + } #endif // Windows/Non-windows - // Keep the face as a mplot::Visual owned resource, shared by VisTextModels? - if constexpr (debug_visualface == true) { - std::cout << "FT_New_Face (ft_freetype, " << fontpath << ", 0, &this->face);\n"; - } - if (FT_New_Face (ft_freetype, fontpath.c_str(), 0, &this->face)) { - std::cout << "ERROR::FREETYPE: Failed to load font (font file may be invalid)" << std::endl; - } + // Keep the face as a mplot::Visual owned resource, shared by VisTextModels? + if constexpr (debug_visualface == true) { + std::cout << "FT_New_Face (ft_freetype, " << fontpath << ", 0, &this->face);\n"; + } + if (FT_New_Face (ft_freetype, fontpath.c_str(), 0, &this->face)) { + std::cout << "ERROR::FREETYPE: Failed to load font (font file may be invalid)" << std::endl; + } - FT_Set_Pixel_Sizes (this->face, 0, fontpixels); + FT_Set_Pixel_Sizes (this->face, 0, fontpixels); - // Can I check this->face for how many glyphs it has? Yes: - // std::cout << "This face has " << this->face->num_glyphs << " glyphs.\n"; - } + // Can I check this->face for how many glyphs it has? Yes: + // std::cout << "This face has " << this->face->num_glyphs << " glyphs.\n"; + } - //! Create a temporary font file at fontpath, using the embedded data - //! starting from filestart and extending to filenend - template - void makeTempFontFile (const std::string& fontpath, T* file_start, T* file_stop) - { - T* p; - if (!mplot::tools::fileExists (fontpath)) { - std::ofstream fout; - fout.open (fontpath.c_str(), std::ios::out | std::ios::trunc | std::ios::binary); - if (fout.is_open()) { - for (p = file_start; p < file_stop; p++) { fout << *p; } - fout.close(); - } else { - std::cout << "WARNING: Failed to open " << fontpath << "!!\n"; - } + //! Create a temporary font file at fontpath, using the embedded data + //! starting from filestart and extending to filenend + template + void makeTempFontFile (const std::string& fontpath, T* file_start, T* file_stop) + { + T* p; + if (!mplot::tools::fileExists (fontpath)) { + std::ofstream fout; + fout.open (fontpath.c_str(), std::ios::out | std::ios::trunc | std::ios::binary); + if (fout.is_open()) { + for (p = file_start; p < file_stop; p++) { fout << *p; } + fout.close(); } else { - if constexpr (debug_visualface == true) { - std::cout << "INFO: " << fontpath << " already exists, no need to re-create it\n"; - } + std::cout << "WARNING: Failed to open " << fontpath << "!!\n"; + } + } else { + if constexpr (debug_visualface == true) { + std::cout << "INFO: " << fontpath << " already exists, no need to re-create it\n"; } } - }; - } // namespace gl -} // namespace mplot + } + }; +} // namespace diff --git a/mplot/VisualFaceMX.h b/mplot/VisualFaceMX.h index 849a7485..2320e221 100644 --- a/mplot/VisualFaceMX.h +++ b/mplot/VisualFaceMX.h @@ -21,87 +21,84 @@ # error "GL headers should have been included already" #endif -namespace mplot { - - namespace visgl { - - struct VisualFaceMX : public mplot::visgl::VisualFaceBase +namespace mplot::visgl +{ + struct VisualFaceMX : public mplot::visgl::VisualFaceBase + { + /*! + * Construct with a mplot::VisualFont \a _font, which specifies a supported + * font (one which we can legally include in the source code without paying any licence fees, + * e.g. Bitstream Vera) and \a fontpixels, which is the texture size, + * e.g. 192. This is the width, in pixels, of the texture that would be + * applied to the letter 'm'. A larger value is required for fonts that will + * take up a large part of the screen, but will be detrimental to the + * appearance of a font which is rendered 'small on the screen'. + * + * VisualResources holds a map of VisualFace instances, to avoid many copies + * of font textures for separate VisualTextModel instances which might have + * the same pixel size. + */ + VisualFaceMX (const mplot::VisualFont _font, unsigned int fontpixels, FT_Library& ft_freetype, + GladGLContext* glfn = nullptr) { - /*! - * Construct with a mplot::VisualFont \a _font, which specifies a supported - * font (one which we can legally include in the source code without paying any licence fees, - * e.g. Bitstream Vera) and \a fontpixels, which is the texture size, - * e.g. 192. This is the width, in pixels, of the texture that would be - * applied to the letter 'm'. A larger value is required for fonts that will - * take up a large part of the screen, but will be detrimental to the - * appearance of a font which is rendered 'small on the screen'. - * - * VisualResources holds a map of VisualFace instances, to avoid many copies - * of font textures for separate VisualTextModel instances which might have - * the same pixel size. - */ - VisualFaceMX (const mplot::VisualFont _font, unsigned int fontpixels, FT_Library& ft_freetype, - GladGLContext* glfn = nullptr) - { - this->init_common (_font, fontpixels, ft_freetype); + this->init_common (_font, fontpixels, ft_freetype); - // How far to loop. In principle, up to 21 bits worth - that's 2097151 possible characters! - for (char32_t c = 0; c < 2097151; c++) { - // Check glyph index first, if it's 0 it's a blank so skip. - if (FT_Get_Char_Index (this->face, c) == 0) { continue; } + // How far to loop. In principle, up to 21 bits worth - that's 2097151 possible characters! + for (char32_t c = 0; c < 2097151; c++) { + // Check glyph index first, if it's 0 it's a blank so skip. + if (FT_Get_Char_Index (this->face, c) == 0) { continue; } - // load character glyph - if (FT_Load_Char (this->face, c, FT_LOAD_RENDER)) { - std::cout << "ERROR::FREETYPE: Failed to load Glyph for Unicode 0x" - << std::hex << static_cast(c) << std::dec << std::endl; - continue; - } + // load character glyph + if (FT_Load_Char (this->face, c, FT_LOAD_RENDER)) { + std::cout << "ERROR::FREETYPE: Failed to load Glyph for Unicode 0x" + << std::hex << static_cast(c) << std::dec << std::endl; + continue; + } - // generate texture - unsigned int texture = 0; + // generate texture + unsigned int texture = 0; - if (glfn == nullptr) { throw std::runtime_error ("glfn problem"); } - glfn->GenTextures (1, &texture); - glfn->BindTexture (GL_TEXTURE_2D, texture); - glfn->TexImage2D( - GL_TEXTURE_2D, - 0, - GL_RED, - this->face->glyph->bitmap.width, - this->face->glyph->bitmap.rows, - 0, - GL_RED, - GL_UNSIGNED_BYTE, - this->face->glyph->bitmap.buffer - ); - // set texture options - glfn->TexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glfn->TexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glfn->TexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glfn->TexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // Could be GL_NEAREST, but doesn't look as good. + if (glfn == nullptr) { throw std::runtime_error ("glfn problem"); } + glfn->GenTextures (1, &texture); + glfn->BindTexture (GL_TEXTURE_2D, texture); + glfn->TexImage2D( + GL_TEXTURE_2D, + 0, + GL_RED, + this->face->glyph->bitmap.width, + this->face->glyph->bitmap.rows, + 0, + GL_RED, + GL_UNSIGNED_BYTE, + this->face->glyph->bitmap.buffer + ); + // set texture options + glfn->TexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glfn->TexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glfn->TexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glfn->TexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // Could be GL_NEAREST, but doesn't look as good. - // now store character for later use - mplot::visgl::CharInfo glchar = { - texture, - {static_cast(this->face->glyph->bitmap.width), static_cast(this->face->glyph->bitmap.rows)}, // size - {this->face->glyph->bitmap_left, this->face->glyph->bitmap_top}, // bearing - static_cast(this->face->glyph->advance.x) // advance - }; + // now store character for later use + mplot::visgl::CharInfo glchar = { + texture, + {static_cast(this->face->glyph->bitmap.width), static_cast(this->face->glyph->bitmap.rows)}, // size + {this->face->glyph->bitmap_left, this->face->glyph->bitmap_top}, // bearing + static_cast(this->face->glyph->advance.x) // advance + }; - if constexpr (debug_visualface == true) { - std::cout << "Inserting character into this->glchars with info: ID:" << glchar.textureID - << ", Size:" << glchar.size << ", Bearing:" << glchar.bearing - << ", Advance:" << glchar.advance << std::endl; - } - this->glchars.insert (std::pair(c, glchar)); + if constexpr (debug_visualface == true) { + std::cout << "Inserting character into this->glchars with info: ID:" << glchar.textureID + << ", Size:" << glchar.size << ", Bearing:" << glchar.bearing + << ", Advance:" << glchar.advance << std::endl; } - glfn->BindTexture(GL_TEXTURE_2D, 0); - - // At this point could FT_Done_Face() etc, I think. as we no longer do anything Freetypey with it. - FT_Done_Face (this->face); + this->glchars.insert (std::pair(c, glchar)); } + glfn->BindTexture(GL_TEXTURE_2D, 0); + + // At this point could FT_Done_Face() etc, I think. as we no longer do anything Freetypey with it. + FT_Done_Face (this->face); + } - ~VisualFaceMX() {} - }; - } // namespace gl -} // namespace mplot + ~VisualFaceMX() {} + }; +} // namespace mplot::visgl diff --git a/mplot/VisualFaceNoMX.h b/mplot/VisualFaceNoMX.h index 99d5fde3..c476a2ef 100644 --- a/mplot/VisualFaceNoMX.h +++ b/mplot/VisualFaceNoMX.h @@ -20,86 +20,83 @@ # error "GL headers should have been included already" #endif -namespace mplot { - - namespace visgl { - - struct VisualFaceNoMX : public mplot::visgl::VisualFaceBase +namespace mplot::visgl +{ + struct VisualFaceNoMX : public mplot::visgl::VisualFaceBase + { + /*! + * Construct with a mplot::VisualFont \a _font, which specifies a supported + * font (one which we can legally include in the source code without paying any licence fees, + * e.g. Bitstream Vera) and \a fontpixels, which is the texture size, + * e.g. 192. This is the width, in pixels, of the texture that would be + * applied to the letter 'm'. A larger value is required for fonts that will + * take up a large part of the screen, but will be detrimental to the + * appearance of a font which is rendered 'small on the screen'. + * + * VisualResources holds a map of VisualFace instances, to avoid many copies + * of font textures for separate VisualTextModel instances which might have + * the same pixel size. + */ + VisualFaceNoMX (const mplot::VisualFont _font, unsigned int fontpixels, FT_Library& ft_freetype) { - /*! - * Construct with a mplot::VisualFont \a _font, which specifies a supported - * font (one which we can legally include in the source code without paying any licence fees, - * e.g. Bitstream Vera) and \a fontpixels, which is the texture size, - * e.g. 192. This is the width, in pixels, of the texture that would be - * applied to the letter 'm'. A larger value is required for fonts that will - * take up a large part of the screen, but will be detrimental to the - * appearance of a font which is rendered 'small on the screen'. - * - * VisualResources holds a map of VisualFace instances, to avoid many copies - * of font textures for separate VisualTextModel instances which might have - * the same pixel size. - */ - VisualFaceNoMX (const mplot::VisualFont _font, unsigned int fontpixels, FT_Library& ft_freetype) - { - this->init_common (_font, fontpixels, ft_freetype); + this->init_common (_font, fontpixels, ft_freetype); - // How far to loop. In principle, up to 21 bits worth - that's 2097151 possible characters! - for (char32_t c = 0; c < 2097151; c++) { - // Check glyph index first, if it's 0 it's a blank so skip. - if (FT_Get_Char_Index (this->face, c) == 0) { continue; } + // How far to loop. In principle, up to 21 bits worth - that's 2097151 possible characters! + for (char32_t c = 0; c < 2097151; c++) { + // Check glyph index first, if it's 0 it's a blank so skip. + if (FT_Get_Char_Index (this->face, c) == 0) { continue; } - // load character glyph - if (FT_Load_Char (this->face, c, FT_LOAD_RENDER)) { - std::cout << "ERROR::FREETYPE: Failed to load Glyph for Unicode 0x" - << std::hex << static_cast(c) << std::dec << std::endl; - continue; - } + // load character glyph + if (FT_Load_Char (this->face, c, FT_LOAD_RENDER)) { + std::cout << "ERROR::FREETYPE: Failed to load Glyph for Unicode 0x" + << std::hex << static_cast(c) << std::dec << std::endl; + continue; + } - // generate texture - unsigned int texture = 0; + // generate texture + unsigned int texture = 0; - glGenTextures (1, &texture); - glBindTexture (GL_TEXTURE_2D, texture); - glTexImage2D( - GL_TEXTURE_2D, - 0, - GL_RED, - this->face->glyph->bitmap.width, - this->face->glyph->bitmap.rows, - 0, - GL_RED, - GL_UNSIGNED_BYTE, - this->face->glyph->bitmap.buffer - ); - // set texture options - glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // Could be GL_NEAREST, but doesn't look as good. + glGenTextures (1, &texture); + glBindTexture (GL_TEXTURE_2D, texture); + glTexImage2D( + GL_TEXTURE_2D, + 0, + GL_RED, + this->face->glyph->bitmap.width, + this->face->glyph->bitmap.rows, + 0, + GL_RED, + GL_UNSIGNED_BYTE, + this->face->glyph->bitmap.buffer + ); + // set texture options + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // Could be GL_NEAREST, but doesn't look as good. - // now store character for later use - mplot::visgl::CharInfo glchar = { - texture, - {static_cast(this->face->glyph->bitmap.width), static_cast(this->face->glyph->bitmap.rows)}, // size - {this->face->glyph->bitmap_left, this->face->glyph->bitmap_top}, // bearing - static_cast(this->face->glyph->advance.x) // advance - }; + // now store character for later use + mplot::visgl::CharInfo glchar = { + texture, + {static_cast(this->face->glyph->bitmap.width), static_cast(this->face->glyph->bitmap.rows)}, // size + {this->face->glyph->bitmap_left, this->face->glyph->bitmap_top}, // bearing + static_cast(this->face->glyph->advance.x) // advance + }; - if constexpr (debug_visualface == true) { - std::cout << "Inserting character into this->glchars with info: ID:" << glchar.textureID - << ", Size:" << glchar.size << ", Bearing:" << glchar.bearing - << ", Advance:" << glchar.advance << std::endl; - } - this->glchars.insert (std::pair(c, glchar)); + if constexpr (debug_visualface == true) { + std::cout << "Inserting character into this->glchars with info: ID:" << glchar.textureID + << ", Size:" << glchar.size << ", Bearing:" << glchar.bearing + << ", Advance:" << glchar.advance << std::endl; } + this->glchars.insert (std::pair(c, glchar)); + } - glBindTexture(GL_TEXTURE_2D, 0); + glBindTexture(GL_TEXTURE_2D, 0); - // At this point could FT_Done_Face() etc, I think. as we no longer do anything Freetypey with it. - FT_Done_Face (this->face); - } + // At this point could FT_Done_Face() etc, I think. as we no longer do anything Freetypey with it. + FT_Done_Face (this->face); + } - ~VisualFaceNoMX() {} - }; - } // namespace gl -} // namespace mplot + ~VisualFaceNoMX() {} + }; +} // namespace mplot::visgl diff --git a/mplot/VisualFont.h b/mplot/VisualFont.h index 34ff329c..9d620373 100644 --- a/mplot/VisualFont.h +++ b/mplot/VisualFont.h @@ -4,9 +4,11 @@ * This is just an enumerated class that defines the fonts we pack into a mplot binary */ -namespace mplot { +namespace mplot +{ //! The fonts supported (i.e. compiled in) to mplot::Visual - enum class VisualFont { + enum class VisualFont + { DVSans, // fonts/dejavu/DejaVuSans.ttf DVSansItalic, // fonts/dejavu/DejaVuSans-Oblique.ttf DVSansBold, // fonts/dejavu/DejaVuSans-Bold.ttf @@ -22,4 +24,4 @@ namespace mplot { VeraSerif, // fonts/ttf-bitstream-vera/VeraSe.ttf VeraSerifBold // fonts/ttf-bitstream-vera/VeraSeBd.ttf }; -} // mplot +} diff --git a/mplot/VisualGlfw.h b/mplot/VisualGlfw.h index 1298fb5d..c8d306f8 100644 --- a/mplot/VisualGlfw.h +++ b/mplot/VisualGlfw.h @@ -17,8 +17,8 @@ #include #include -namespace mplot { - +namespace mplot +{ //! Singleton resource class for mplot::Visual scenes. template class VisualGlfw diff --git a/mplot/VisualMX.h b/mplot/VisualMX.h index d8cffbba..bd9b9da9 100644 --- a/mplot/VisualMX.h +++ b/mplot/VisualMX.h @@ -25,7 +25,8 @@ #include #include -namespace mplot { +namespace mplot +{ // With mplot::Visual, we use a GLFW window which is owned by mplot::Visual. using win_t = GLFWwindow; } @@ -33,8 +34,8 @@ namespace mplot { #include #include -namespace mplot { - +namespace mplot +{ /*! * Visual 'scene' class * diff --git a/mplot/VisualModel.h b/mplot/VisualModel.h index 18982b32..95aef39f 100644 --- a/mplot/VisualModel.h +++ b/mplot/VisualModel.h @@ -16,8 +16,8 @@ # include #endif -namespace mplot { - +namespace mplot +{ /*! * An OpenGL model class * @@ -45,5 +45,4 @@ namespace mplot { VisualModel(const sm::vec& _offset) : mplot::VisualModelImpl::VisualModelImpl(_offset) {} }; - -} // namespace mplot +} diff --git a/mplot/VisualModelBase.h b/mplot/VisualModelBase.h index 1e4d77f5..cd2d878e 100644 --- a/mplot/VisualModelBase.h +++ b/mplot/VisualModelBase.h @@ -50,8 +50,8 @@ #include #include -namespace mplot { - +namespace mplot +{ union float_bytes { float f; diff --git a/mplot/VisualModelImplMX.h b/mplot/VisualModelImplMX.h index c9f0cdb8..b752d3f1 100644 --- a/mplot/VisualModelImplMX.h +++ b/mplot/VisualModelImplMX.h @@ -23,8 +23,8 @@ #include #include -namespace mplot { - +namespace mplot +{ //! Forward declaration of base classes template class VisualBase; template class VisualOwnableMX; diff --git a/mplot/VisualModelImplNoMX.h b/mplot/VisualModelImplNoMX.h index 261f8f2a..70f236c3 100644 --- a/mplot/VisualModelImplNoMX.h +++ b/mplot/VisualModelImplNoMX.h @@ -23,8 +23,8 @@ #include #include -namespace mplot { - +namespace mplot +{ //! Forward declaration of a Visual base class template class VisualBase; diff --git a/mplot/VisualNoMX.h b/mplot/VisualNoMX.h index fe2feb9e..d4efc038 100644 --- a/mplot/VisualNoMX.h +++ b/mplot/VisualNoMX.h @@ -23,7 +23,8 @@ #include #include -namespace mplot { +namespace mplot +{ // With mplot::Visual, we use a GLFW window which is owned by mplot::Visual. using win_t = GLFWwindow; } @@ -32,8 +33,8 @@ namespace mplot { #include #include -namespace mplot { - +namespace mplot +{ /*! * Visual 'scene' class * diff --git a/mplot/VisualOwnableMX.h b/mplot/VisualOwnableMX.h index 6532dbc0..8aedc7b4 100644 --- a/mplot/VisualOwnableMX.h +++ b/mplot/VisualOwnableMX.h @@ -26,7 +26,7 @@ // By including this header, you take out a contract that you ARE using multicontext (MX) GLAD // headers. This must appear BEFORE the rest of the mplot headers. -namespace mplot { namespace gl { static constexpr int multicontext = 1; } } +namespace mplot::gl { static constexpr int multicontext = 1; } #include #include @@ -34,8 +34,8 @@ namespace mplot { namespace gl { static constexpr int multicontext = 1; } } #include #include -namespace mplot { - +namespace mplot +{ /*! * VisualOwnableMX - adds multi-context-safe GL calls to the 'scene' base class, VisualBase * diff --git a/mplot/VisualOwnableNoMX.h b/mplot/VisualOwnableNoMX.h index 5180d5c6..b1690c3f 100644 --- a/mplot/VisualOwnableNoMX.h +++ b/mplot/VisualOwnableNoMX.h @@ -26,7 +26,7 @@ // By including this header, you take out a contract that you are not using multicontext (MX) GLAD // headers. This must appear BEFORE the rest of the mplot headers. -namespace mplot { namespace gl { static constexpr int multicontext = 0; } } +namespace mplot::gl { static constexpr int multicontext = 0; } #include #include @@ -34,8 +34,8 @@ namespace mplot { namespace gl { static constexpr int multicontext = 0; } } #include #include -namespace mplot { - +namespace mplot +{ /*! * VisualOwnableNoMX - adds GL calls to the 'scene' base class, VisualBase * diff --git a/mplot/VisualResourcesBase.h b/mplot/VisualResourcesBase.h index 91ce5afe..32b986d4 100644 --- a/mplot/VisualResourcesBase.h +++ b/mplot/VisualResourcesBase.h @@ -21,8 +21,8 @@ #include #include FT_FREETYPE_H -namespace mplot { - +namespace mplot +{ // Pointers to mplot::VisualBase are used to index font faces template class VisualBase; diff --git a/mplot/VisualResourcesMX.h b/mplot/VisualResourcesMX.h index c587c0e7..a8cf1d7c 100644 --- a/mplot/VisualResourcesMX.h +++ b/mplot/VisualResourcesMX.h @@ -14,8 +14,8 @@ #include #include -namespace mplot { - +namespace mplot +{ // Pointers to mplot::VisualBase are used to index font faces template class VisualBase; diff --git a/mplot/VisualResourcesNoMX.h b/mplot/VisualResourcesNoMX.h index 60edbc8a..ee342f8a 100644 --- a/mplot/VisualResourcesNoMX.h +++ b/mplot/VisualResourcesNoMX.h @@ -14,8 +14,8 @@ #include #include -namespace mplot { - +namespace mplot +{ // Pointers to mplot::VisualBase are used to index font faces template class VisualBase; diff --git a/mplot/VisualTextModel.h b/mplot/VisualTextModel.h index 1825e9d3..cc70ed00 100644 --- a/mplot/VisualTextModel.h +++ b/mplot/VisualTextModel.h @@ -20,11 +20,12 @@ # include #endif -namespace mplot { +namespace mplot +{ // glad_type is set in VisualOwnableNoMX.h or VisualOwnableMX.h template struct VisualTextModel : public mplot::VisualTextModelImpl { VisualTextModel(mplot::TextFeatures _tf) : mplot::VisualTextModelImpl::VisualTextModelImpl(_tf) {} }; -} // namespace mplot +} diff --git a/mplot/VisualTextModelBase.h b/mplot/VisualTextModelBase.h index 9a1e224a..da547f23 100644 --- a/mplot/VisualTextModelBase.h +++ b/mplot/VisualTextModelBase.h @@ -30,8 +30,8 @@ #include #include -namespace mplot { - +namespace mplot +{ //! Forward declaration of a VisualBase class template class VisualBase; diff --git a/mplot/VisualTextModelImplMX.h b/mplot/VisualTextModelImplMX.h index 1bdd2fb9..80e6a912 100644 --- a/mplot/VisualTextModelImplMX.h +++ b/mplot/VisualTextModelImplMX.h @@ -22,8 +22,8 @@ #include #include -namespace mplot { - +namespace mplot +{ //! Forward declaration of a VisualBase class template class VisualBase; diff --git a/mplot/VisualTextModelImplNoMX.h b/mplot/VisualTextModelImplNoMX.h index f7b2ca0c..35ae8241 100644 --- a/mplot/VisualTextModelImplNoMX.h +++ b/mplot/VisualTextModelImplNoMX.h @@ -22,8 +22,8 @@ #include #include -namespace mplot { - +namespace mplot +{ //! Forward declaration of a VisualBase class template class VisualBase; diff --git a/mplot/VoronoiVisual.h b/mplot/VoronoiVisual.h index 8da3c7a6..556ed1b2 100644 --- a/mplot/VoronoiVisual.h +++ b/mplot/VoronoiVisual.h @@ -27,8 +27,8 @@ #include -namespace mplot { - +namespace mplot +{ //! The template argument F is the type of the data which this VoronoiVisual //! will visualize. template diff --git a/mplot/colour.h b/mplot/colour.h index 50eb8c05..f806f7e0 100644 --- a/mplot/colour.h +++ b/mplot/colour.h @@ -11,702 +11,700 @@ #include -namespace mplot { - namespace colour { - - static constexpr std::array indian_red = {0.6901960784f,0.0901960784f,0.1215686275f}; - static constexpr std::array crimson = {0.862745098f,0.0784313725f,0.2352941176f}; - static constexpr std::array lightpink = {1.0f,0.7137254902f,0.7568627451f}; - static constexpr std::array lightpink1 = {1.0f,0.6823529412f,0.7254901961f}; - static constexpr std::array lightpink2 = {0.9333333333f,0.6352941176f,0.6784313725f}; - static constexpr std::array lightpink3 = {0.8039215686f,0.5490196078f,0.5843137255f}; - static constexpr std::array lightpink4 = {0.5450980392f,0.3725490196f,0.3960784314f}; - static constexpr std::array pink = {1.0f,0.7529411765f,0.7960784314f}; - static constexpr std::array pink1 = {1.0f,0.7098039216f,0.7725490196f}; - static constexpr std::array pink2 = {0.9333333333f,0.662745098f,0.7215686275f}; - static constexpr std::array pink3 = {0.8039215686f,0.568627451f,0.6196078431f}; - static constexpr std::array pink4 = {0.5450980392f,0.3882352941f,0.4235294118f}; - static constexpr std::array palevioletred = {0.8588235294f,0.4392156863f,0.5764705882f}; - static constexpr std::array palevioletred1 = {1.0f,0.5098039216f,0.6705882353f}; - static constexpr std::array palevioletred2 = {0.9333333333f,0.4745098039f,0.6235294118f}; - static constexpr std::array palevioletred3 = {0.8039215686f,0.4078431373f,0.537254902f}; - static constexpr std::array palevioletred4 = {0.5450980392f,0.2784313725f,0.3647058824f}; - static constexpr std::array lavenderblush = {1.0f,0.9411764706f,0.9607843137f}; - static constexpr std::array lavenderblush1 = lavenderblush; - static constexpr std::array lavenderblush2 = {0.9333333333f,0.8784313725f,0.8980392157f}; - static constexpr std::array lavenderblush3 = {0.8039215686f,0.7568627451f,0.7725490196f}; - static constexpr std::array lavenderblush4 = {0.5450980392f,0.5137254902f,0.5254901961f}; - static constexpr std::array violetred1 = {1.0f,0.2431372549f,0.5882352941f}; - static constexpr std::array violetred2 = {0.9333333333f,0.2274509804f,0.5490196078f}; - static constexpr std::array violetred3 = {0.8039215686f,0.1960784314f,0.4705882353f}; - static constexpr std::array violetred4 = {0.5450980392f,0.1333333333f,0.3215686275f}; - static constexpr std::array hotpink = {1.0f,0.4117647059f,0.7058823529f}; - static constexpr std::array hotpink1 = {1.0f,0.431372549f,0.7058823529f}; - static constexpr std::array hotpink2 = {0.9333333333f,0.4156862745f,0.6549019608f}; - static constexpr std::array hotpink3 = {0.8039215686f,0.3764705882f,0.5647058824f}; - static constexpr std::array hotpink4 = {0.5450980392f,0.2274509804f,0.3843137255f}; - static constexpr std::array raspberry = {0.5294117647f,0.1490196078f,0.3411764706f}; - static constexpr std::array deeppink = {1.0f,0.0784313725f,0.5764705882f}; - static constexpr std::array deeppink1 = {1.0f,0.0784313725f,0.5764705882f}; - static constexpr std::array deeppink2 = {0.9333333333f,0.0705882353f,0.537254902f}; - static constexpr std::array deeppink3 = {0.8039215686f,0.062745098f,0.462745098f}; - static constexpr std::array deeppink4 = {0.5450980392f,0.0392156863f,0.3137254902f}; - static constexpr std::array maroon1 = {1.0f,0.2039215686f,0.7019607843f}; - static constexpr std::array maroon2 = {0.9333333333f,0.1882352941f,0.6549019608f}; - static constexpr std::array maroon3 = {0.8039215686f,0.1607843137f,0.5647058824f}; - static constexpr std::array maroon4 = {0.5450980392f,0.1098039216f,0.3843137255f}; - static constexpr std::array mediumvioletred = {0.7803921569f,0.0823529412f,0.5215686275f}; - static constexpr std::array violetred = {0.8156862745f,0.1254901961f,0.5647058824f}; - static constexpr std::array orchid = {0.8549019608f,0.4392156863f,0.8392156863f}; - static constexpr std::array orchid1 = {1.0f,0.5137254902f,0.9803921569f}; - static constexpr std::array orchid2 = {0.9333333333f,0.4784313725f,0.9137254902f}; - static constexpr std::array orchid3 = {0.8039215686f,0.4117647059f,0.7882352941f}; - static constexpr std::array orchid4 = {0.5450980392f,0.2784313725f,0.537254902f}; - static constexpr std::array thistle = {0.8470588235f,0.7490196078f,0.8470588235f}; - static constexpr std::array thistle1 = {1.0f,0.8823529412f,1.0f}; - static constexpr std::array thistle2 = {0.9333333333f,0.8235294118f,0.9333333333f}; - static constexpr std::array thistle3 = {0.8039215686f,0.7098039216f,0.8039215686f}; - static constexpr std::array thistle4 = {0.5450980392f,0.4823529412f,0.5450980392f}; - static constexpr std::array plum1 = {1.0f,0.7333333333f,1.0f}; - static constexpr std::array plum2 = {0.9333333333f,0.6823529412f,0.9333333333f}; - static constexpr std::array plum3 = {0.8039215686f,0.5882352941f,0.8039215686f}; - static constexpr std::array plum4 = {0.5450980392f,0.4f,0.5450980392f}; - static constexpr std::array plum = {0.8666666667f,0.6274509804f,0.8666666667f}; - static constexpr std::array violet = {0.9333333333f,0.5098039216f,0.9333333333f}; - static constexpr std::array magenta = {1.0f,0.0f,1.0f}; - static constexpr std::array fuchsia = magenta; - static constexpr std::array magenta2 = {0.9333333333f,0.0f,0.9333333333f}; - static constexpr std::array magenta3 = {0.8039215686f,0.0f,0.8039215686f}; - static constexpr std::array magenta4 = {0.5450980392f,0.0f,0.5450980392f}; - static constexpr std::array darkmagenta = magenta4; - static constexpr std::array purple = {0.5019607843f,0.0f,0.5019607843f}; - static constexpr std::array mediumorchid = {0.7294117647f,0.3333333333f,0.8274509804f}; - static constexpr std::array mediumorchid1 = {0.8784313725f,0.4f,1.0f}; - static constexpr std::array mediumorchid2 = {0.8196078431f,0.3725490196f,0.9333333333f}; - static constexpr std::array mediumorchid3 = {0.7058823529f,0.3215686275f,0.8039215686f}; - static constexpr std::array mediumorchid4 = {0.4784313725f,0.2156862745f,0.5450980392f}; - static constexpr std::array darkviolet = {0.5803921569f,0.0f,0.8274509804f}; - static constexpr std::array darkorchid = {0.6f,0.1960784314f,0.8f}; - static constexpr std::array darkorchid1 = {0.7490196078f,0.2431372549f,1.0f}; - static constexpr std::array darkorchid2 = {0.6980392157f,0.2274509804f,0.9333333333f}; - static constexpr std::array darkorchid3 = {0.6039215686f,0.1960784314f,0.8039215686f}; - static constexpr std::array darkorchid4 = {0.4078431373f,0.1333333333f,0.5450980392f}; - static constexpr std::array indigo = {0.2941176471f,0.0f,0.5098039216f}; - static constexpr std::array blueviolet = {0.5411764706f,0.168627451f,0.8862745098f}; - static constexpr std::array purple1 = {0.6078431373f,0.1882352941f,1.0f}; - static constexpr std::array purple2 = {0.568627451f,0.1725490196f,0.9333333333f}; - static constexpr std::array purple3 = {0.4901960784f,0.1490196078f,0.8039215686f}; - static constexpr std::array purple4 = {0.3333333333f,0.1019607843f,0.5450980392f}; - static constexpr std::array mediumpurple = {0.5764705882f,0.4392156863f,0.8588235294f}; - static constexpr std::array mediumpurple1 = {0.6705882353f,0.5098039216f,1.0f}; - static constexpr std::array mediumpurple2 = {0.6235294118f,0.4745098039f,0.9333333333f}; - static constexpr std::array mediumpurple3 = {0.537254902f,0.4078431373f,0.8039215686f}; - static constexpr std::array mediumpurple4 = {0.3647058824f,0.2784313725f,0.5450980392f}; - static constexpr std::array darkslateblue = {0.2823529412f,0.2392156863f,0.5450980392f}; - static constexpr std::array lightslateblue = {0.5176470588f,0.4392156863f,1.0f}; - static constexpr std::array mediumslateblue = {0.4823529412f,0.4078431373f,0.9333333333f}; - static constexpr std::array slateblue = {0.4156862745f,0.3529411765f,0.8039215686f}; - static constexpr std::array slateblue1 = {0.5137254902f,0.4352941176f,1.0f}; - static constexpr std::array slateblue2 = {0.4784313725f,0.4039215686f,0.9333333333f}; - static constexpr std::array slateblue3 = {0.4117647059f,0.3490196078f,0.8039215686f}; - static constexpr std::array slateblue4 = {0.2784313725f,0.2352941176f,0.5450980392f}; - static constexpr std::array ghostwhite = {0.9725490196f,0.9725490196f,1.0f}; - static constexpr std::array lavender = {0.9019607843f,0.9019607843f,0.9803921569f}; - static constexpr std::array blue = {0.0f,0.0f,1.0f}; - static constexpr std::array blue1 = blue; - static constexpr std::array blue2 = {0.0f,0.0f,0.9333333333f}; - static constexpr std::array blue3 = {0.0f,0.0f,0.8039215686f}; - static constexpr std::array mediumblue = blue3; - static constexpr std::array blue4 = {0.0f,0.0f,0.5450980392f}; - static constexpr std::array darkblue = blue4; - static constexpr std::array navy = {0.0f,0.0f,0.5019607843f}; - static constexpr std::array midnightblue = {0.0980392157f,0.0980392157f,0.4392156863f}; - static constexpr std::array cobalt = {0.2392156863f,0.3490196078f,0.6705882353f}; - static constexpr std::array royalblue = {0.2549019608f,0.4117647059f,0.8823529412f}; - static constexpr std::array royalblue1 = {0.2823529412f,0.462745098f,1.0f}; - static constexpr std::array royalblue2 = {0.262745098f,0.431372549f,0.9333333333f}; - static constexpr std::array royalblue3 = {0.2274509804f,0.3725490196f,0.8039215686f}; - static constexpr std::array royalblue4 = {0.1529411765f,0.2509803922f,0.5450980392f}; - static constexpr std::array cornflowerblue = {0.3921568627f,0.5843137255f,0.9294117647f}; - static constexpr std::array lightsteelblue = {0.6901960784f,0.768627451f,0.8705882353f}; - static constexpr std::array lightsteelblue1 = {0.7921568627f,0.8823529412f,1.0f}; - static constexpr std::array lightsteelblue2 = {0.737254902f,0.8235294118f,0.9333333333f}; - static constexpr std::array lightsteelblue3 = {0.6352941176f,0.7098039216f,0.8039215686f}; - static constexpr std::array lightsteelblue4 = {0.431372549f,0.4823529412f,0.5450980392f}; - static constexpr std::array lightslategray = {0.4666666667f,0.5333333333f,0.6f}; - static constexpr std::array slategray = {0.4392156863f,0.5019607843f,0.5647058824f}; - static constexpr std::array slategray1 = {0.7764705882f,0.8862745098f,1.0f}; - static constexpr std::array slategray2 = {0.7254901961f,0.8274509804f,0.9333333333f}; - static constexpr std::array slategray3 = {0.6235294118f,0.7137254902f,0.8039215686f}; - static constexpr std::array slategray4 = {0.4235294118f,0.4823529412f,0.5450980392f}; - static constexpr std::array dodgerblue = {0.1176470588f,0.5647058824f,1.0f}; - static constexpr std::array dodgerblue1 = dodgerblue; - static constexpr std::array dodgerblue2 = {0.1098039216f,0.5254901961f,0.9333333333f}; - static constexpr std::array dodgerblue3 = {0.0941176471f,0.4549019608f,0.8039215686f}; - static constexpr std::array dodgerblue4 = {0.062745098f,0.3058823529f,0.5450980392f}; - static constexpr std::array aliceblue = {0.9411764706f,0.9725490196f,1.0f}; - static constexpr std::array steelblue = {0.2745098039f,0.5098039216f,0.7058823529f}; - static constexpr std::array steelblue1 = {0.3882352941f,0.7215686275f,1.0f}; - static constexpr std::array steelblue2 = {0.3607843137f,0.6745098039f,0.9333333333f}; - static constexpr std::array steelblue3 = {0.3098039216f,0.5803921569f,0.8039215686f}; - static constexpr std::array steelblue4 = {0.2117647059f,0.3921568627f,0.5450980392f}; - static constexpr std::array lightskyblue = {0.5294117647f,0.8078431373f,0.9803921569f}; - static constexpr std::array lightskyblue1 = {0.6901960784f,0.8862745098f,1.0f}; - static constexpr std::array lightskyblue2 = {0.6431372549f,0.8274509804f,0.9333333333f}; - static constexpr std::array lightskyblue3 = {0.5529411765f,0.7137254902f,0.8039215686f}; - static constexpr std::array lightskyblue4 = {0.3764705882f,0.4823529412f,0.5450980392f}; - static constexpr std::array skyblue = {0.5294117647f,0.8078431373f,0.9215686275f}; - static constexpr std::array skyblue1 = {0.5294117647f,0.8078431373f,1.0f}; - static constexpr std::array skyblue2 = {0.4941176471f,0.7529411765f,0.9333333333f}; - static constexpr std::array skyblue3 = {0.4235294118f,0.6509803922f,0.8039215686f}; - static constexpr std::array skyblue4 = {0.2901960784f,0.4392156863f,0.5450980392f}; - static constexpr std::array deepskyblue = {0.0f,0.7490196078f,1.0f}; - static constexpr std::array deepskyblue1 = deepskyblue; - static constexpr std::array deepskyblue2 = {0.0f,0.6980392157f,0.9333333333f}; - static constexpr std::array deepskyblue3 = {0.0f,0.6039215686f,0.8039215686f}; - static constexpr std::array deepskyblue4 = {0.0f,0.4078431373f,0.5450980392f}; - static constexpr std::array peacock = {0.2f,0.631372549f,0.7882352941f}; - static constexpr std::array lightblue = {0.6784313725f,0.8470588235f,0.9019607843f}; - static constexpr std::array lightblue1 = {0.7490196078f,0.937254902f,1.0f}; - static constexpr std::array lightblue2 = {0.6980392157f,0.8745098039f,0.9333333333f}; - static constexpr std::array lightblue3 = {0.6039215686f,0.7529411765f,0.8039215686f}; - static constexpr std::array lightblue4 = {0.4078431373f,0.5137254902f,0.5450980392f}; - static constexpr std::array powderblue = {0.6901960784f,0.8784313725f,0.9019607843f}; - static constexpr std::array cadetblue1 = {0.5960784314f,0.9607843137f,1.0f}; - static constexpr std::array cadetblue2 = {0.5568627451f,0.8980392157f,0.9333333333f}; - static constexpr std::array cadetblue3 = {0.4784313725f,0.7725490196f,0.8039215686f}; - static constexpr std::array cadetblue4 = {0.3254901961f,0.5254901961f,0.5450980392f}; - static constexpr std::array turquoise1 = {0.0f,0.9607843137f,1.0f}; - static constexpr std::array turquoise2 = {0.0f,0.8980392157f,0.9333333333f}; - static constexpr std::array turquoise3 = {0.0f,0.7725490196f,0.8039215686f}; - static constexpr std::array turquoise4 = {0.0f,0.5254901961f,0.5450980392f}; - static constexpr std::array cadetblue = {0.3725490196f,0.6196078431f,0.6274509804f}; - static constexpr std::array darkturquoise = {0.0f,0.8078431373f,0.8196078431f}; - static constexpr std::array azure = {0.9411764706f,1.0f,1.0f}; - static constexpr std::array azure1 = azure; - static constexpr std::array azure2 = {0.8784313725f,0.9333333333f,0.9333333333f}; - static constexpr std::array azure3 = {0.7568627451f,0.8039215686f,0.8039215686f}; - static constexpr std::array azure4 = {0.5137254902f,0.5450980392f,0.5450980392f}; - static constexpr std::array lightcyan = {0.8784313725f,1.0f,1.0f}; - static constexpr std::array lightcyan1 = lightcyan; - static constexpr std::array lightcyan2 = {0.8196078431f,0.9333333333f,0.9333333333f}; - static constexpr std::array lightcyan3 = {0.7058823529f,0.8039215686f,0.8039215686f}; - static constexpr std::array lightcyan4 = {0.4784313725f,0.5450980392f,0.5450980392f}; - static constexpr std::array paleturquoise1 = {0.7333333333f,1.0f,1.0f}; - static constexpr std::array paleturquoise = {0.6823529412f,0.9333333333f,0.9333333333f}; - static constexpr std::array paleturquoise2 = paleturquoise; - static constexpr std::array paleturquoise3 = {0.5882352941f,0.8039215686f,0.8039215686f}; - static constexpr std::array paleturquoise4 = {0.4f,0.5450980392f,0.5450980392f}; - static constexpr std::array darkslategray = {0.1843137255f,0.3098039216f,0.3098039216f}; - static constexpr std::array darkslategray1 = {0.5921568627f,1.0f,1.0f}; - static constexpr std::array darkslategray2 = {0.5529411765f,0.9333333333f,0.9333333333f}; - static constexpr std::array darkslategray3 = {0.4745098039f,0.8039215686f,0.8039215686f}; - static constexpr std::array darkslategray4 = {0.3215686275f,0.5450980392f,0.5450980392f}; - static constexpr std::array cyan = {0.0f,1.0f,1.0f}; - static constexpr std::array cyan1 = cyan; - static constexpr std::array cyan2 = {0.0f,0.9333333333f,0.9333333333f}; - static constexpr std::array cyan3 = {0.0f,0.8039215686f,0.8039215686f}; - static constexpr std::array cyan4 = {0.0f,0.5450980392f,0.5450980392f}; - static constexpr std::array darkcyan = cyan4; - static constexpr std::array teal = {0.0f,0.5019607843f,0.5019607843f}; - static constexpr std::array mediumturquoise = {0.2823529412f,0.8196078431f,0.8f}; - static constexpr std::array lightseagreen = {0.1254901961f,0.6980392157f,0.6666666667f}; - static constexpr std::array manganeseblue = {0.0117647059f,0.6588235294f,0.6196078431f}; - static constexpr std::array turquoise = {0.2509803922f,0.8784313725f,0.8156862745f}; - static constexpr std::array coldgrey = {0.5019607843f,0.5411764706f,0.5294117647f}; - static constexpr std::array turquoiseblue = {0.0f,0.7803921569f,0.5490196078f}; - static constexpr std::array aquamarine = {0.4980392157f,1.0f,0.831372549f}; - static constexpr std::array aquamarine1 = aquamarine; - static constexpr std::array aquamarine2 = {0.462745098f,0.9333333333f,0.7764705882f}; - static constexpr std::array aquamarine3 = {0.4f,0.8039215686f,0.6666666667f}; - static constexpr std::array mediumaquamarine = aquamarine3; - static constexpr std::array aquamarine4 = {0.2705882353f,0.5450980392f,0.4549019608f}; - static constexpr std::array mediumspringgreen = {0.0f,0.9803921569f,0.6039215686f}; - static constexpr std::array mintcream = {0.9607843137f,1.0f,0.9803921569f}; - static constexpr std::array springgreen = {0.0f,1.0f,0.4980392157f}; - static constexpr std::array springgreen1 = {0.0f,0.9333333333f,0.462745098f}; - static constexpr std::array springgreen2 = {0.0f,0.8039215686f,0.4f}; - static constexpr std::array springgreen3 = {0.0f,0.5450980392f,0.2705882353f}; - static constexpr std::array mediumseagreen = {0.2352941176f,0.7019607843f,0.4431372549f}; - static constexpr std::array seagreen1 = {0.3294117647f,1.0f,0.6235294118f}; - static constexpr std::array seagreen2 = {0.3058823529f,0.9333333333f,0.5803921569f}; - static constexpr std::array seagreen3 = {0.262745098f,0.8039215686f,0.5019607843f}; - static constexpr std::array seagreen = {0.1803921569f,0.5450980392f,0.3411764706f}; - static constexpr std::array seagreen4 = seagreen; - static constexpr std::array emeraldgreen = {0.0f,0.7882352941f,0.3411764706f}; - static constexpr std::array mint = {0.7411764706f,0.9882352941f,0.7882352941f}; - static constexpr std::array cobaltgreen = {0.2392156863f,0.568627451f,0.2509803922f}; - static constexpr std::array honeydew = {0.9411764706f,1.0f,0.9411764706f}; - static constexpr std::array honeydew1 = honeydew; - static constexpr std::array honeydew2 = {0.8784313725f,0.9333333333f,0.8784313725f}; - static constexpr std::array honeydew3 = {0.7568627451f,0.8039215686f,0.7568627451f}; - static constexpr std::array honeydew4 = {0.5137254902f,0.5450980392f,0.5137254902f}; - static constexpr std::array darkseagreen = {0.5607843137f,0.737254902f,0.5607843137f}; - static constexpr std::array darkseagreen1 = {0.7568627451f,1.0f,0.7568627451f}; - static constexpr std::array darkseagreen2 = {0.7058823529f,0.9333333333f,0.7058823529f}; - static constexpr std::array darkseagreen3 = {0.6078431373f,0.8039215686f,0.6078431373f}; - static constexpr std::array darkseagreen4 = {0.4117647059f,0.5450980392f,0.4117647059f}; - static constexpr std::array palegreen = {0.5960784314f,0.9843137255f,0.5960784314f}; - static constexpr std::array palegreen1 = {0.6039215686f,1.0f,0.6039215686f}; - static constexpr std::array lightgreen = {0.5647058824f,0.9333333333f,0.5647058824f}; - static constexpr std::array palegreen2 = lightgreen; - static constexpr std::array palegreen3 = {0.4862745098f,0.8039215686f,0.4862745098f}; - static constexpr std::array palegreen4 = {0.3294117647f,0.5450980392f,0.3294117647f}; - static constexpr std::array limegreen = {0.1960784314f,0.8039215686f,0.1960784314f}; - static constexpr std::array forestgreen = {0.1333333333f,0.5450980392f,0.1333333333f}; - static constexpr std::array lime = {0.0f,1.0f,0.0f}; - static constexpr std::array green1 = lime; - static constexpr std::array green2 = {0.0f,0.9333333333f,0.0f}; - static constexpr std::array green3 = {0.0f,0.8039215686f,0.0f}; - static constexpr std::array green4 = {0.0f,0.5450980392f,0.0f}; - static constexpr std::array green = {0.0f,0.5019607843f,0.0f}; - static constexpr std::array darkgreen = {0.0f,0.3921568627f,0.0f}; - static constexpr std::array sapgreen = {0.1882352941f,0.5019607843f,0.0784313725f}; - static constexpr std::array lawngreen = {0.4862745098f,0.9882352941f,0.0f}; - static constexpr std::array chartreuse = {0.4980392157f,1.0f,0.0f}; - static constexpr std::array chartreuse1 = chartreuse; - static constexpr std::array chartreuse2 = {0.462745098f,0.9333333333f,0.0f}; - static constexpr std::array chartreuse3 = {0.4f,0.8039215686f,0.0f}; - static constexpr std::array chartreuse4 = {0.2705882353f,0.5450980392f,0.0f}; - static constexpr std::array greenyellow = {0.6784313725f,1.0f,0.1843137255f}; - static constexpr std::array darkolivegreen1 = {0.7921568627f,1.0f,0.4392156863f}; - static constexpr std::array darkolivegreen2 = {0.737254902f,0.9333333333f,0.4078431373f}; - static constexpr std::array darkolivegreen3 = {0.6352941176f,0.8039215686f,0.3529411765f}; - static constexpr std::array darkolivegreen4 = {0.431372549f,0.5450980392f,0.2392156863f}; - static constexpr std::array darkolivegreen = {0.3333333333f,0.4196078431f,0.1843137255f}; - static constexpr std::array olivedrab = {0.4196078431f,0.5568627451f,0.137254902f}; - static constexpr std::array olivedrab1 = {0.7529411765f,1.0f,0.2431372549f}; - static constexpr std::array olivedrab2 = {0.7019607843f,0.9333333333f,0.2274509804f}; - static constexpr std::array olivedrab3 = {0.6039215686f,0.8039215686f,0.1960784314f}; - static constexpr std::array yellowgreen = olivedrab3; - static constexpr std::array olivedrab4 = {0.4117647059f,0.5450980392f,0.1333333333f}; - static constexpr std::array ivory = {1.0f,1.0f,0.9411764706f}; - static constexpr std::array ivory1 = ivory; - static constexpr std::array ivory2 = {0.9333333333f,0.9333333333f,0.8784313725f}; - static constexpr std::array ivory3 = {0.8039215686f,0.8039215686f,0.7568627451f}; - static constexpr std::array ivory4 = {0.5450980392f,0.5450980392f,0.5137254902f}; - static constexpr std::array beige = {0.9607843137f,0.9607843137f,0.862745098f}; - static constexpr std::array lightyellow = {1.0f,1.0f,0.8784313725f}; - static constexpr std::array lightyellow1 = lightyellow; - static constexpr std::array lightyellow2 = {0.9333333333f,0.9333333333f,0.8196078431f}; - static constexpr std::array lightyellow3 = {0.8039215686f,0.8039215686f,0.7058823529f}; - static constexpr std::array lightyellow4 = {0.5450980392f,0.5450980392f,0.4784313725f}; - static constexpr std::array lightgoldenrodyellow = {0.9803921569f,0.9803921569f,0.8235294118f}; - static constexpr std::array yellow = {1.0f,1.0f,0.0f}; - static constexpr std::array yellow1 = yellow; - static constexpr std::array yellow2 = {0.9333333333f,0.9333333333f,0.0f}; - static constexpr std::array yellow3 = {0.8039215686f,0.8039215686f,0.0f}; - static constexpr std::array yellow4 = {0.5450980392f,0.5450980392f,0.0f}; - static constexpr std::array warmgrey = {0.5019607843f,0.5019607843f,0.4117647059f}; - static constexpr std::array olive = {0.5019607843f,0.5019607843f,0.0f}; - static constexpr std::array darkkhaki = {0.7411764706f,0.7176470588f,0.4196078431f}; - static constexpr std::array khaki1 = {1.0f,0.9647058824f,0.5607843137f}; - static constexpr std::array khaki2 = {0.9333333333f,0.9019607843f,0.5215686275f}; - static constexpr std::array khaki3 = {0.8039215686f,0.7764705882f,0.4509803922f}; - static constexpr std::array khaki4 = {0.5450980392f,0.5254901961f,0.3058823529f}; - static constexpr std::array khaki = {0.9411764706f,0.9019607843f,0.5490196078f}; - static constexpr std::array palegoldenrod = {0.9333333333f,0.9098039216f,0.6666666667f}; - static constexpr std::array lemonchiffon = {1.0f,0.9803921569f,0.8039215686f}; - static constexpr std::array lemonchiffon1 = lemonchiffon; - static constexpr std::array lemonchiffon2 = {0.9333333333f,0.9137254902f,0.7490196078f}; - static constexpr std::array lemonchiffon3 = {0.8039215686f,0.7882352941f,0.6470588235f}; - static constexpr std::array lemonchiffon4 = {0.5450980392f,0.537254902f,0.4392156863f}; - static constexpr std::array lightgoldenrod1 = {1.0f,0.9254901961f,0.5450980392f}; - static constexpr std::array lightgoldenrod2 = {0.9333333333f,0.862745098f,0.5098039216f}; - static constexpr std::array lightgoldenrod3 = {0.8039215686f,0.7450980392f,0.4392156863f}; - static constexpr std::array lightgoldenrod4 = {0.5450980392f,0.5058823529f,0.2980392157f}; - static constexpr std::array banana = {0.8901960784f,0.8117647059f,0.3411764706f}; - static constexpr std::array gold = {1.0f,0.8431372549f,0.0f}; - static constexpr std::array gold1 = gold; - static constexpr std::array gold2 = {0.9333333333f,0.7882352941f,0.0f}; - static constexpr std::array gold3 = {0.8039215686f,0.6784313725f,0.0f}; - static constexpr std::array gold4 = {0.5450980392f,0.4588235294f,0.0f}; - static constexpr std::array cornsilk = {1.0f,0.9725490196f,0.862745098f}; - static constexpr std::array cornsilk1 = cornsilk; - static constexpr std::array cornsilk2 = {0.9333333333f,0.9098039216f,0.8039215686f}; - static constexpr std::array cornsilk3 = {0.8039215686f,0.7843137255f,0.6941176471f}; - static constexpr std::array cornsilk4 = {0.5450980392f,0.5333333333f,0.4705882353f}; - static constexpr std::array goldenrod = {0.8549019608f,0.6470588235f,0.1254901961f}; - static constexpr std::array goldenrod1 = {1.0f,0.7568627451f,0.1450980392f}; - static constexpr std::array goldenrod2 = {0.9333333333f,0.7058823529f,0.1333333333f}; - static constexpr std::array goldenrod3 = {0.8039215686f,0.6078431373f,0.1137254902f}; - static constexpr std::array goldenrod4 = {0.5450980392f,0.4117647059f,0.0784313725f}; - static constexpr std::array darkgoldenrod = {0.7215686275f,0.5254901961f,0.0431372549f}; - static constexpr std::array darkgoldenrod1 = {1.0f,0.7254901961f,0.0588235294f}; - static constexpr std::array darkgoldenrod2 = {0.9333333333f,0.6784313725f,0.0549019608f}; - static constexpr std::array darkgoldenrod3 = {0.8039215686f,0.5843137255f,0.0470588235f}; - static constexpr std::array darkgoldenrod4 = {0.5450980392f,0.3960784314f,0.031372549f}; - static constexpr std::array orange = {1.0f,0.5019607843f,0.0f}; - static constexpr std::array orange1 = {1.0f,0.6470588235f,0.0f}; - static constexpr std::array orange2 = {0.9333333333f,0.6039215686f,0.0f}; - static constexpr std::array orange3 = {0.8039215686f,0.5215686275f,0.0f}; - static constexpr std::array orange4 = {0.5450980392f,0.3529411765f,0.0f}; - static constexpr std::array floralwhite = {1.0f,0.9803921569f,0.9411764706f}; - static constexpr std::array oldlace = {0.9921568627f,0.9607843137f,0.9019607843f}; - static constexpr std::array wheat = {0.9607843137f,0.8705882353f,0.7019607843f}; - static constexpr std::array wheat1 = {1.0f,0.9058823529f,0.7294117647f}; - static constexpr std::array wheat2 = {0.9333333333f,0.8470588235f,0.6823529412f}; - static constexpr std::array wheat3 = {0.8039215686f,0.7294117647f,0.5882352941f}; - static constexpr std::array wheat4 = {0.5450980392f,0.4941176471f,0.4f}; - static constexpr std::array moccasin = {1.0f,0.8941176471f,0.7098039216f}; - static constexpr std::array papayawhip = {1.0f,0.937254902f,0.8352941176f}; - static constexpr std::array blanchedalmond = {1.0f,0.9215686275f,0.8039215686f}; - static constexpr std::array navajowhite = {1.0f,0.8705882353f,0.6784313725f}; - static constexpr std::array navajowhite1 = navajowhite; - static constexpr std::array navajowhite2 = {0.9333333333f,0.8117647059f,0.631372549f}; - static constexpr std::array navajowhite3 = {0.8039215686f,0.7019607843f,0.5450980392f}; - static constexpr std::array navajowhite4 = {0.5450980392f,0.4745098039f,0.368627451f}; - static constexpr std::array eggshell = {0.9882352941f,0.9019607843f,0.7882352941f}; - static constexpr std::array brick = {0.6117647059f,0.4f,0.1215686275f}; - static constexpr std::array cadmiumyellow = {1.0f,0.6f,0.0705882353f}; - static constexpr std::array antiquewhite = {0.9803921569f,0.9215686275f,0.8431372549f}; - static constexpr std::array antiquewhite1 = {1.0f,0.937254902f,0.8588235294f}; - static constexpr std::array antiquewhite2 = {0.9333333333f,0.8745098039f,0.8f}; - static constexpr std::array antiquewhite3 = {0.8039215686f,0.7529411765f,0.6901960784f}; - static constexpr std::array antiquewhite4 = {0.5450980392f,0.5137254902f,0.4705882353f}; - static constexpr std::array burlywood = {0.8705882353f,0.7215686275f,0.5294117647f}; - static constexpr std::array burlywood1 = {1.0f,0.8274509804f,0.6078431373f}; - static constexpr std::array burlywood2 = {0.9333333333f,0.7725490196f,0.568627451f}; - static constexpr std::array burlywood3 = {0.8039215686f,0.6666666667f,0.4901960784f}; - static constexpr std::array burlywood4 = {0.5450980392f,0.4509803922f,0.3333333333f}; - static constexpr std::array bisque = {1.0f,0.8941176471f,0.768627451f}; - static constexpr std::array bisque1 = bisque; - static constexpr std::array bisque2 = {0.9333333333f,0.8352941176f,0.7176470588f}; - static constexpr std::array bisque3 = {0.8039215686f,0.7176470588f,0.6196078431f}; - static constexpr std::array bisque4 = {0.5450980392f,0.4901960784f,0.4196078431f}; - static constexpr std::array melon = {0.8901960784f,0.6588235294f,0.4117647059f}; - static constexpr std::array carrot = {0.9294117647f,0.568627451f,0.1294117647f}; - static constexpr std::array darkorange = {1.0f,0.5490196078f,0.0f}; - static constexpr std::array darkorange1 = {1.0f,0.4980392157f,0.0f}; - static constexpr std::array darkorange2 = {0.9333333333f,0.462745098f,0.0f}; - static constexpr std::array darkorange3 = {0.8039215686f,0.4f,0.0f}; - static constexpr std::array darkorange4 = {0.5450980392f,0.2705882353f,0.0f}; - static constexpr std::array tan = {0.8235294118f,0.7058823529f,0.5490196078f}; - static constexpr std::array tan1 = {1.0f,0.6470588235f,0.3098039216f}; - static constexpr std::array tan2 = {0.9333333333f,0.6039215686f,0.2862745098f}; - static constexpr std::array tan3 = {0.8039215686f,0.5215686275f,0.2470588235f}; - static constexpr std::array peru = tan3; - static constexpr std::array tan4 = {0.5450980392f,0.3529411765f,0.168627451f}; - static constexpr std::array linen = {0.9803921569f,0.9411764706f,0.9019607843f}; - static constexpr std::array peachpuff = {1.0f,0.8549019608f,0.7254901961f}; - static constexpr std::array peachpuff1 = peachpuff; - static constexpr std::array peachpuff2 = {0.9333333333f,0.7960784314f,0.6784313725f}; - static constexpr std::array peachpuff3 = {0.8039215686f,0.6862745098f,0.5843137255f}; - static constexpr std::array peachpuff4 = {0.5450980392f,0.4666666667f,0.3960784314f}; - static constexpr std::array seashell = {1.0f,0.9607843137f,0.9333333333f}; - static constexpr std::array seashell1 = seashell; - static constexpr std::array seashell2 = {0.9333333333f,0.8980392157f,0.8705882353f}; - static constexpr std::array seashell3 = {0.8039215686f,0.7725490196f,0.7490196078f}; - static constexpr std::array seashell4 = {0.5450980392f,0.5254901961f,0.5098039216f}; - static constexpr std::array sandybrown = {0.9568627451f,0.6431372549f,0.3764705882f}; - static constexpr std::array rawsienna = {0.7803921569f,0.3803921569f,0.0784313725f}; - static constexpr std::array chocolate = {0.8235294118f,0.4117647059f,0.1176470588f}; - static constexpr std::array chocolate1 = {1.0f,0.4980392157f,0.1411764706f}; - static constexpr std::array chocolate2 = {0.9333333333f,0.462745098f,0.1294117647f}; - static constexpr std::array chocolate3 = {0.8039215686f,0.4f,0.1137254902f}; - static constexpr std::array chocolate4 = {0.5450980392f,0.2705882353f,0.0745098039f}; - static constexpr std::array saddlebrown = chocolate4; - static constexpr std::array ivoryblack = {0.1607843137f,0.1411764706f,0.1294117647f}; - static constexpr std::array flesh = {1.0f,0.4901960784f,0.2509803922f}; - static constexpr std::array cadmiumorange = {1.0f,0.3803921569f,0.0117647059f}; - static constexpr std::array burntsienna = {0.5411764706f,0.2117647059f,0.0588235294f}; - static constexpr std::array sienna = {0.6274509804f,0.3215686275f,0.1764705882f}; - static constexpr std::array sienna1 = {1.0f,0.5098039216f,0.2784313725f}; - static constexpr std::array sienna2 = {0.9333333333f,0.4745098039f,0.2588235294f}; - static constexpr std::array sienna3 = {0.8039215686f,0.4078431373f,0.2235294118f}; - static constexpr std::array sienna4 = {0.5450980392f,0.2784313725f,0.1490196078f}; - static constexpr std::array lightsalmon = {1.0f,0.6274509804f,0.4784313725f}; - static constexpr std::array lightsalmon1 = lightsalmon; - static constexpr std::array lightsalmon2 = {0.9333333333f,0.5843137255f,0.4470588235f}; - static constexpr std::array lightsalmon3 = {0.8039215686f,0.5058823529f,0.3843137255f}; - static constexpr std::array lightsalmon4 = {0.5450980392f,0.3411764706f,0.2588235294f}; - static constexpr std::array coral = {1.0f,0.4980392157f,0.3137254902f}; - static constexpr std::array orangered = {1.0f,0.2705882353f,0.0f}; - static constexpr std::array orangered1 = orangered; - static constexpr std::array orangered2 = {0.9333333333f,0.2509803922f,0.0f}; - static constexpr std::array orangered3 = {0.8039215686f,0.2156862745f,0.0f}; - static constexpr std::array orangered4 = {0.5450980392f,0.1450980392f,0.0f}; - static constexpr std::array sepia = {0.368627451f,0.1490196078f,0.0705882353f}; - static constexpr std::array darksalmon = {0.9137254902f,0.5882352941f,0.4784313725f}; - static constexpr std::array salmon1 = {1.0f,0.5490196078f,0.4117647059f}; - static constexpr std::array salmon2 = {0.9333333333f,0.5098039216f,0.3843137255f}; - static constexpr std::array salmon3 = {0.8039215686f,0.4392156863f,0.3294117647f}; - static constexpr std::array salmon4 = {0.5450980392f,0.2980392157f,0.2235294118f}; - static constexpr std::array coral1 = {1.0f,0.4470588235f,0.337254902f}; - static constexpr std::array coral2 = {0.9333333333f,0.4156862745f,0.3137254902f}; - static constexpr std::array coral3 = {0.8039215686f,0.3568627451f,0.2705882353f}; - static constexpr std::array coral4 = {0.5450980392f,0.2431372549f,0.1843137255f}; - static constexpr std::array burntumber = {0.5411764706f,0.2f,0.1411764706f}; - static constexpr std::array tomato = {1.0f,0.3882352941f,0.2784313725f}; - static constexpr std::array tomato1 = tomato; - static constexpr std::array tomato2 = {0.9333333333f,0.3607843137f,0.2588235294f}; - static constexpr std::array tomato3 = {0.8039215686f,0.3098039216f,0.2235294118f}; - static constexpr std::array tomato4 = {0.5450980392f,0.2117647059f,0.1490196078f}; - static constexpr std::array salmon = {0.9803921569f,0.5019607843f,0.4470588235f}; - static constexpr std::array mistyrose = {1.0f,0.8941176471f,0.8823529412f}; - static constexpr std::array mistyrose1 = mistyrose; - static constexpr std::array mistyrose2 = {0.9333333333f,0.8352941176f,0.8235294118f}; - static constexpr std::array mistyrose3 = {0.8039215686f,0.7176470588f,0.7098039216f}; - static constexpr std::array mistyrose4 = {0.5450980392f,0.4901960784f,0.4823529412f}; - static constexpr std::array snow = {1.0f,0.9803921569f,0.9803921569f}; - static constexpr std::array snow1 = snow; - static constexpr std::array snow2 = {0.9333333333f,0.9137254902f,0.9137254902f}; - static constexpr std::array snow3 = {0.8039215686f,0.7882352941f,0.7882352941f}; - static constexpr std::array snow4 = {0.5450980392f,0.537254902f,0.537254902f}; - static constexpr std::array rosybrown = {0.737254902f,0.5607843137f,0.5607843137f}; - static constexpr std::array rosybrown1 = {1.0f,0.7568627451f,0.7568627451f}; - static constexpr std::array rosybrown2 = {0.9333333333f,0.7058823529f,0.7058823529f}; - static constexpr std::array rosybrown3 = {0.8039215686f,0.6078431373f,0.6078431373f}; - static constexpr std::array rosybrown4 = {0.5450980392f,0.4117647059f,0.4117647059f}; - static constexpr std::array lightcoral = {0.9411764706f,0.5019607843f,0.5019607843f}; - static constexpr std::array indianred = {0.8039215686f,0.3607843137f,0.3607843137f}; - static constexpr std::array indianred1 = {1.0f,0.4156862745f,0.4156862745f}; - static constexpr std::array indianred2 = {0.9333333333f,0.3882352941f,0.3882352941f}; - static constexpr std::array indianred4 = {0.5450980392f,0.2274509804f,0.2274509804f}; - static constexpr std::array indianred3 = {0.8039215686f,0.3333333333f,0.3333333333f}; - static constexpr std::array brown = {0.6470588235f,0.1647058824f,0.1647058824f}; - static constexpr std::array brown1 = {1.0f,0.2509803922f,0.2509803922f}; - static constexpr std::array brown2 = {0.9333333333f,0.231372549f,0.231372549f}; - static constexpr std::array brown3 = {0.8039215686f,0.2f,0.2f}; - static constexpr std::array brown4 = {0.5450980392f,0.137254902f,0.137254902f}; - static constexpr std::array firebrick = {0.6980392157f,0.1333333333f,0.1333333333f}; - static constexpr std::array firebrick1 = {1.0f,0.1882352941f,0.1882352941f}; - static constexpr std::array firebrick2 = {0.9333333333f,0.1725490196f,0.1725490196f}; - static constexpr std::array firebrick3 = {0.8039215686f,0.1490196078f,0.1490196078f}; - static constexpr std::array firebrick4 = {0.5450980392f,0.1019607843f,0.1019607843f}; - static constexpr std::array red = {1.0f,0.0f,0.0f}; - static constexpr std::array red1 = red; - static constexpr std::array red2 = {0.9333333333f,0.0f,0.0f}; - static constexpr std::array red3 = {0.8039215686f,0.0f,0.0f}; - static constexpr std::array red4 = {0.5450980392f,0.0f,0.0f}; - static constexpr std::array darkred = red4; - static constexpr std::array maroon = {0.5019607843f,0.0f,0.0f}; - static constexpr std::array sgi_beet = {0.5568627451f,0.2196078431f,0.5568627451f}; - static constexpr std::array sgi_slateblue = {0.4431372549f,0.4431372549f,0.7764705882f}; - static constexpr std::array sgi_lightblue = {0.4901960784f,0.6196078431f,0.7529411765f}; - static constexpr std::array sgi_teal = {0.2196078431f,0.5568627451f,0.5568627451f}; - static constexpr std::array sgi_chartreuse = {0.4431372549f,0.7764705882f,0.4431372549f}; - static constexpr std::array sgi_olivedrab = {0.5568627451f,0.5568627451f,0.2196078431f}; - static constexpr std::array sgi_brightgray = {0.7725490196f,0.7568627451f,0.6666666667f}; - static constexpr std::array sgi_salmon = {0.7764705882f,0.4431372549f,0.4431372549f}; - static constexpr std::array sgi_darkgray = {0.3333333333f,0.3333333333f,0.3333333333f}; - static constexpr std::array sgi_gray12 = {0.1176470588f,0.1176470588f,0.1176470588f}; - static constexpr std::array sgi_gray16 = {0.1568627451f,0.1568627451f,0.1568627451f}; - static constexpr std::array sgi_gray32 = {0.3176470588f,0.3176470588f,0.3176470588f}; - static constexpr std::array sgi_gray36 = {0.3568627451f,0.3568627451f,0.3568627451f}; - static constexpr std::array sgi_gray52 = {0.5176470588f,0.5176470588f,0.5176470588f}; - static constexpr std::array sgi_gray56 = {0.5568627451f,0.5568627451f,0.5568627451f}; - static constexpr std::array sgi_lightgray = {0.6666666667f,0.6666666667f,0.6666666667f}; - static constexpr std::array sgi_gray72 = {0.7176470588f,0.7176470588f,0.7176470588f}; - static constexpr std::array sgi_gray76 = {0.7568627451f,0.7568627451f,0.7568627451f}; - static constexpr std::array sgi_gray92 = {0.9176470588f,0.9176470588f,0.9176470588f}; - static constexpr std::array sgi_gray96 = {0.9568627451f,0.9568627451f,0.9568627451f}; - static constexpr std::array white = {1.0f,1.0f,1.0f}; - static constexpr std::array white_smoke = {0.9607843137f,0.9607843137f,0.9607843137f}; - static constexpr std::array gainsboro = {0.862745098f,0.862745098f,0.862745098f}; - static constexpr std::array lightgrey = {0.8274509804f,0.8274509804f,0.8274509804f}; - static constexpr std::array silver = {0.7529411765f,0.7529411765f,0.7529411765f}; - static constexpr std::array darkgray = {0.662745098f,0.662745098f,0.662745098f}; - static constexpr std::array gray = {0.5019607843f,0.5019607843f,0.5019607843f}; - static constexpr std::array dimgray = {0.4117647059f,0.4117647059f,0.4117647059f}; - static constexpr std::array black = {0.0f,0.0f,0.0f}; - static constexpr std::array gray99 = {0.9882352941f,0.9882352941f,0.9882352941f}; - static constexpr std::array gray98 = {0.9803921569f,0.9803921569f,0.9803921569f}; - static constexpr std::array gray97 = {0.968627451f,0.968627451f,0.968627451f}; - static constexpr std::array gray96 = {0.9607843137f,0.9607843137f,0.9607843137f}; - static constexpr std::array gray95 = {0.9490196078f,0.9490196078f,0.9490196078f}; - static constexpr std::array gray94 = {0.9411764706f,0.9411764706f,0.9411764706f}; - static constexpr std::array gray93 = {0.9294117647f,0.9294117647f,0.9294117647f}; - static constexpr std::array gray92 = {0.9215686275f,0.9215686275f,0.9215686275f}; - static constexpr std::array gray91 = {0.9098039216f,0.9098039216f,0.9098039216f}; - static constexpr std::array gray90 = {0.8980392157f,0.8980392157f,0.8980392157f}; - static constexpr std::array gray89 = {0.8901960784f,0.8901960784f,0.8901960784f}; - static constexpr std::array gray88 = {0.8784313725f,0.8784313725f,0.8784313725f}; - static constexpr std::array gray87 = {0.8705882353f,0.8705882353f,0.8705882353f}; - static constexpr std::array gray86 = {0.8588235294f,0.8588235294f,0.8588235294f}; - static constexpr std::array gray85 = {0.8509803922f,0.8509803922f,0.8509803922f}; - static constexpr std::array gray84 = {0.8392156863f,0.8392156863f,0.8392156863f}; - static constexpr std::array gray83 = {0.831372549f,0.831372549f,0.831372549f}; - static constexpr std::array gray82 = {0.8196078431f,0.8196078431f,0.8196078431f}; - static constexpr std::array gray81 = {0.8117647059f,0.8117647059f,0.8117647059f}; - static constexpr std::array gray80 = {0.8f,0.8f,0.8f}; - static constexpr std::array gray79 = {0.7882352941f,0.7882352941f,0.7882352941f}; - static constexpr std::array gray78 = {0.7803921569f,0.7803921569f,0.7803921569f}; - static constexpr std::array gray77 = {0.768627451f,0.768627451f,0.768627451f}; - static constexpr std::array gray76 = {0.7607843137f,0.7607843137f,0.7607843137f}; - static constexpr std::array gray75 = {0.7490196078f,0.7490196078f,0.7490196078f}; - static constexpr std::array gray74 = {0.7411764706f,0.7411764706f,0.7411764706f}; - static constexpr std::array gray73 = {0.7294117647f,0.7294117647f,0.7294117647f}; - static constexpr std::array gray72 = {0.7215686275f,0.7215686275f,0.7215686275f}; - static constexpr std::array gray71 = {0.7098039216f,0.7098039216f,0.7098039216f}; - static constexpr std::array gray70 = {0.7019607843f,0.7019607843f,0.7019607843f}; - static constexpr std::array gray69 = {0.6901960784f,0.6901960784f,0.6901960784f}; - static constexpr std::array gray68 = {0.6784313725f,0.6784313725f,0.6784313725f}; - static constexpr std::array gray67 = {0.6705882353f,0.6705882353f,0.6705882353f}; - static constexpr std::array gray66 = {0.6588235294f,0.6588235294f,0.6588235294f}; - static constexpr std::array gray65 = {0.6509803922f,0.6509803922f,0.6509803922f}; - static constexpr std::array gray64 = {0.6392156863f,0.6392156863f,0.6392156863f}; - static constexpr std::array gray63 = {0.631372549f,0.631372549f,0.631372549f}; - static constexpr std::array gray62 = {0.6196078431f,0.6196078431f,0.6196078431f}; - static constexpr std::array gray61 = {0.6117647059f,0.6117647059f,0.6117647059f}; - static constexpr std::array gray60 = {0.6f,0.6f,0.6f}; - static constexpr std::array gray59 = {0.5882352941f,0.5882352941f,0.5882352941f}; - static constexpr std::array gray58 = {0.5803921569f,0.5803921569f,0.5803921569f}; - static constexpr std::array gray57 = {0.568627451f,0.568627451f,0.568627451f}; - static constexpr std::array gray56 = {0.5607843137f,0.5607843137f,0.5607843137f}; - static constexpr std::array gray55 = {0.5490196078f,0.5490196078f,0.5490196078f}; - static constexpr std::array gray54 = {0.5411764706f,0.5411764706f,0.5411764706f}; - static constexpr std::array gray53 = {0.5294117647f,0.5294117647f,0.5294117647f}; - static constexpr std::array gray52 = {0.5215686275f,0.5215686275f,0.5215686275f}; - static constexpr std::array gray51 = {0.5098039216f,0.5098039216f,0.5098039216f}; - static constexpr std::array gray50 = {0.4980392157f,0.4980392157f,0.4980392157f}; - static constexpr std::array gray49 = {0.4901960784f,0.4901960784f,0.4901960784f}; - static constexpr std::array gray48 = {0.4784313725f,0.4784313725f,0.4784313725f}; - static constexpr std::array gray47 = {0.4705882353f,0.4705882353f,0.4705882353f}; - static constexpr std::array gray46 = {0.4588235294f,0.4588235294f,0.4588235294f}; - static constexpr std::array gray45 = {0.4509803922f,0.4509803922f,0.4509803922f}; - static constexpr std::array gray44 = {0.4392156863f,0.4392156863f,0.4392156863f}; - static constexpr std::array gray43 = {0.431372549f,0.431372549f,0.431372549f}; - static constexpr std::array gray42 = {0.4196078431f,0.4196078431f,0.4196078431f}; - static constexpr std::array gray41 = {0.4117647059f,0.4117647059f,0.4117647059f}; - static constexpr std::array gray40 = {0.4f,0.4f,0.4f}; - static constexpr std::array gray39 = {0.3882352941f,0.3882352941f,0.3882352941f}; - static constexpr std::array gray38 = {0.3803921569f,0.3803921569f,0.3803921569f}; - static constexpr std::array gray37 = {0.368627451f,0.368627451f,0.368627451f}; - static constexpr std::array gray36 = {0.3607843137f,0.3607843137f,0.3607843137f}; - static constexpr std::array gray35 = {0.3490196078f,0.3490196078f,0.3490196078f}; - static constexpr std::array gray34 = {0.3411764706f,0.3411764706f,0.3411764706f}; - static constexpr std::array gray33 = {0.3294117647f,0.3294117647f,0.3294117647f}; - static constexpr std::array gray32 = {0.3215686275f,0.3215686275f,0.3215686275f}; - static constexpr std::array gray31 = {0.3098039216f,0.3098039216f,0.3098039216f}; - static constexpr std::array gray30 = {0.3019607843f,0.3019607843f,0.3019607843f}; - static constexpr std::array gray29 = {0.2901960784f,0.2901960784f,0.2901960784f}; - static constexpr std::array gray28 = {0.2784313725f,0.2784313725f,0.2784313725f}; - static constexpr std::array gray27 = {0.2705882353f,0.2705882353f,0.2705882353f}; - static constexpr std::array gray26 = {0.2588235294f,0.2588235294f,0.2588235294f}; - static constexpr std::array gray25 = {0.2509803922f,0.2509803922f,0.2509803922f}; - static constexpr std::array gray24 = {0.2392156863f,0.2392156863f,0.2392156863f}; - static constexpr std::array gray23 = {0.231372549f,0.231372549f,0.231372549f}; - static constexpr std::array gray22 = {0.2196078431f,0.2196078431f,0.2196078431f}; - static constexpr std::array gray21 = {0.2117647059f,0.2117647059f,0.2117647059f}; - static constexpr std::array gray20 = {0.2f,0.2f,0.2f}; - static constexpr std::array gray19 = {0.1882352941f,0.1882352941f,0.1882352941f}; - static constexpr std::array gray18 = {0.1803921569f,0.1803921569f,0.1803921569f}; - static constexpr std::array gray17 = {0.168627451f,0.168627451f,0.168627451f}; - static constexpr std::array gray16 = {0.1607843137f,0.1607843137f,0.1607843137f}; - static constexpr std::array gray15 = {0.1490196078f,0.1490196078f,0.1490196078f}; - static constexpr std::array gray14 = {0.1411764706f,0.1411764706f,0.1411764706f}; - static constexpr std::array gray13 = {0.1294117647f,0.1294117647f,0.1294117647f}; - static constexpr std::array gray12 = {0.1215686275f,0.1215686275f,0.1215686275f}; - static constexpr std::array gray11 = {0.1098039216f,0.1098039216f,0.1098039216f}; - static constexpr std::array gray10 = {0.1019607843f,0.1019607843f,0.1019607843f}; - static constexpr std::array gray9 = {0.0901960784f,0.0901960784f,0.0901960784f}; - static constexpr std::array gray8 = {0.0784313725f,0.0784313725f,0.0784313725f}; - static constexpr std::array gray7 = {0.0705882353f,0.0705882353f,0.0705882353f}; - static constexpr std::array gray6 = {0.0588235294f,0.0588235294f,0.0588235294f}; - static constexpr std::array gray5 = {0.0509803922f,0.0509803922f,0.0509803922f}; - static constexpr std::array gray4 = {0.0392156863f,0.0392156863f,0.0392156863f}; - static constexpr std::array gray3 = {0.031372549f,0.031372549f,0.031372549f}; - static constexpr std::array gray2 = {0.0196078431f,0.0196078431f,0.0196078431f}; - static constexpr std::array gray1 = {0.0117647059f,0.0117647059f,0.0117647059f}; - static constexpr std::array grey99 = {0.9882352941f,0.9882352941f,0.9882352941f}; - static constexpr std::array grey98 = {0.9803921569f,0.9803921569f,0.9803921569f}; - static constexpr std::array grey97 = {0.968627451f,0.968627451f,0.968627451f}; - static constexpr std::array grey96 = {0.9607843137f,0.9607843137f,0.9607843137f}; - static constexpr std::array grey95 = {0.9490196078f,0.9490196078f,0.9490196078f}; - static constexpr std::array grey94 = {0.9411764706f,0.9411764706f,0.9411764706f}; - static constexpr std::array grey93 = {0.9294117647f,0.9294117647f,0.9294117647f}; - static constexpr std::array grey92 = {0.9215686275f,0.9215686275f,0.9215686275f}; - static constexpr std::array grey91 = {0.9098039216f,0.9098039216f,0.9098039216f}; - static constexpr std::array grey90 = {0.8980392157f,0.8980392157f,0.8980392157f}; - static constexpr std::array grey89 = {0.8901960784f,0.8901960784f,0.8901960784f}; - static constexpr std::array grey88 = {0.8784313725f,0.8784313725f,0.8784313725f}; - static constexpr std::array grey87 = {0.8705882353f,0.8705882353f,0.8705882353f}; - static constexpr std::array grey86 = {0.8588235294f,0.8588235294f,0.8588235294f}; - static constexpr std::array grey85 = {0.8509803922f,0.8509803922f,0.8509803922f}; - static constexpr std::array grey84 = {0.8392156863f,0.8392156863f,0.8392156863f}; - static constexpr std::array grey83 = {0.831372549f,0.831372549f,0.831372549f}; - static constexpr std::array grey82 = {0.8196078431f,0.8196078431f,0.8196078431f}; - static constexpr std::array grey81 = {0.8117647059f,0.8117647059f,0.8117647059f}; - static constexpr std::array grey80 = {0.8f,0.8f,0.8f}; - static constexpr std::array grey79 = {0.7882352941f,0.7882352941f,0.7882352941f}; - static constexpr std::array grey78 = {0.7803921569f,0.7803921569f,0.7803921569f}; - static constexpr std::array grey77 = {0.768627451f,0.768627451f,0.768627451f}; - static constexpr std::array grey76 = {0.7607843137f,0.7607843137f,0.7607843137f}; - static constexpr std::array grey75 = {0.7490196078f,0.7490196078f,0.7490196078f}; - static constexpr std::array grey74 = {0.7411764706f,0.7411764706f,0.7411764706f}; - static constexpr std::array grey73 = {0.7294117647f,0.7294117647f,0.7294117647f}; - static constexpr std::array grey72 = {0.7215686275f,0.7215686275f,0.7215686275f}; - static constexpr std::array grey71 = {0.7098039216f,0.7098039216f,0.7098039216f}; - static constexpr std::array grey70 = {0.7019607843f,0.7019607843f,0.7019607843f}; - static constexpr std::array grey69 = {0.6901960784f,0.6901960784f,0.6901960784f}; - static constexpr std::array grey68 = {0.6784313725f,0.6784313725f,0.6784313725f}; - static constexpr std::array grey67 = {0.6705882353f,0.6705882353f,0.6705882353f}; - static constexpr std::array grey66 = {0.6588235294f,0.6588235294f,0.6588235294f}; - static constexpr std::array grey65 = {0.6509803922f,0.6509803922f,0.6509803922f}; - static constexpr std::array grey64 = {0.6392156863f,0.6392156863f,0.6392156863f}; - static constexpr std::array grey63 = {0.631372549f,0.631372549f,0.631372549f}; - static constexpr std::array grey62 = {0.6196078431f,0.6196078431f,0.6196078431f}; - static constexpr std::array grey61 = {0.6117647059f,0.6117647059f,0.6117647059f}; - static constexpr std::array grey60 = {0.6f,0.6f,0.6f}; - static constexpr std::array grey59 = {0.5882352941f,0.5882352941f,0.5882352941f}; - static constexpr std::array grey58 = {0.5803921569f,0.5803921569f,0.5803921569f}; - static constexpr std::array grey57 = {0.568627451f,0.568627451f,0.568627451f}; - static constexpr std::array grey56 = {0.5607843137f,0.5607843137f,0.5607843137f}; - static constexpr std::array grey55 = {0.5490196078f,0.5490196078f,0.5490196078f}; - static constexpr std::array grey54 = {0.5411764706f,0.5411764706f,0.5411764706f}; - static constexpr std::array grey53 = {0.5294117647f,0.5294117647f,0.5294117647f}; - static constexpr std::array grey52 = {0.5215686275f,0.5215686275f,0.5215686275f}; - static constexpr std::array grey51 = {0.5098039216f,0.5098039216f,0.5098039216f}; - static constexpr std::array grey50 = {0.4980392157f,0.4980392157f,0.4980392157f}; - static constexpr std::array grey49 = {0.4901960784f,0.4901960784f,0.4901960784f}; - static constexpr std::array grey48 = {0.4784313725f,0.4784313725f,0.4784313725f}; - static constexpr std::array grey47 = {0.4705882353f,0.4705882353f,0.4705882353f}; - static constexpr std::array grey46 = {0.4588235294f,0.4588235294f,0.4588235294f}; - static constexpr std::array grey45 = {0.4509803922f,0.4509803922f,0.4509803922f}; - static constexpr std::array grey44 = {0.4392156863f,0.4392156863f,0.4392156863f}; - static constexpr std::array grey43 = {0.431372549f,0.431372549f,0.431372549f}; - static constexpr std::array grey42 = {0.4196078431f,0.4196078431f,0.4196078431f}; - static constexpr std::array grey41 = {0.4117647059f,0.4117647059f,0.4117647059f}; - static constexpr std::array grey40 = {0.4f,0.4f,0.4f}; - static constexpr std::array grey39 = {0.3882352941f,0.3882352941f,0.3882352941f}; - static constexpr std::array grey38 = {0.3803921569f,0.3803921569f,0.3803921569f}; - static constexpr std::array grey37 = {0.368627451f,0.368627451f,0.368627451f}; - static constexpr std::array grey36 = {0.3607843137f,0.3607843137f,0.3607843137f}; - static constexpr std::array grey35 = {0.3490196078f,0.3490196078f,0.3490196078f}; - static constexpr std::array grey34 = {0.3411764706f,0.3411764706f,0.3411764706f}; - static constexpr std::array grey33 = {0.3294117647f,0.3294117647f,0.3294117647f}; - static constexpr std::array grey32 = {0.3215686275f,0.3215686275f,0.3215686275f}; - static constexpr std::array grey31 = {0.3098039216f,0.3098039216f,0.3098039216f}; - static constexpr std::array grey30 = {0.3019607843f,0.3019607843f,0.3019607843f}; - static constexpr std::array grey29 = {0.2901960784f,0.2901960784f,0.2901960784f}; - static constexpr std::array grey28 = {0.2784313725f,0.2784313725f,0.2784313725f}; - static constexpr std::array grey27 = {0.2705882353f,0.2705882353f,0.2705882353f}; - static constexpr std::array grey26 = {0.2588235294f,0.2588235294f,0.2588235294f}; - static constexpr std::array grey25 = {0.2509803922f,0.2509803922f,0.2509803922f}; - static constexpr std::array grey24 = {0.2392156863f,0.2392156863f,0.2392156863f}; - static constexpr std::array grey23 = {0.231372549f,0.231372549f,0.231372549f}; - static constexpr std::array grey22 = {0.2196078431f,0.2196078431f,0.2196078431f}; - static constexpr std::array grey21 = {0.2117647059f,0.2117647059f,0.2117647059f}; - static constexpr std::array grey20 = {0.2f,0.2f,0.2f}; - static constexpr std::array grey19 = {0.1882352941f,0.1882352941f,0.1882352941f}; - static constexpr std::array grey18 = {0.1803921569f,0.1803921569f,0.1803921569f}; - static constexpr std::array grey17 = {0.168627451f,0.168627451f,0.168627451f}; - static constexpr std::array grey16 = {0.1607843137f,0.1607843137f,0.1607843137f}; - static constexpr std::array grey15 = {0.1490196078f,0.1490196078f,0.1490196078f}; - static constexpr std::array grey14 = {0.1411764706f,0.1411764706f,0.1411764706f}; - static constexpr std::array grey13 = {0.1294117647f,0.1294117647f,0.1294117647f}; - static constexpr std::array grey12 = {0.1215686275f,0.1215686275f,0.1215686275f}; - static constexpr std::array grey11 = {0.1098039216f,0.1098039216f,0.1098039216f}; - static constexpr std::array grey10 = {0.1019607843f,0.1019607843f,0.1019607843f}; - static constexpr std::array grey9 = {0.0901960784f,0.0901960784f,0.0901960784f}; - static constexpr std::array grey8 = {0.0784313725f,0.0784313725f,0.0784313725f}; - static constexpr std::array grey7 = {0.0705882353f,0.0705882353f,0.0705882353f}; - static constexpr std::array grey6 = {0.0588235294f,0.0588235294f,0.0588235294f}; - static constexpr std::array grey5 = {0.0509803922f,0.0509803922f,0.0509803922f}; - static constexpr std::array grey4 = {0.0392156863f,0.0392156863f,0.0392156863f}; - static constexpr std::array grey3 = {0.031372549f,0.031372549f,0.031372549f}; - static constexpr std::array grey2 = {0.0196078431f,0.0196078431f,0.0196078431f}; - static constexpr std::array grey1 = {0.0117647059f,0.0117647059f,0.0117647059f}; - } // end of namespace colour -} // namespace mplot +namespace mplot::colour +{ + static constexpr std::array indian_red = {0.6901960784f,0.0901960784f,0.1215686275f}; + static constexpr std::array crimson = {0.862745098f,0.0784313725f,0.2352941176f}; + static constexpr std::array lightpink = {1.0f,0.7137254902f,0.7568627451f}; + static constexpr std::array lightpink1 = {1.0f,0.6823529412f,0.7254901961f}; + static constexpr std::array lightpink2 = {0.9333333333f,0.6352941176f,0.6784313725f}; + static constexpr std::array lightpink3 = {0.8039215686f,0.5490196078f,0.5843137255f}; + static constexpr std::array lightpink4 = {0.5450980392f,0.3725490196f,0.3960784314f}; + static constexpr std::array pink = {1.0f,0.7529411765f,0.7960784314f}; + static constexpr std::array pink1 = {1.0f,0.7098039216f,0.7725490196f}; + static constexpr std::array pink2 = {0.9333333333f,0.662745098f,0.7215686275f}; + static constexpr std::array pink3 = {0.8039215686f,0.568627451f,0.6196078431f}; + static constexpr std::array pink4 = {0.5450980392f,0.3882352941f,0.4235294118f}; + static constexpr std::array palevioletred = {0.8588235294f,0.4392156863f,0.5764705882f}; + static constexpr std::array palevioletred1 = {1.0f,0.5098039216f,0.6705882353f}; + static constexpr std::array palevioletred2 = {0.9333333333f,0.4745098039f,0.6235294118f}; + static constexpr std::array palevioletred3 = {0.8039215686f,0.4078431373f,0.537254902f}; + static constexpr std::array palevioletred4 = {0.5450980392f,0.2784313725f,0.3647058824f}; + static constexpr std::array lavenderblush = {1.0f,0.9411764706f,0.9607843137f}; + static constexpr std::array lavenderblush1 = lavenderblush; + static constexpr std::array lavenderblush2 = {0.9333333333f,0.8784313725f,0.8980392157f}; + static constexpr std::array lavenderblush3 = {0.8039215686f,0.7568627451f,0.7725490196f}; + static constexpr std::array lavenderblush4 = {0.5450980392f,0.5137254902f,0.5254901961f}; + static constexpr std::array violetred1 = {1.0f,0.2431372549f,0.5882352941f}; + static constexpr std::array violetred2 = {0.9333333333f,0.2274509804f,0.5490196078f}; + static constexpr std::array violetred3 = {0.8039215686f,0.1960784314f,0.4705882353f}; + static constexpr std::array violetred4 = {0.5450980392f,0.1333333333f,0.3215686275f}; + static constexpr std::array hotpink = {1.0f,0.4117647059f,0.7058823529f}; + static constexpr std::array hotpink1 = {1.0f,0.431372549f,0.7058823529f}; + static constexpr std::array hotpink2 = {0.9333333333f,0.4156862745f,0.6549019608f}; + static constexpr std::array hotpink3 = {0.8039215686f,0.3764705882f,0.5647058824f}; + static constexpr std::array hotpink4 = {0.5450980392f,0.2274509804f,0.3843137255f}; + static constexpr std::array raspberry = {0.5294117647f,0.1490196078f,0.3411764706f}; + static constexpr std::array deeppink = {1.0f,0.0784313725f,0.5764705882f}; + static constexpr std::array deeppink1 = {1.0f,0.0784313725f,0.5764705882f}; + static constexpr std::array deeppink2 = {0.9333333333f,0.0705882353f,0.537254902f}; + static constexpr std::array deeppink3 = {0.8039215686f,0.062745098f,0.462745098f}; + static constexpr std::array deeppink4 = {0.5450980392f,0.0392156863f,0.3137254902f}; + static constexpr std::array maroon1 = {1.0f,0.2039215686f,0.7019607843f}; + static constexpr std::array maroon2 = {0.9333333333f,0.1882352941f,0.6549019608f}; + static constexpr std::array maroon3 = {0.8039215686f,0.1607843137f,0.5647058824f}; + static constexpr std::array maroon4 = {0.5450980392f,0.1098039216f,0.3843137255f}; + static constexpr std::array mediumvioletred = {0.7803921569f,0.0823529412f,0.5215686275f}; + static constexpr std::array violetred = {0.8156862745f,0.1254901961f,0.5647058824f}; + static constexpr std::array orchid = {0.8549019608f,0.4392156863f,0.8392156863f}; + static constexpr std::array orchid1 = {1.0f,0.5137254902f,0.9803921569f}; + static constexpr std::array orchid2 = {0.9333333333f,0.4784313725f,0.9137254902f}; + static constexpr std::array orchid3 = {0.8039215686f,0.4117647059f,0.7882352941f}; + static constexpr std::array orchid4 = {0.5450980392f,0.2784313725f,0.537254902f}; + static constexpr std::array thistle = {0.8470588235f,0.7490196078f,0.8470588235f}; + static constexpr std::array thistle1 = {1.0f,0.8823529412f,1.0f}; + static constexpr std::array thistle2 = {0.9333333333f,0.8235294118f,0.9333333333f}; + static constexpr std::array thistle3 = {0.8039215686f,0.7098039216f,0.8039215686f}; + static constexpr std::array thistle4 = {0.5450980392f,0.4823529412f,0.5450980392f}; + static constexpr std::array plum1 = {1.0f,0.7333333333f,1.0f}; + static constexpr std::array plum2 = {0.9333333333f,0.6823529412f,0.9333333333f}; + static constexpr std::array plum3 = {0.8039215686f,0.5882352941f,0.8039215686f}; + static constexpr std::array plum4 = {0.5450980392f,0.4f,0.5450980392f}; + static constexpr std::array plum = {0.8666666667f,0.6274509804f,0.8666666667f}; + static constexpr std::array violet = {0.9333333333f,0.5098039216f,0.9333333333f}; + static constexpr std::array magenta = {1.0f,0.0f,1.0f}; + static constexpr std::array fuchsia = magenta; + static constexpr std::array magenta2 = {0.9333333333f,0.0f,0.9333333333f}; + static constexpr std::array magenta3 = {0.8039215686f,0.0f,0.8039215686f}; + static constexpr std::array magenta4 = {0.5450980392f,0.0f,0.5450980392f}; + static constexpr std::array darkmagenta = magenta4; + static constexpr std::array purple = {0.5019607843f,0.0f,0.5019607843f}; + static constexpr std::array mediumorchid = {0.7294117647f,0.3333333333f,0.8274509804f}; + static constexpr std::array mediumorchid1 = {0.8784313725f,0.4f,1.0f}; + static constexpr std::array mediumorchid2 = {0.8196078431f,0.3725490196f,0.9333333333f}; + static constexpr std::array mediumorchid3 = {0.7058823529f,0.3215686275f,0.8039215686f}; + static constexpr std::array mediumorchid4 = {0.4784313725f,0.2156862745f,0.5450980392f}; + static constexpr std::array darkviolet = {0.5803921569f,0.0f,0.8274509804f}; + static constexpr std::array darkorchid = {0.6f,0.1960784314f,0.8f}; + static constexpr std::array darkorchid1 = {0.7490196078f,0.2431372549f,1.0f}; + static constexpr std::array darkorchid2 = {0.6980392157f,0.2274509804f,0.9333333333f}; + static constexpr std::array darkorchid3 = {0.6039215686f,0.1960784314f,0.8039215686f}; + static constexpr std::array darkorchid4 = {0.4078431373f,0.1333333333f,0.5450980392f}; + static constexpr std::array indigo = {0.2941176471f,0.0f,0.5098039216f}; + static constexpr std::array blueviolet = {0.5411764706f,0.168627451f,0.8862745098f}; + static constexpr std::array purple1 = {0.6078431373f,0.1882352941f,1.0f}; + static constexpr std::array purple2 = {0.568627451f,0.1725490196f,0.9333333333f}; + static constexpr std::array purple3 = {0.4901960784f,0.1490196078f,0.8039215686f}; + static constexpr std::array purple4 = {0.3333333333f,0.1019607843f,0.5450980392f}; + static constexpr std::array mediumpurple = {0.5764705882f,0.4392156863f,0.8588235294f}; + static constexpr std::array mediumpurple1 = {0.6705882353f,0.5098039216f,1.0f}; + static constexpr std::array mediumpurple2 = {0.6235294118f,0.4745098039f,0.9333333333f}; + static constexpr std::array mediumpurple3 = {0.537254902f,0.4078431373f,0.8039215686f}; + static constexpr std::array mediumpurple4 = {0.3647058824f,0.2784313725f,0.5450980392f}; + static constexpr std::array darkslateblue = {0.2823529412f,0.2392156863f,0.5450980392f}; + static constexpr std::array lightslateblue = {0.5176470588f,0.4392156863f,1.0f}; + static constexpr std::array mediumslateblue = {0.4823529412f,0.4078431373f,0.9333333333f}; + static constexpr std::array slateblue = {0.4156862745f,0.3529411765f,0.8039215686f}; + static constexpr std::array slateblue1 = {0.5137254902f,0.4352941176f,1.0f}; + static constexpr std::array slateblue2 = {0.4784313725f,0.4039215686f,0.9333333333f}; + static constexpr std::array slateblue3 = {0.4117647059f,0.3490196078f,0.8039215686f}; + static constexpr std::array slateblue4 = {0.2784313725f,0.2352941176f,0.5450980392f}; + static constexpr std::array ghostwhite = {0.9725490196f,0.9725490196f,1.0f}; + static constexpr std::array lavender = {0.9019607843f,0.9019607843f,0.9803921569f}; + static constexpr std::array blue = {0.0f,0.0f,1.0f}; + static constexpr std::array blue1 = blue; + static constexpr std::array blue2 = {0.0f,0.0f,0.9333333333f}; + static constexpr std::array blue3 = {0.0f,0.0f,0.8039215686f}; + static constexpr std::array mediumblue = blue3; + static constexpr std::array blue4 = {0.0f,0.0f,0.5450980392f}; + static constexpr std::array darkblue = blue4; + static constexpr std::array navy = {0.0f,0.0f,0.5019607843f}; + static constexpr std::array midnightblue = {0.0980392157f,0.0980392157f,0.4392156863f}; + static constexpr std::array cobalt = {0.2392156863f,0.3490196078f,0.6705882353f}; + static constexpr std::array royalblue = {0.2549019608f,0.4117647059f,0.8823529412f}; + static constexpr std::array royalblue1 = {0.2823529412f,0.462745098f,1.0f}; + static constexpr std::array royalblue2 = {0.262745098f,0.431372549f,0.9333333333f}; + static constexpr std::array royalblue3 = {0.2274509804f,0.3725490196f,0.8039215686f}; + static constexpr std::array royalblue4 = {0.1529411765f,0.2509803922f,0.5450980392f}; + static constexpr std::array cornflowerblue = {0.3921568627f,0.5843137255f,0.9294117647f}; + static constexpr std::array lightsteelblue = {0.6901960784f,0.768627451f,0.8705882353f}; + static constexpr std::array lightsteelblue1 = {0.7921568627f,0.8823529412f,1.0f}; + static constexpr std::array lightsteelblue2 = {0.737254902f,0.8235294118f,0.9333333333f}; + static constexpr std::array lightsteelblue3 = {0.6352941176f,0.7098039216f,0.8039215686f}; + static constexpr std::array lightsteelblue4 = {0.431372549f,0.4823529412f,0.5450980392f}; + static constexpr std::array lightslategray = {0.4666666667f,0.5333333333f,0.6f}; + static constexpr std::array slategray = {0.4392156863f,0.5019607843f,0.5647058824f}; + static constexpr std::array slategray1 = {0.7764705882f,0.8862745098f,1.0f}; + static constexpr std::array slategray2 = {0.7254901961f,0.8274509804f,0.9333333333f}; + static constexpr std::array slategray3 = {0.6235294118f,0.7137254902f,0.8039215686f}; + static constexpr std::array slategray4 = {0.4235294118f,0.4823529412f,0.5450980392f}; + static constexpr std::array dodgerblue = {0.1176470588f,0.5647058824f,1.0f}; + static constexpr std::array dodgerblue1 = dodgerblue; + static constexpr std::array dodgerblue2 = {0.1098039216f,0.5254901961f,0.9333333333f}; + static constexpr std::array dodgerblue3 = {0.0941176471f,0.4549019608f,0.8039215686f}; + static constexpr std::array dodgerblue4 = {0.062745098f,0.3058823529f,0.5450980392f}; + static constexpr std::array aliceblue = {0.9411764706f,0.9725490196f,1.0f}; + static constexpr std::array steelblue = {0.2745098039f,0.5098039216f,0.7058823529f}; + static constexpr std::array steelblue1 = {0.3882352941f,0.7215686275f,1.0f}; + static constexpr std::array steelblue2 = {0.3607843137f,0.6745098039f,0.9333333333f}; + static constexpr std::array steelblue3 = {0.3098039216f,0.5803921569f,0.8039215686f}; + static constexpr std::array steelblue4 = {0.2117647059f,0.3921568627f,0.5450980392f}; + static constexpr std::array lightskyblue = {0.5294117647f,0.8078431373f,0.9803921569f}; + static constexpr std::array lightskyblue1 = {0.6901960784f,0.8862745098f,1.0f}; + static constexpr std::array lightskyblue2 = {0.6431372549f,0.8274509804f,0.9333333333f}; + static constexpr std::array lightskyblue3 = {0.5529411765f,0.7137254902f,0.8039215686f}; + static constexpr std::array lightskyblue4 = {0.3764705882f,0.4823529412f,0.5450980392f}; + static constexpr std::array skyblue = {0.5294117647f,0.8078431373f,0.9215686275f}; + static constexpr std::array skyblue1 = {0.5294117647f,0.8078431373f,1.0f}; + static constexpr std::array skyblue2 = {0.4941176471f,0.7529411765f,0.9333333333f}; + static constexpr std::array skyblue3 = {0.4235294118f,0.6509803922f,0.8039215686f}; + static constexpr std::array skyblue4 = {0.2901960784f,0.4392156863f,0.5450980392f}; + static constexpr std::array deepskyblue = {0.0f,0.7490196078f,1.0f}; + static constexpr std::array deepskyblue1 = deepskyblue; + static constexpr std::array deepskyblue2 = {0.0f,0.6980392157f,0.9333333333f}; + static constexpr std::array deepskyblue3 = {0.0f,0.6039215686f,0.8039215686f}; + static constexpr std::array deepskyblue4 = {0.0f,0.4078431373f,0.5450980392f}; + static constexpr std::array peacock = {0.2f,0.631372549f,0.7882352941f}; + static constexpr std::array lightblue = {0.6784313725f,0.8470588235f,0.9019607843f}; + static constexpr std::array lightblue1 = {0.7490196078f,0.937254902f,1.0f}; + static constexpr std::array lightblue2 = {0.6980392157f,0.8745098039f,0.9333333333f}; + static constexpr std::array lightblue3 = {0.6039215686f,0.7529411765f,0.8039215686f}; + static constexpr std::array lightblue4 = {0.4078431373f,0.5137254902f,0.5450980392f}; + static constexpr std::array powderblue = {0.6901960784f,0.8784313725f,0.9019607843f}; + static constexpr std::array cadetblue1 = {0.5960784314f,0.9607843137f,1.0f}; + static constexpr std::array cadetblue2 = {0.5568627451f,0.8980392157f,0.9333333333f}; + static constexpr std::array cadetblue3 = {0.4784313725f,0.7725490196f,0.8039215686f}; + static constexpr std::array cadetblue4 = {0.3254901961f,0.5254901961f,0.5450980392f}; + static constexpr std::array turquoise1 = {0.0f,0.9607843137f,1.0f}; + static constexpr std::array turquoise2 = {0.0f,0.8980392157f,0.9333333333f}; + static constexpr std::array turquoise3 = {0.0f,0.7725490196f,0.8039215686f}; + static constexpr std::array turquoise4 = {0.0f,0.5254901961f,0.5450980392f}; + static constexpr std::array cadetblue = {0.3725490196f,0.6196078431f,0.6274509804f}; + static constexpr std::array darkturquoise = {0.0f,0.8078431373f,0.8196078431f}; + static constexpr std::array azure = {0.9411764706f,1.0f,1.0f}; + static constexpr std::array azure1 = azure; + static constexpr std::array azure2 = {0.8784313725f,0.9333333333f,0.9333333333f}; + static constexpr std::array azure3 = {0.7568627451f,0.8039215686f,0.8039215686f}; + static constexpr std::array azure4 = {0.5137254902f,0.5450980392f,0.5450980392f}; + static constexpr std::array lightcyan = {0.8784313725f,1.0f,1.0f}; + static constexpr std::array lightcyan1 = lightcyan; + static constexpr std::array lightcyan2 = {0.8196078431f,0.9333333333f,0.9333333333f}; + static constexpr std::array lightcyan3 = {0.7058823529f,0.8039215686f,0.8039215686f}; + static constexpr std::array lightcyan4 = {0.4784313725f,0.5450980392f,0.5450980392f}; + static constexpr std::array paleturquoise1 = {0.7333333333f,1.0f,1.0f}; + static constexpr std::array paleturquoise = {0.6823529412f,0.9333333333f,0.9333333333f}; + static constexpr std::array paleturquoise2 = paleturquoise; + static constexpr std::array paleturquoise3 = {0.5882352941f,0.8039215686f,0.8039215686f}; + static constexpr std::array paleturquoise4 = {0.4f,0.5450980392f,0.5450980392f}; + static constexpr std::array darkslategray = {0.1843137255f,0.3098039216f,0.3098039216f}; + static constexpr std::array darkslategray1 = {0.5921568627f,1.0f,1.0f}; + static constexpr std::array darkslategray2 = {0.5529411765f,0.9333333333f,0.9333333333f}; + static constexpr std::array darkslategray3 = {0.4745098039f,0.8039215686f,0.8039215686f}; + static constexpr std::array darkslategray4 = {0.3215686275f,0.5450980392f,0.5450980392f}; + static constexpr std::array cyan = {0.0f,1.0f,1.0f}; + static constexpr std::array cyan1 = cyan; + static constexpr std::array cyan2 = {0.0f,0.9333333333f,0.9333333333f}; + static constexpr std::array cyan3 = {0.0f,0.8039215686f,0.8039215686f}; + static constexpr std::array cyan4 = {0.0f,0.5450980392f,0.5450980392f}; + static constexpr std::array darkcyan = cyan4; + static constexpr std::array teal = {0.0f,0.5019607843f,0.5019607843f}; + static constexpr std::array mediumturquoise = {0.2823529412f,0.8196078431f,0.8f}; + static constexpr std::array lightseagreen = {0.1254901961f,0.6980392157f,0.6666666667f}; + static constexpr std::array manganeseblue = {0.0117647059f,0.6588235294f,0.6196078431f}; + static constexpr std::array turquoise = {0.2509803922f,0.8784313725f,0.8156862745f}; + static constexpr std::array coldgrey = {0.5019607843f,0.5411764706f,0.5294117647f}; + static constexpr std::array turquoiseblue = {0.0f,0.7803921569f,0.5490196078f}; + static constexpr std::array aquamarine = {0.4980392157f,1.0f,0.831372549f}; + static constexpr std::array aquamarine1 = aquamarine; + static constexpr std::array aquamarine2 = {0.462745098f,0.9333333333f,0.7764705882f}; + static constexpr std::array aquamarine3 = {0.4f,0.8039215686f,0.6666666667f}; + static constexpr std::array mediumaquamarine = aquamarine3; + static constexpr std::array aquamarine4 = {0.2705882353f,0.5450980392f,0.4549019608f}; + static constexpr std::array mediumspringgreen = {0.0f,0.9803921569f,0.6039215686f}; + static constexpr std::array mintcream = {0.9607843137f,1.0f,0.9803921569f}; + static constexpr std::array springgreen = {0.0f,1.0f,0.4980392157f}; + static constexpr std::array springgreen1 = {0.0f,0.9333333333f,0.462745098f}; + static constexpr std::array springgreen2 = {0.0f,0.8039215686f,0.4f}; + static constexpr std::array springgreen3 = {0.0f,0.5450980392f,0.2705882353f}; + static constexpr std::array mediumseagreen = {0.2352941176f,0.7019607843f,0.4431372549f}; + static constexpr std::array seagreen1 = {0.3294117647f,1.0f,0.6235294118f}; + static constexpr std::array seagreen2 = {0.3058823529f,0.9333333333f,0.5803921569f}; + static constexpr std::array seagreen3 = {0.262745098f,0.8039215686f,0.5019607843f}; + static constexpr std::array seagreen = {0.1803921569f,0.5450980392f,0.3411764706f}; + static constexpr std::array seagreen4 = seagreen; + static constexpr std::array emeraldgreen = {0.0f,0.7882352941f,0.3411764706f}; + static constexpr std::array mint = {0.7411764706f,0.9882352941f,0.7882352941f}; + static constexpr std::array cobaltgreen = {0.2392156863f,0.568627451f,0.2509803922f}; + static constexpr std::array honeydew = {0.9411764706f,1.0f,0.9411764706f}; + static constexpr std::array honeydew1 = honeydew; + static constexpr std::array honeydew2 = {0.8784313725f,0.9333333333f,0.8784313725f}; + static constexpr std::array honeydew3 = {0.7568627451f,0.8039215686f,0.7568627451f}; + static constexpr std::array honeydew4 = {0.5137254902f,0.5450980392f,0.5137254902f}; + static constexpr std::array darkseagreen = {0.5607843137f,0.737254902f,0.5607843137f}; + static constexpr std::array darkseagreen1 = {0.7568627451f,1.0f,0.7568627451f}; + static constexpr std::array darkseagreen2 = {0.7058823529f,0.9333333333f,0.7058823529f}; + static constexpr std::array darkseagreen3 = {0.6078431373f,0.8039215686f,0.6078431373f}; + static constexpr std::array darkseagreen4 = {0.4117647059f,0.5450980392f,0.4117647059f}; + static constexpr std::array palegreen = {0.5960784314f,0.9843137255f,0.5960784314f}; + static constexpr std::array palegreen1 = {0.6039215686f,1.0f,0.6039215686f}; + static constexpr std::array lightgreen = {0.5647058824f,0.9333333333f,0.5647058824f}; + static constexpr std::array palegreen2 = lightgreen; + static constexpr std::array palegreen3 = {0.4862745098f,0.8039215686f,0.4862745098f}; + static constexpr std::array palegreen4 = {0.3294117647f,0.5450980392f,0.3294117647f}; + static constexpr std::array limegreen = {0.1960784314f,0.8039215686f,0.1960784314f}; + static constexpr std::array forestgreen = {0.1333333333f,0.5450980392f,0.1333333333f}; + static constexpr std::array lime = {0.0f,1.0f,0.0f}; + static constexpr std::array green1 = lime; + static constexpr std::array green2 = {0.0f,0.9333333333f,0.0f}; + static constexpr std::array green3 = {0.0f,0.8039215686f,0.0f}; + static constexpr std::array green4 = {0.0f,0.5450980392f,0.0f}; + static constexpr std::array green = {0.0f,0.5019607843f,0.0f}; + static constexpr std::array darkgreen = {0.0f,0.3921568627f,0.0f}; + static constexpr std::array sapgreen = {0.1882352941f,0.5019607843f,0.0784313725f}; + static constexpr std::array lawngreen = {0.4862745098f,0.9882352941f,0.0f}; + static constexpr std::array chartreuse = {0.4980392157f,1.0f,0.0f}; + static constexpr std::array chartreuse1 = chartreuse; + static constexpr std::array chartreuse2 = {0.462745098f,0.9333333333f,0.0f}; + static constexpr std::array chartreuse3 = {0.4f,0.8039215686f,0.0f}; + static constexpr std::array chartreuse4 = {0.2705882353f,0.5450980392f,0.0f}; + static constexpr std::array greenyellow = {0.6784313725f,1.0f,0.1843137255f}; + static constexpr std::array darkolivegreen1 = {0.7921568627f,1.0f,0.4392156863f}; + static constexpr std::array darkolivegreen2 = {0.737254902f,0.9333333333f,0.4078431373f}; + static constexpr std::array darkolivegreen3 = {0.6352941176f,0.8039215686f,0.3529411765f}; + static constexpr std::array darkolivegreen4 = {0.431372549f,0.5450980392f,0.2392156863f}; + static constexpr std::array darkolivegreen = {0.3333333333f,0.4196078431f,0.1843137255f}; + static constexpr std::array olivedrab = {0.4196078431f,0.5568627451f,0.137254902f}; + static constexpr std::array olivedrab1 = {0.7529411765f,1.0f,0.2431372549f}; + static constexpr std::array olivedrab2 = {0.7019607843f,0.9333333333f,0.2274509804f}; + static constexpr std::array olivedrab3 = {0.6039215686f,0.8039215686f,0.1960784314f}; + static constexpr std::array yellowgreen = olivedrab3; + static constexpr std::array olivedrab4 = {0.4117647059f,0.5450980392f,0.1333333333f}; + static constexpr std::array ivory = {1.0f,1.0f,0.9411764706f}; + static constexpr std::array ivory1 = ivory; + static constexpr std::array ivory2 = {0.9333333333f,0.9333333333f,0.8784313725f}; + static constexpr std::array ivory3 = {0.8039215686f,0.8039215686f,0.7568627451f}; + static constexpr std::array ivory4 = {0.5450980392f,0.5450980392f,0.5137254902f}; + static constexpr std::array beige = {0.9607843137f,0.9607843137f,0.862745098f}; + static constexpr std::array lightyellow = {1.0f,1.0f,0.8784313725f}; + static constexpr std::array lightyellow1 = lightyellow; + static constexpr std::array lightyellow2 = {0.9333333333f,0.9333333333f,0.8196078431f}; + static constexpr std::array lightyellow3 = {0.8039215686f,0.8039215686f,0.7058823529f}; + static constexpr std::array lightyellow4 = {0.5450980392f,0.5450980392f,0.4784313725f}; + static constexpr std::array lightgoldenrodyellow = {0.9803921569f,0.9803921569f,0.8235294118f}; + static constexpr std::array yellow = {1.0f,1.0f,0.0f}; + static constexpr std::array yellow1 = yellow; + static constexpr std::array yellow2 = {0.9333333333f,0.9333333333f,0.0f}; + static constexpr std::array yellow3 = {0.8039215686f,0.8039215686f,0.0f}; + static constexpr std::array yellow4 = {0.5450980392f,0.5450980392f,0.0f}; + static constexpr std::array warmgrey = {0.5019607843f,0.5019607843f,0.4117647059f}; + static constexpr std::array olive = {0.5019607843f,0.5019607843f,0.0f}; + static constexpr std::array darkkhaki = {0.7411764706f,0.7176470588f,0.4196078431f}; + static constexpr std::array khaki1 = {1.0f,0.9647058824f,0.5607843137f}; + static constexpr std::array khaki2 = {0.9333333333f,0.9019607843f,0.5215686275f}; + static constexpr std::array khaki3 = {0.8039215686f,0.7764705882f,0.4509803922f}; + static constexpr std::array khaki4 = {0.5450980392f,0.5254901961f,0.3058823529f}; + static constexpr std::array khaki = {0.9411764706f,0.9019607843f,0.5490196078f}; + static constexpr std::array palegoldenrod = {0.9333333333f,0.9098039216f,0.6666666667f}; + static constexpr std::array lemonchiffon = {1.0f,0.9803921569f,0.8039215686f}; + static constexpr std::array lemonchiffon1 = lemonchiffon; + static constexpr std::array lemonchiffon2 = {0.9333333333f,0.9137254902f,0.7490196078f}; + static constexpr std::array lemonchiffon3 = {0.8039215686f,0.7882352941f,0.6470588235f}; + static constexpr std::array lemonchiffon4 = {0.5450980392f,0.537254902f,0.4392156863f}; + static constexpr std::array lightgoldenrod1 = {1.0f,0.9254901961f,0.5450980392f}; + static constexpr std::array lightgoldenrod2 = {0.9333333333f,0.862745098f,0.5098039216f}; + static constexpr std::array lightgoldenrod3 = {0.8039215686f,0.7450980392f,0.4392156863f}; + static constexpr std::array lightgoldenrod4 = {0.5450980392f,0.5058823529f,0.2980392157f}; + static constexpr std::array banana = {0.8901960784f,0.8117647059f,0.3411764706f}; + static constexpr std::array gold = {1.0f,0.8431372549f,0.0f}; + static constexpr std::array gold1 = gold; + static constexpr std::array gold2 = {0.9333333333f,0.7882352941f,0.0f}; + static constexpr std::array gold3 = {0.8039215686f,0.6784313725f,0.0f}; + static constexpr std::array gold4 = {0.5450980392f,0.4588235294f,0.0f}; + static constexpr std::array cornsilk = {1.0f,0.9725490196f,0.862745098f}; + static constexpr std::array cornsilk1 = cornsilk; + static constexpr std::array cornsilk2 = {0.9333333333f,0.9098039216f,0.8039215686f}; + static constexpr std::array cornsilk3 = {0.8039215686f,0.7843137255f,0.6941176471f}; + static constexpr std::array cornsilk4 = {0.5450980392f,0.5333333333f,0.4705882353f}; + static constexpr std::array goldenrod = {0.8549019608f,0.6470588235f,0.1254901961f}; + static constexpr std::array goldenrod1 = {1.0f,0.7568627451f,0.1450980392f}; + static constexpr std::array goldenrod2 = {0.9333333333f,0.7058823529f,0.1333333333f}; + static constexpr std::array goldenrod3 = {0.8039215686f,0.6078431373f,0.1137254902f}; + static constexpr std::array goldenrod4 = {0.5450980392f,0.4117647059f,0.0784313725f}; + static constexpr std::array darkgoldenrod = {0.7215686275f,0.5254901961f,0.0431372549f}; + static constexpr std::array darkgoldenrod1 = {1.0f,0.7254901961f,0.0588235294f}; + static constexpr std::array darkgoldenrod2 = {0.9333333333f,0.6784313725f,0.0549019608f}; + static constexpr std::array darkgoldenrod3 = {0.8039215686f,0.5843137255f,0.0470588235f}; + static constexpr std::array darkgoldenrod4 = {0.5450980392f,0.3960784314f,0.031372549f}; + static constexpr std::array orange = {1.0f,0.5019607843f,0.0f}; + static constexpr std::array orange1 = {1.0f,0.6470588235f,0.0f}; + static constexpr std::array orange2 = {0.9333333333f,0.6039215686f,0.0f}; + static constexpr std::array orange3 = {0.8039215686f,0.5215686275f,0.0f}; + static constexpr std::array orange4 = {0.5450980392f,0.3529411765f,0.0f}; + static constexpr std::array floralwhite = {1.0f,0.9803921569f,0.9411764706f}; + static constexpr std::array oldlace = {0.9921568627f,0.9607843137f,0.9019607843f}; + static constexpr std::array wheat = {0.9607843137f,0.8705882353f,0.7019607843f}; + static constexpr std::array wheat1 = {1.0f,0.9058823529f,0.7294117647f}; + static constexpr std::array wheat2 = {0.9333333333f,0.8470588235f,0.6823529412f}; + static constexpr std::array wheat3 = {0.8039215686f,0.7294117647f,0.5882352941f}; + static constexpr std::array wheat4 = {0.5450980392f,0.4941176471f,0.4f}; + static constexpr std::array moccasin = {1.0f,0.8941176471f,0.7098039216f}; + static constexpr std::array papayawhip = {1.0f,0.937254902f,0.8352941176f}; + static constexpr std::array blanchedalmond = {1.0f,0.9215686275f,0.8039215686f}; + static constexpr std::array navajowhite = {1.0f,0.8705882353f,0.6784313725f}; + static constexpr std::array navajowhite1 = navajowhite; + static constexpr std::array navajowhite2 = {0.9333333333f,0.8117647059f,0.631372549f}; + static constexpr std::array navajowhite3 = {0.8039215686f,0.7019607843f,0.5450980392f}; + static constexpr std::array navajowhite4 = {0.5450980392f,0.4745098039f,0.368627451f}; + static constexpr std::array eggshell = {0.9882352941f,0.9019607843f,0.7882352941f}; + static constexpr std::array brick = {0.6117647059f,0.4f,0.1215686275f}; + static constexpr std::array cadmiumyellow = {1.0f,0.6f,0.0705882353f}; + static constexpr std::array antiquewhite = {0.9803921569f,0.9215686275f,0.8431372549f}; + static constexpr std::array antiquewhite1 = {1.0f,0.937254902f,0.8588235294f}; + static constexpr std::array antiquewhite2 = {0.9333333333f,0.8745098039f,0.8f}; + static constexpr std::array antiquewhite3 = {0.8039215686f,0.7529411765f,0.6901960784f}; + static constexpr std::array antiquewhite4 = {0.5450980392f,0.5137254902f,0.4705882353f}; + static constexpr std::array burlywood = {0.8705882353f,0.7215686275f,0.5294117647f}; + static constexpr std::array burlywood1 = {1.0f,0.8274509804f,0.6078431373f}; + static constexpr std::array burlywood2 = {0.9333333333f,0.7725490196f,0.568627451f}; + static constexpr std::array burlywood3 = {0.8039215686f,0.6666666667f,0.4901960784f}; + static constexpr std::array burlywood4 = {0.5450980392f,0.4509803922f,0.3333333333f}; + static constexpr std::array bisque = {1.0f,0.8941176471f,0.768627451f}; + static constexpr std::array bisque1 = bisque; + static constexpr std::array bisque2 = {0.9333333333f,0.8352941176f,0.7176470588f}; + static constexpr std::array bisque3 = {0.8039215686f,0.7176470588f,0.6196078431f}; + static constexpr std::array bisque4 = {0.5450980392f,0.4901960784f,0.4196078431f}; + static constexpr std::array melon = {0.8901960784f,0.6588235294f,0.4117647059f}; + static constexpr std::array carrot = {0.9294117647f,0.568627451f,0.1294117647f}; + static constexpr std::array darkorange = {1.0f,0.5490196078f,0.0f}; + static constexpr std::array darkorange1 = {1.0f,0.4980392157f,0.0f}; + static constexpr std::array darkorange2 = {0.9333333333f,0.462745098f,0.0f}; + static constexpr std::array darkorange3 = {0.8039215686f,0.4f,0.0f}; + static constexpr std::array darkorange4 = {0.5450980392f,0.2705882353f,0.0f}; + static constexpr std::array tan = {0.8235294118f,0.7058823529f,0.5490196078f}; + static constexpr std::array tan1 = {1.0f,0.6470588235f,0.3098039216f}; + static constexpr std::array tan2 = {0.9333333333f,0.6039215686f,0.2862745098f}; + static constexpr std::array tan3 = {0.8039215686f,0.5215686275f,0.2470588235f}; + static constexpr std::array peru = tan3; + static constexpr std::array tan4 = {0.5450980392f,0.3529411765f,0.168627451f}; + static constexpr std::array linen = {0.9803921569f,0.9411764706f,0.9019607843f}; + static constexpr std::array peachpuff = {1.0f,0.8549019608f,0.7254901961f}; + static constexpr std::array peachpuff1 = peachpuff; + static constexpr std::array peachpuff2 = {0.9333333333f,0.7960784314f,0.6784313725f}; + static constexpr std::array peachpuff3 = {0.8039215686f,0.6862745098f,0.5843137255f}; + static constexpr std::array peachpuff4 = {0.5450980392f,0.4666666667f,0.3960784314f}; + static constexpr std::array seashell = {1.0f,0.9607843137f,0.9333333333f}; + static constexpr std::array seashell1 = seashell; + static constexpr std::array seashell2 = {0.9333333333f,0.8980392157f,0.8705882353f}; + static constexpr std::array seashell3 = {0.8039215686f,0.7725490196f,0.7490196078f}; + static constexpr std::array seashell4 = {0.5450980392f,0.5254901961f,0.5098039216f}; + static constexpr std::array sandybrown = {0.9568627451f,0.6431372549f,0.3764705882f}; + static constexpr std::array rawsienna = {0.7803921569f,0.3803921569f,0.0784313725f}; + static constexpr std::array chocolate = {0.8235294118f,0.4117647059f,0.1176470588f}; + static constexpr std::array chocolate1 = {1.0f,0.4980392157f,0.1411764706f}; + static constexpr std::array chocolate2 = {0.9333333333f,0.462745098f,0.1294117647f}; + static constexpr std::array chocolate3 = {0.8039215686f,0.4f,0.1137254902f}; + static constexpr std::array chocolate4 = {0.5450980392f,0.2705882353f,0.0745098039f}; + static constexpr std::array saddlebrown = chocolate4; + static constexpr std::array ivoryblack = {0.1607843137f,0.1411764706f,0.1294117647f}; + static constexpr std::array flesh = {1.0f,0.4901960784f,0.2509803922f}; + static constexpr std::array cadmiumorange = {1.0f,0.3803921569f,0.0117647059f}; + static constexpr std::array burntsienna = {0.5411764706f,0.2117647059f,0.0588235294f}; + static constexpr std::array sienna = {0.6274509804f,0.3215686275f,0.1764705882f}; + static constexpr std::array sienna1 = {1.0f,0.5098039216f,0.2784313725f}; + static constexpr std::array sienna2 = {0.9333333333f,0.4745098039f,0.2588235294f}; + static constexpr std::array sienna3 = {0.8039215686f,0.4078431373f,0.2235294118f}; + static constexpr std::array sienna4 = {0.5450980392f,0.2784313725f,0.1490196078f}; + static constexpr std::array lightsalmon = {1.0f,0.6274509804f,0.4784313725f}; + static constexpr std::array lightsalmon1 = lightsalmon; + static constexpr std::array lightsalmon2 = {0.9333333333f,0.5843137255f,0.4470588235f}; + static constexpr std::array lightsalmon3 = {0.8039215686f,0.5058823529f,0.3843137255f}; + static constexpr std::array lightsalmon4 = {0.5450980392f,0.3411764706f,0.2588235294f}; + static constexpr std::array coral = {1.0f,0.4980392157f,0.3137254902f}; + static constexpr std::array orangered = {1.0f,0.2705882353f,0.0f}; + static constexpr std::array orangered1 = orangered; + static constexpr std::array orangered2 = {0.9333333333f,0.2509803922f,0.0f}; + static constexpr std::array orangered3 = {0.8039215686f,0.2156862745f,0.0f}; + static constexpr std::array orangered4 = {0.5450980392f,0.1450980392f,0.0f}; + static constexpr std::array sepia = {0.368627451f,0.1490196078f,0.0705882353f}; + static constexpr std::array darksalmon = {0.9137254902f,0.5882352941f,0.4784313725f}; + static constexpr std::array salmon1 = {1.0f,0.5490196078f,0.4117647059f}; + static constexpr std::array salmon2 = {0.9333333333f,0.5098039216f,0.3843137255f}; + static constexpr std::array salmon3 = {0.8039215686f,0.4392156863f,0.3294117647f}; + static constexpr std::array salmon4 = {0.5450980392f,0.2980392157f,0.2235294118f}; + static constexpr std::array coral1 = {1.0f,0.4470588235f,0.337254902f}; + static constexpr std::array coral2 = {0.9333333333f,0.4156862745f,0.3137254902f}; + static constexpr std::array coral3 = {0.8039215686f,0.3568627451f,0.2705882353f}; + static constexpr std::array coral4 = {0.5450980392f,0.2431372549f,0.1843137255f}; + static constexpr std::array burntumber = {0.5411764706f,0.2f,0.1411764706f}; + static constexpr std::array tomato = {1.0f,0.3882352941f,0.2784313725f}; + static constexpr std::array tomato1 = tomato; + static constexpr std::array tomato2 = {0.9333333333f,0.3607843137f,0.2588235294f}; + static constexpr std::array tomato3 = {0.8039215686f,0.3098039216f,0.2235294118f}; + static constexpr std::array tomato4 = {0.5450980392f,0.2117647059f,0.1490196078f}; + static constexpr std::array salmon = {0.9803921569f,0.5019607843f,0.4470588235f}; + static constexpr std::array mistyrose = {1.0f,0.8941176471f,0.8823529412f}; + static constexpr std::array mistyrose1 = mistyrose; + static constexpr std::array mistyrose2 = {0.9333333333f,0.8352941176f,0.8235294118f}; + static constexpr std::array mistyrose3 = {0.8039215686f,0.7176470588f,0.7098039216f}; + static constexpr std::array mistyrose4 = {0.5450980392f,0.4901960784f,0.4823529412f}; + static constexpr std::array snow = {1.0f,0.9803921569f,0.9803921569f}; + static constexpr std::array snow1 = snow; + static constexpr std::array snow2 = {0.9333333333f,0.9137254902f,0.9137254902f}; + static constexpr std::array snow3 = {0.8039215686f,0.7882352941f,0.7882352941f}; + static constexpr std::array snow4 = {0.5450980392f,0.537254902f,0.537254902f}; + static constexpr std::array rosybrown = {0.737254902f,0.5607843137f,0.5607843137f}; + static constexpr std::array rosybrown1 = {1.0f,0.7568627451f,0.7568627451f}; + static constexpr std::array rosybrown2 = {0.9333333333f,0.7058823529f,0.7058823529f}; + static constexpr std::array rosybrown3 = {0.8039215686f,0.6078431373f,0.6078431373f}; + static constexpr std::array rosybrown4 = {0.5450980392f,0.4117647059f,0.4117647059f}; + static constexpr std::array lightcoral = {0.9411764706f,0.5019607843f,0.5019607843f}; + static constexpr std::array indianred = {0.8039215686f,0.3607843137f,0.3607843137f}; + static constexpr std::array indianred1 = {1.0f,0.4156862745f,0.4156862745f}; + static constexpr std::array indianred2 = {0.9333333333f,0.3882352941f,0.3882352941f}; + static constexpr std::array indianred4 = {0.5450980392f,0.2274509804f,0.2274509804f}; + static constexpr std::array indianred3 = {0.8039215686f,0.3333333333f,0.3333333333f}; + static constexpr std::array brown = {0.6470588235f,0.1647058824f,0.1647058824f}; + static constexpr std::array brown1 = {1.0f,0.2509803922f,0.2509803922f}; + static constexpr std::array brown2 = {0.9333333333f,0.231372549f,0.231372549f}; + static constexpr std::array brown3 = {0.8039215686f,0.2f,0.2f}; + static constexpr std::array brown4 = {0.5450980392f,0.137254902f,0.137254902f}; + static constexpr std::array firebrick = {0.6980392157f,0.1333333333f,0.1333333333f}; + static constexpr std::array firebrick1 = {1.0f,0.1882352941f,0.1882352941f}; + static constexpr std::array firebrick2 = {0.9333333333f,0.1725490196f,0.1725490196f}; + static constexpr std::array firebrick3 = {0.8039215686f,0.1490196078f,0.1490196078f}; + static constexpr std::array firebrick4 = {0.5450980392f,0.1019607843f,0.1019607843f}; + static constexpr std::array red = {1.0f,0.0f,0.0f}; + static constexpr std::array red1 = red; + static constexpr std::array red2 = {0.9333333333f,0.0f,0.0f}; + static constexpr std::array red3 = {0.8039215686f,0.0f,0.0f}; + static constexpr std::array red4 = {0.5450980392f,0.0f,0.0f}; + static constexpr std::array darkred = red4; + static constexpr std::array maroon = {0.5019607843f,0.0f,0.0f}; + static constexpr std::array sgi_beet = {0.5568627451f,0.2196078431f,0.5568627451f}; + static constexpr std::array sgi_slateblue = {0.4431372549f,0.4431372549f,0.7764705882f}; + static constexpr std::array sgi_lightblue = {0.4901960784f,0.6196078431f,0.7529411765f}; + static constexpr std::array sgi_teal = {0.2196078431f,0.5568627451f,0.5568627451f}; + static constexpr std::array sgi_chartreuse = {0.4431372549f,0.7764705882f,0.4431372549f}; + static constexpr std::array sgi_olivedrab = {0.5568627451f,0.5568627451f,0.2196078431f}; + static constexpr std::array sgi_brightgray = {0.7725490196f,0.7568627451f,0.6666666667f}; + static constexpr std::array sgi_salmon = {0.7764705882f,0.4431372549f,0.4431372549f}; + static constexpr std::array sgi_darkgray = {0.3333333333f,0.3333333333f,0.3333333333f}; + static constexpr std::array sgi_gray12 = {0.1176470588f,0.1176470588f,0.1176470588f}; + static constexpr std::array sgi_gray16 = {0.1568627451f,0.1568627451f,0.1568627451f}; + static constexpr std::array sgi_gray32 = {0.3176470588f,0.3176470588f,0.3176470588f}; + static constexpr std::array sgi_gray36 = {0.3568627451f,0.3568627451f,0.3568627451f}; + static constexpr std::array sgi_gray52 = {0.5176470588f,0.5176470588f,0.5176470588f}; + static constexpr std::array sgi_gray56 = {0.5568627451f,0.5568627451f,0.5568627451f}; + static constexpr std::array sgi_lightgray = {0.6666666667f,0.6666666667f,0.6666666667f}; + static constexpr std::array sgi_gray72 = {0.7176470588f,0.7176470588f,0.7176470588f}; + static constexpr std::array sgi_gray76 = {0.7568627451f,0.7568627451f,0.7568627451f}; + static constexpr std::array sgi_gray92 = {0.9176470588f,0.9176470588f,0.9176470588f}; + static constexpr std::array sgi_gray96 = {0.9568627451f,0.9568627451f,0.9568627451f}; + static constexpr std::array white = {1.0f,1.0f,1.0f}; + static constexpr std::array white_smoke = {0.9607843137f,0.9607843137f,0.9607843137f}; + static constexpr std::array gainsboro = {0.862745098f,0.862745098f,0.862745098f}; + static constexpr std::array lightgrey = {0.8274509804f,0.8274509804f,0.8274509804f}; + static constexpr std::array silver = {0.7529411765f,0.7529411765f,0.7529411765f}; + static constexpr std::array darkgray = {0.662745098f,0.662745098f,0.662745098f}; + static constexpr std::array gray = {0.5019607843f,0.5019607843f,0.5019607843f}; + static constexpr std::array dimgray = {0.4117647059f,0.4117647059f,0.4117647059f}; + static constexpr std::array black = {0.0f,0.0f,0.0f}; + static constexpr std::array gray99 = {0.9882352941f,0.9882352941f,0.9882352941f}; + static constexpr std::array gray98 = {0.9803921569f,0.9803921569f,0.9803921569f}; + static constexpr std::array gray97 = {0.968627451f,0.968627451f,0.968627451f}; + static constexpr std::array gray96 = {0.9607843137f,0.9607843137f,0.9607843137f}; + static constexpr std::array gray95 = {0.9490196078f,0.9490196078f,0.9490196078f}; + static constexpr std::array gray94 = {0.9411764706f,0.9411764706f,0.9411764706f}; + static constexpr std::array gray93 = {0.9294117647f,0.9294117647f,0.9294117647f}; + static constexpr std::array gray92 = {0.9215686275f,0.9215686275f,0.9215686275f}; + static constexpr std::array gray91 = {0.9098039216f,0.9098039216f,0.9098039216f}; + static constexpr std::array gray90 = {0.8980392157f,0.8980392157f,0.8980392157f}; + static constexpr std::array gray89 = {0.8901960784f,0.8901960784f,0.8901960784f}; + static constexpr std::array gray88 = {0.8784313725f,0.8784313725f,0.8784313725f}; + static constexpr std::array gray87 = {0.8705882353f,0.8705882353f,0.8705882353f}; + static constexpr std::array gray86 = {0.8588235294f,0.8588235294f,0.8588235294f}; + static constexpr std::array gray85 = {0.8509803922f,0.8509803922f,0.8509803922f}; + static constexpr std::array gray84 = {0.8392156863f,0.8392156863f,0.8392156863f}; + static constexpr std::array gray83 = {0.831372549f,0.831372549f,0.831372549f}; + static constexpr std::array gray82 = {0.8196078431f,0.8196078431f,0.8196078431f}; + static constexpr std::array gray81 = {0.8117647059f,0.8117647059f,0.8117647059f}; + static constexpr std::array gray80 = {0.8f,0.8f,0.8f}; + static constexpr std::array gray79 = {0.7882352941f,0.7882352941f,0.7882352941f}; + static constexpr std::array gray78 = {0.7803921569f,0.7803921569f,0.7803921569f}; + static constexpr std::array gray77 = {0.768627451f,0.768627451f,0.768627451f}; + static constexpr std::array gray76 = {0.7607843137f,0.7607843137f,0.7607843137f}; + static constexpr std::array gray75 = {0.7490196078f,0.7490196078f,0.7490196078f}; + static constexpr std::array gray74 = {0.7411764706f,0.7411764706f,0.7411764706f}; + static constexpr std::array gray73 = {0.7294117647f,0.7294117647f,0.7294117647f}; + static constexpr std::array gray72 = {0.7215686275f,0.7215686275f,0.7215686275f}; + static constexpr std::array gray71 = {0.7098039216f,0.7098039216f,0.7098039216f}; + static constexpr std::array gray70 = {0.7019607843f,0.7019607843f,0.7019607843f}; + static constexpr std::array gray69 = {0.6901960784f,0.6901960784f,0.6901960784f}; + static constexpr std::array gray68 = {0.6784313725f,0.6784313725f,0.6784313725f}; + static constexpr std::array gray67 = {0.6705882353f,0.6705882353f,0.6705882353f}; + static constexpr std::array gray66 = {0.6588235294f,0.6588235294f,0.6588235294f}; + static constexpr std::array gray65 = {0.6509803922f,0.6509803922f,0.6509803922f}; + static constexpr std::array gray64 = {0.6392156863f,0.6392156863f,0.6392156863f}; + static constexpr std::array gray63 = {0.631372549f,0.631372549f,0.631372549f}; + static constexpr std::array gray62 = {0.6196078431f,0.6196078431f,0.6196078431f}; + static constexpr std::array gray61 = {0.6117647059f,0.6117647059f,0.6117647059f}; + static constexpr std::array gray60 = {0.6f,0.6f,0.6f}; + static constexpr std::array gray59 = {0.5882352941f,0.5882352941f,0.5882352941f}; + static constexpr std::array gray58 = {0.5803921569f,0.5803921569f,0.5803921569f}; + static constexpr std::array gray57 = {0.568627451f,0.568627451f,0.568627451f}; + static constexpr std::array gray56 = {0.5607843137f,0.5607843137f,0.5607843137f}; + static constexpr std::array gray55 = {0.5490196078f,0.5490196078f,0.5490196078f}; + static constexpr std::array gray54 = {0.5411764706f,0.5411764706f,0.5411764706f}; + static constexpr std::array gray53 = {0.5294117647f,0.5294117647f,0.5294117647f}; + static constexpr std::array gray52 = {0.5215686275f,0.5215686275f,0.5215686275f}; + static constexpr std::array gray51 = {0.5098039216f,0.5098039216f,0.5098039216f}; + static constexpr std::array gray50 = {0.4980392157f,0.4980392157f,0.4980392157f}; + static constexpr std::array gray49 = {0.4901960784f,0.4901960784f,0.4901960784f}; + static constexpr std::array gray48 = {0.4784313725f,0.4784313725f,0.4784313725f}; + static constexpr std::array gray47 = {0.4705882353f,0.4705882353f,0.4705882353f}; + static constexpr std::array gray46 = {0.4588235294f,0.4588235294f,0.4588235294f}; + static constexpr std::array gray45 = {0.4509803922f,0.4509803922f,0.4509803922f}; + static constexpr std::array gray44 = {0.4392156863f,0.4392156863f,0.4392156863f}; + static constexpr std::array gray43 = {0.431372549f,0.431372549f,0.431372549f}; + static constexpr std::array gray42 = {0.4196078431f,0.4196078431f,0.4196078431f}; + static constexpr std::array gray41 = {0.4117647059f,0.4117647059f,0.4117647059f}; + static constexpr std::array gray40 = {0.4f,0.4f,0.4f}; + static constexpr std::array gray39 = {0.3882352941f,0.3882352941f,0.3882352941f}; + static constexpr std::array gray38 = {0.3803921569f,0.3803921569f,0.3803921569f}; + static constexpr std::array gray37 = {0.368627451f,0.368627451f,0.368627451f}; + static constexpr std::array gray36 = {0.3607843137f,0.3607843137f,0.3607843137f}; + static constexpr std::array gray35 = {0.3490196078f,0.3490196078f,0.3490196078f}; + static constexpr std::array gray34 = {0.3411764706f,0.3411764706f,0.3411764706f}; + static constexpr std::array gray33 = {0.3294117647f,0.3294117647f,0.3294117647f}; + static constexpr std::array gray32 = {0.3215686275f,0.3215686275f,0.3215686275f}; + static constexpr std::array gray31 = {0.3098039216f,0.3098039216f,0.3098039216f}; + static constexpr std::array gray30 = {0.3019607843f,0.3019607843f,0.3019607843f}; + static constexpr std::array gray29 = {0.2901960784f,0.2901960784f,0.2901960784f}; + static constexpr std::array gray28 = {0.2784313725f,0.2784313725f,0.2784313725f}; + static constexpr std::array gray27 = {0.2705882353f,0.2705882353f,0.2705882353f}; + static constexpr std::array gray26 = {0.2588235294f,0.2588235294f,0.2588235294f}; + static constexpr std::array gray25 = {0.2509803922f,0.2509803922f,0.2509803922f}; + static constexpr std::array gray24 = {0.2392156863f,0.2392156863f,0.2392156863f}; + static constexpr std::array gray23 = {0.231372549f,0.231372549f,0.231372549f}; + static constexpr std::array gray22 = {0.2196078431f,0.2196078431f,0.2196078431f}; + static constexpr std::array gray21 = {0.2117647059f,0.2117647059f,0.2117647059f}; + static constexpr std::array gray20 = {0.2f,0.2f,0.2f}; + static constexpr std::array gray19 = {0.1882352941f,0.1882352941f,0.1882352941f}; + static constexpr std::array gray18 = {0.1803921569f,0.1803921569f,0.1803921569f}; + static constexpr std::array gray17 = {0.168627451f,0.168627451f,0.168627451f}; + static constexpr std::array gray16 = {0.1607843137f,0.1607843137f,0.1607843137f}; + static constexpr std::array gray15 = {0.1490196078f,0.1490196078f,0.1490196078f}; + static constexpr std::array gray14 = {0.1411764706f,0.1411764706f,0.1411764706f}; + static constexpr std::array gray13 = {0.1294117647f,0.1294117647f,0.1294117647f}; + static constexpr std::array gray12 = {0.1215686275f,0.1215686275f,0.1215686275f}; + static constexpr std::array gray11 = {0.1098039216f,0.1098039216f,0.1098039216f}; + static constexpr std::array gray10 = {0.1019607843f,0.1019607843f,0.1019607843f}; + static constexpr std::array gray9 = {0.0901960784f,0.0901960784f,0.0901960784f}; + static constexpr std::array gray8 = {0.0784313725f,0.0784313725f,0.0784313725f}; + static constexpr std::array gray7 = {0.0705882353f,0.0705882353f,0.0705882353f}; + static constexpr std::array gray6 = {0.0588235294f,0.0588235294f,0.0588235294f}; + static constexpr std::array gray5 = {0.0509803922f,0.0509803922f,0.0509803922f}; + static constexpr std::array gray4 = {0.0392156863f,0.0392156863f,0.0392156863f}; + static constexpr std::array gray3 = {0.031372549f,0.031372549f,0.031372549f}; + static constexpr std::array gray2 = {0.0196078431f,0.0196078431f,0.0196078431f}; + static constexpr std::array gray1 = {0.0117647059f,0.0117647059f,0.0117647059f}; + static constexpr std::array grey99 = {0.9882352941f,0.9882352941f,0.9882352941f}; + static constexpr std::array grey98 = {0.9803921569f,0.9803921569f,0.9803921569f}; + static constexpr std::array grey97 = {0.968627451f,0.968627451f,0.968627451f}; + static constexpr std::array grey96 = {0.9607843137f,0.9607843137f,0.9607843137f}; + static constexpr std::array grey95 = {0.9490196078f,0.9490196078f,0.9490196078f}; + static constexpr std::array grey94 = {0.9411764706f,0.9411764706f,0.9411764706f}; + static constexpr std::array grey93 = {0.9294117647f,0.9294117647f,0.9294117647f}; + static constexpr std::array grey92 = {0.9215686275f,0.9215686275f,0.9215686275f}; + static constexpr std::array grey91 = {0.9098039216f,0.9098039216f,0.9098039216f}; + static constexpr std::array grey90 = {0.8980392157f,0.8980392157f,0.8980392157f}; + static constexpr std::array grey89 = {0.8901960784f,0.8901960784f,0.8901960784f}; + static constexpr std::array grey88 = {0.8784313725f,0.8784313725f,0.8784313725f}; + static constexpr std::array grey87 = {0.8705882353f,0.8705882353f,0.8705882353f}; + static constexpr std::array grey86 = {0.8588235294f,0.8588235294f,0.8588235294f}; + static constexpr std::array grey85 = {0.8509803922f,0.8509803922f,0.8509803922f}; + static constexpr std::array grey84 = {0.8392156863f,0.8392156863f,0.8392156863f}; + static constexpr std::array grey83 = {0.831372549f,0.831372549f,0.831372549f}; + static constexpr std::array grey82 = {0.8196078431f,0.8196078431f,0.8196078431f}; + static constexpr std::array grey81 = {0.8117647059f,0.8117647059f,0.8117647059f}; + static constexpr std::array grey80 = {0.8f,0.8f,0.8f}; + static constexpr std::array grey79 = {0.7882352941f,0.7882352941f,0.7882352941f}; + static constexpr std::array grey78 = {0.7803921569f,0.7803921569f,0.7803921569f}; + static constexpr std::array grey77 = {0.768627451f,0.768627451f,0.768627451f}; + static constexpr std::array grey76 = {0.7607843137f,0.7607843137f,0.7607843137f}; + static constexpr std::array grey75 = {0.7490196078f,0.7490196078f,0.7490196078f}; + static constexpr std::array grey74 = {0.7411764706f,0.7411764706f,0.7411764706f}; + static constexpr std::array grey73 = {0.7294117647f,0.7294117647f,0.7294117647f}; + static constexpr std::array grey72 = {0.7215686275f,0.7215686275f,0.7215686275f}; + static constexpr std::array grey71 = {0.7098039216f,0.7098039216f,0.7098039216f}; + static constexpr std::array grey70 = {0.7019607843f,0.7019607843f,0.7019607843f}; + static constexpr std::array grey69 = {0.6901960784f,0.6901960784f,0.6901960784f}; + static constexpr std::array grey68 = {0.6784313725f,0.6784313725f,0.6784313725f}; + static constexpr std::array grey67 = {0.6705882353f,0.6705882353f,0.6705882353f}; + static constexpr std::array grey66 = {0.6588235294f,0.6588235294f,0.6588235294f}; + static constexpr std::array grey65 = {0.6509803922f,0.6509803922f,0.6509803922f}; + static constexpr std::array grey64 = {0.6392156863f,0.6392156863f,0.6392156863f}; + static constexpr std::array grey63 = {0.631372549f,0.631372549f,0.631372549f}; + static constexpr std::array grey62 = {0.6196078431f,0.6196078431f,0.6196078431f}; + static constexpr std::array grey61 = {0.6117647059f,0.6117647059f,0.6117647059f}; + static constexpr std::array grey60 = {0.6f,0.6f,0.6f}; + static constexpr std::array grey59 = {0.5882352941f,0.5882352941f,0.5882352941f}; + static constexpr std::array grey58 = {0.5803921569f,0.5803921569f,0.5803921569f}; + static constexpr std::array grey57 = {0.568627451f,0.568627451f,0.568627451f}; + static constexpr std::array grey56 = {0.5607843137f,0.5607843137f,0.5607843137f}; + static constexpr std::array grey55 = {0.5490196078f,0.5490196078f,0.5490196078f}; + static constexpr std::array grey54 = {0.5411764706f,0.5411764706f,0.5411764706f}; + static constexpr std::array grey53 = {0.5294117647f,0.5294117647f,0.5294117647f}; + static constexpr std::array grey52 = {0.5215686275f,0.5215686275f,0.5215686275f}; + static constexpr std::array grey51 = {0.5098039216f,0.5098039216f,0.5098039216f}; + static constexpr std::array grey50 = {0.4980392157f,0.4980392157f,0.4980392157f}; + static constexpr std::array grey49 = {0.4901960784f,0.4901960784f,0.4901960784f}; + static constexpr std::array grey48 = {0.4784313725f,0.4784313725f,0.4784313725f}; + static constexpr std::array grey47 = {0.4705882353f,0.4705882353f,0.4705882353f}; + static constexpr std::array grey46 = {0.4588235294f,0.4588235294f,0.4588235294f}; + static constexpr std::array grey45 = {0.4509803922f,0.4509803922f,0.4509803922f}; + static constexpr std::array grey44 = {0.4392156863f,0.4392156863f,0.4392156863f}; + static constexpr std::array grey43 = {0.431372549f,0.431372549f,0.431372549f}; + static constexpr std::array grey42 = {0.4196078431f,0.4196078431f,0.4196078431f}; + static constexpr std::array grey41 = {0.4117647059f,0.4117647059f,0.4117647059f}; + static constexpr std::array grey40 = {0.4f,0.4f,0.4f}; + static constexpr std::array grey39 = {0.3882352941f,0.3882352941f,0.3882352941f}; + static constexpr std::array grey38 = {0.3803921569f,0.3803921569f,0.3803921569f}; + static constexpr std::array grey37 = {0.368627451f,0.368627451f,0.368627451f}; + static constexpr std::array grey36 = {0.3607843137f,0.3607843137f,0.3607843137f}; + static constexpr std::array grey35 = {0.3490196078f,0.3490196078f,0.3490196078f}; + static constexpr std::array grey34 = {0.3411764706f,0.3411764706f,0.3411764706f}; + static constexpr std::array grey33 = {0.3294117647f,0.3294117647f,0.3294117647f}; + static constexpr std::array grey32 = {0.3215686275f,0.3215686275f,0.3215686275f}; + static constexpr std::array grey31 = {0.3098039216f,0.3098039216f,0.3098039216f}; + static constexpr std::array grey30 = {0.3019607843f,0.3019607843f,0.3019607843f}; + static constexpr std::array grey29 = {0.2901960784f,0.2901960784f,0.2901960784f}; + static constexpr std::array grey28 = {0.2784313725f,0.2784313725f,0.2784313725f}; + static constexpr std::array grey27 = {0.2705882353f,0.2705882353f,0.2705882353f}; + static constexpr std::array grey26 = {0.2588235294f,0.2588235294f,0.2588235294f}; + static constexpr std::array grey25 = {0.2509803922f,0.2509803922f,0.2509803922f}; + static constexpr std::array grey24 = {0.2392156863f,0.2392156863f,0.2392156863f}; + static constexpr std::array grey23 = {0.231372549f,0.231372549f,0.231372549f}; + static constexpr std::array grey22 = {0.2196078431f,0.2196078431f,0.2196078431f}; + static constexpr std::array grey21 = {0.2117647059f,0.2117647059f,0.2117647059f}; + static constexpr std::array grey20 = {0.2f,0.2f,0.2f}; + static constexpr std::array grey19 = {0.1882352941f,0.1882352941f,0.1882352941f}; + static constexpr std::array grey18 = {0.1803921569f,0.1803921569f,0.1803921569f}; + static constexpr std::array grey17 = {0.168627451f,0.168627451f,0.168627451f}; + static constexpr std::array grey16 = {0.1607843137f,0.1607843137f,0.1607843137f}; + static constexpr std::array grey15 = {0.1490196078f,0.1490196078f,0.1490196078f}; + static constexpr std::array grey14 = {0.1411764706f,0.1411764706f,0.1411764706f}; + static constexpr std::array grey13 = {0.1294117647f,0.1294117647f,0.1294117647f}; + static constexpr std::array grey12 = {0.1215686275f,0.1215686275f,0.1215686275f}; + static constexpr std::array grey11 = {0.1098039216f,0.1098039216f,0.1098039216f}; + static constexpr std::array grey10 = {0.1019607843f,0.1019607843f,0.1019607843f}; + static constexpr std::array grey9 = {0.0901960784f,0.0901960784f,0.0901960784f}; + static constexpr std::array grey8 = {0.0784313725f,0.0784313725f,0.0784313725f}; + static constexpr std::array grey7 = {0.0705882353f,0.0705882353f,0.0705882353f}; + static constexpr std::array grey6 = {0.0588235294f,0.0588235294f,0.0588235294f}; + static constexpr std::array grey5 = {0.0509803922f,0.0509803922f,0.0509803922f}; + static constexpr std::array grey4 = {0.0392156863f,0.0392156863f,0.0392156863f}; + static constexpr std::array grey3 = {0.031372549f,0.031372549f,0.031372549f}; + static constexpr std::array grey2 = {0.0196078431f,0.0196078431f,0.0196078431f}; + static constexpr std::array grey1 = {0.0117647059f,0.0117647059f,0.0117647059f}; +} diff --git a/mplot/colourmaps_cet.h b/mplot/colourmaps_cet.h index e21a0491..09524efc 100644 --- a/mplot/colourmaps_cet.h +++ b/mplot/colourmaps_cet.h @@ -5,9 +5,8 @@ #include -namespace mplot { - namespace cet { - +namespace mplot::cet +{ constexpr std::array, 256> cm_CET_C4s = {{ { 0.1020000f, 0.3900000f, 0.8970000f }, { 0.1120000f, 0.3920000f, 0.8970000f }, @@ -15288,5 +15287,5 @@ namespace mplot { { 0.8490000f, 0.0310000f, 0.0520000f }, { 0.8420000f, 0.0200000f, 0.0520000f } }}; // cm_CET_R4 - } // namespace cet -} // namespace mplot + +} // namespace mplot::cet diff --git a/mplot/colourmaps_crameri.h b/mplot/colourmaps_crameri.h index f3d8567e..24b74c04 100644 --- a/mplot/colourmaps_crameri.h +++ b/mplot/colourmaps_crameri.h @@ -5,9 +5,8 @@ #include -namespace mplot { - namespace crameri { - +namespace mplot::crameri +{ constexpr std::array, 256> cm_lipari = {{ { 0.0113700f, 0.0732400f, 0.1482840f }, { 0.0139650f, 0.0790620f, 0.1553700f }, @@ -10367,5 +10366,4 @@ namespace mplot { { 0.9929940f, 0.9929850f, 0.9929450f }, { 1.0000000f, 1.0000000f, 1.0000000f } }}; // cm_bilbao - } // namespace crameri -} // namespace mplot +} // namespace mplot::crameri diff --git a/mplot/compoundray/EyeVisual.h b/mplot/compoundray/EyeVisual.h index c7dfdddd..4d3b5f96 100644 --- a/mplot/compoundray/EyeVisual.h +++ b/mplot/compoundray/EyeVisual.h @@ -535,4 +535,4 @@ namespace mplot::compoundray } }; -} // namespace comray +} // namespace mplot::compoundray diff --git a/mplot/compoundray/Visual.h b/mplot/compoundray/Visual.h index 5837234c..662eef2f 100644 --- a/mplot/compoundray/Visual.h +++ b/mplot/compoundray/Visual.h @@ -11,8 +11,8 @@ #include #include -namespace mplot::compoundray { - +namespace mplot::compoundray +{ template struct Visual : public mplot::Visual { diff --git a/mplot/gl/compute_manager.h b/mplot/gl/compute_manager.h index 4eff470a..8e70f66e 100644 --- a/mplot/gl/compute_manager.h +++ b/mplot/gl/compute_manager.h @@ -29,344 +29,341 @@ #include #include -namespace mplot { - namespace gl { - - using namespace std::chrono; - using sc = std::chrono::steady_clock; - - // A default shader which won't compile (better than having an empty no-op default shader) - const char* defaultComputeShader = "This is an intentionally non-compiling non-shader\n"; +namespace mplot::gl +{ + using namespace std::chrono; + using sc = std::chrono::steady_clock; + + // A default shader which won't compile (better than having an empty no-op default shader) + const char* defaultComputeShader = "This is an intentionally non-compiling non-shader\n"; + + // You may wish to pass a compiled-in shader that will fail, so that your system MUST find the + // file-based shader in mplot::gl::LoadShaders. + const char* nonCompilingComputeShader = "This is an intentionally non-compiling non-shader\n"; + + /*! + * A gl compute environment. I think user will extend this class to add their data structures + * and then run with their own GLSL compute shader code. + */ + template + struct compute_manager + { + compute_manager() { this->t0 = sc::now(); } + ~compute_manager() + { + glfwDestroyWindow (this->window); + } + + //! Init GLFW and then the GLFW window. What if you want to set window width + //! based on GLFW info such as this->workarea_width? In that case, instead + //! of calling this do-it-all init function, just call the init functions separately: + //! init_glfw(); do_stuff(); init_window(); init_gl(); + void init() + { + // Init GLFW first + this->init_glfw(); + // Now init a window/context for compute + this->init_window(); + // Finally init GL + this->init_gl(); + } + + void setContext() + { + glfwMakeContextCurrent (this->window); + glfwSwapInterval (0); + } + void releaseContext() { glfwMakeContextCurrent (nullptr); } - // You may wish to pass a compiled-in shader that will fail, so that your system MUST find the - // file-based shader in mplot::gl::LoadShaders. - const char* nonCompilingComputeShader = "This is an intentionally non-compiling non-shader\n"; + // You will need to re-implement this function + virtual void compute() = 0; - /*! - * A gl compute environment. I think user will extend this class to add their data structures - * and then run with their own GLSL compute shader code. - */ - template - struct compute_manager + void keepOpen() { - compute_manager() { this->t0 = sc::now(); } - ~compute_manager() - { - glfwDestroyWindow (this->window); + while (this->readyToFinish == false) { + glfwWaitEventsTimeout (0.01667); // 16.67 ms ~ 60 Hz + this->render(); } + } - //! Init GLFW and then the GLFW window. What if you want to set window width - //! based on GLFW info such as this->workarea_width? In that case, instead - //! of calling this do-it-all init function, just call the init functions separately: - //! init_glfw(); do_stuff(); init_window(); init_gl(); - void init() - { - // Init GLFW first - this->init_glfw(); - // Now init a window/context for compute - this->init_window(); - // Finally init GL - this->init_gl(); - } + //! You may wish to render the result of your compute. This method can be overridden. + virtual void render() + { + glfwSwapBuffers (this->window); + } - void setContext() - { - glfwMakeContextCurrent (this->window); - glfwSwapInterval (0); - } - void releaseContext() { glfwMakeContextCurrent (nullptr); } + //! Set to true when the program should end + bool readyToFinish = false; - // You will need to re-implement this function - virtual void compute() = 0; + protected: - void keepOpen() - { - while (this->readyToFinish == false) { - glfwWaitEventsTimeout (0.01667); // 16.67 ms ~ 60 Hz - this->render(); - } + void init_glfw() + { + mplot::VisualGlfw::i().init(); + // See https://www.glfw.org/docs/latest/monitor_guide.html + GLFWmonitor* primary = glfwGetPrimaryMonitor(); + glfwGetMonitorContentScale (primary, &this->monitor_xscale, &this->monitor_yscale); + glfwGetMonitorWorkarea (primary, &this->workarea_xpos, &this->workarea_ypos, &this->workarea_width, &this->workarea_height); + } + + void init_window() + { + this->window = glfwCreateWindow (this->win_sz[0], this->win_sz[1], this->title.c_str(), NULL, NULL); + if (!this->window) { + throw std::runtime_error("GLFW compute window creation failed!"); } - - //! You may wish to render the result of your compute. This method can be overridden. - virtual void render() - { - glfwSwapBuffers (this->window); + // Set up GLFW callbacks + glfwSetWindowUserPointer (this->window, this); // Bind window to this object. Required for callbacks + glfwSetKeyCallback (this->window, key_callback_dispatch); + glfwSetWindowCloseCallback (this->window, window_close_callback_dispatch); + + // Lastly make the context current + glfwMakeContextCurrent (this->window); + glfwSwapInterval (0); + } + + // Initialize OpenGL shaders, set any GL flags required + void init_gl() + { + // Swap as fast as possible to compute as fast as possible + glfwSwapInterval (0); + + unsigned char* glv = (unsigned char*)glGetString(GL_VERSION); + std::cout << "compute_manager<" << mplot::gl::version::vstring (glver) + << "> running on OpenGL Version " << glv << std::endl; + + // Store, and also output to stdout, some info about the GL resources available + glGetIntegerv (GL_MAX_COMPUTE_ATOMIC_COUNTERS, &this->max_compute_atomic_counters); + mplot::gl::Util::checkError (__FILE__, __LINE__); + std::cout << "GL_MAX_COMPUTE_ATOMIC_COUNTERS: " << this->max_compute_atomic_counters << std::endl; + + glGetIntegerv (GL_MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS, &this->max_compute_atomic_counters_buffers); + mplot::gl::Util::checkError (__FILE__, __LINE__); + std::cout << "GL_MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS: " << this->max_compute_atomic_counters_buffers << std::endl; + + glGetIntegerv (GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS, &this->max_compute_shader_storage_blocks); + mplot::gl::Util::checkError (__FILE__, __LINE__); + std::cout << "GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS: " << this->max_compute_shader_storage_blocks << std::endl; + + glGetIntegerv (GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS, &this->max_compute_texture_image_units); + mplot::gl::Util::checkError (__FILE__, __LINE__); + std::cout << "GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS: " << this->max_compute_texture_image_units << std::endl; + + glGetIntegerv (GL_MAX_COMPUTE_UNIFORM_BLOCKS, &this->max_compute_uniform_blocks); + mplot::gl::Util::checkError (__FILE__, __LINE__); + std::cout << "GL_MAX_COMPUTE_UNIFORM_BLOCKS: " << this->max_compute_uniform_blocks << std::endl; + + glGetIntegerv (GL_MAX_COMPUTE_UNIFORM_COMPONENTS, &this->max_compute_uniform_components); + mplot::gl::Util::checkError (__FILE__, __LINE__); + std::cout << "GL_MAX_COMPUTE_UNIFORM_COMPONENTS: " << this->max_compute_uniform_components << std::endl; + + glGetInteger64v (GL_MAX_COMPUTE_WORK_GROUP_INVOCATIONS, &this->max_compute_work_group_invocations); + std::cout << "GL_MAX_COMPUTE_WORK_GROUP_INVOCATIONS: " << this->max_compute_work_group_invocations << std::endl; + + glGetInteger64i_v (GL_MAX_COMPUTE_WORK_GROUP_COUNT, 0, &this->max_compute_work_group_count[0]); + glGetInteger64i_v (GL_MAX_COMPUTE_WORK_GROUP_COUNT, 1, &this->max_compute_work_group_count[1]); + glGetInteger64i_v (GL_MAX_COMPUTE_WORK_GROUP_COUNT, 2, &this->max_compute_work_group_count[2]); + std::cout << "GL_MAX_COMPUTE_WORK_GROUP_COUNTS (x, y, z): " << this->max_compute_work_group_count << std::endl; + + glGetInteger64i_v (GL_MAX_COMPUTE_WORK_GROUP_SIZE, 0, &this->max_compute_work_group_size[0]); + glGetInteger64i_v (GL_MAX_COMPUTE_WORK_GROUP_SIZE, 1, &this->max_compute_work_group_size[1]); + glGetInteger64i_v (GL_MAX_COMPUTE_WORK_GROUP_SIZE, 2, &this->max_compute_work_group_size[2]); + std::cout << "GL_MAX_COMPUTE_WORK_GROUP_SIZE (x, y, z): " << this->max_compute_work_group_size << std::endl; + + glGetIntegerv (GL_MAX_COMPUTE_SHARED_MEMORY_SIZE, &this->max_compute_shared_memory_size); + mplot::gl::Util::checkError (__FILE__, __LINE__); + std::cout << "GL_MAX_COMPUTE_SHARED_MEMORY_SIZE: " << this->max_compute_shared_memory_size << " bytes" << std::endl; + + // Shader storage + glGetIntegerv (GL_MAX_SHADER_STORAGE_BLOCK_SIZE, &this->max_shader_storage_block_size); + mplot::gl::Util::checkError (__FILE__, __LINE__); + std::cout << "GL_MAX_SHADER_STORAGE_BLOCK_SIZE: " << this->max_shader_storage_block_size << std::endl; + + glGetIntegerv (GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS, &this->max_shader_storage_buffer_bindings); + mplot::gl::Util::checkError (__FILE__, __LINE__); + std::cout << "GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS: " << this->max_shader_storage_buffer_bindings << std::endl; + + // Combined + glGetIntegerv (GL_MAX_TEXTURE_IMAGE_UNITS, &this->max_texture_image_units); + mplot::gl::Util::checkError (__FILE__, __LINE__); + std::cout << "GL_MAX_TEXTURE_IMAGE_UNITS: " << this->max_texture_image_units << std::endl; + + glGetIntegerv (GL_MAX_TEXTURE_SIZE, &this->max_texture_size); + mplot::gl::Util::checkError (__FILE__, __LINE__); + std::cout << "GL_MAX_TEXTURE_SIZE: " << this->max_texture_size << std::endl; + + glGetIntegerv (GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &this->max_combined_texture_image_units); + mplot::gl::Util::checkError (__FILE__, __LINE__); + std::cout << "GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS: " << this->max_combined_texture_image_units << std::endl; + + // Not mentioned on es3.1 Reference page https://registry.khronos.org/OpenGL-Refpages/es3.1/html/glGet.xhtml but can be queried: + glGetIntegerv (GL_MAX_IMAGE_UNITS, &this->max_image_units); + mplot::gl::Util::checkError (__FILE__, __LINE__); + std::cout << "GL_MAX_IMAGE_UNITS: " << this->max_image_units << std::endl; + + load_shaders(); + + // No need to set any GL flags (though a derived class may need to if it is to render any graphics) + + mplot::gl::Util::checkError (__FILE__, __LINE__); + } + + public: + // Add an implementation of load_shaders looking something like: + // + // void load_shaders() finals + // { + // std::vector shaders1 = { + // {GL_COMPUTE_SHADER, "Default.compute1.glsl", mplot::gl::nonCompilingComputeShader, 0 } + // }; + // this->my_compute_program_1.load_shaders (shaders1); + // + // std::vector shaders2 = { + // {GL_COMPUTE_SHADER, "Default.compute2.glsl", mplot::gl::nonCompilingComputeShader, 0 } + // }; + // this->my_compute_program_2.load_shaders (shaders2); + // } + // + // Here "Default.compute.glsl" is the path to a file containing the GLSL + // code. mplot::defaultComputeShader is a const char* of some default GLSL code + // text that will be used if the file cannot be accessed. + // + virtual void load_shaders() = 0; + + protected: + //! The window (and OpenGL context) for this gl::compute_manager + GLFWwindow* window = nullptr; + + //! Monitor info, obtained from glfw + float monitor_xscale = 0.0f; + float monitor_yscale = 0.0f; + + //! Desktop environment workarea info, obtained from glfw. + int workarea_xpos=0; + int workarea_ypos=0; + int workarea_width=0; + int workarea_height=0; + + //! Window size, if the derived class creates a Window + sm::vec win_sz = { 640, 480 }; + //! The title for the object, if needed + std::string title = "mplot::gl_compute"; + + // Various runtime-queryable limits on computation. The GL names for each of these can + // be obtained by upper-casing and prepending 'GL_'. E.g.: max_compute_atomic_counters will + // be set from a query of GL_MAX_COMPUTE_ATOMIC_COUNTERS. + GLint max_compute_atomic_counters = -1; + GLint max_compute_atomic_counters_buffers = -1; + GLint max_compute_shader_storage_blocks = -1; + GLint max_compute_texture_image_units = -1; + GLint max_compute_uniform_blocks = -1; + GLint max_compute_uniform_components = -1; + GLint64 max_compute_work_group_invocations = -1; + sm::vec max_compute_work_group_count = {-1,-1,-1}; + sm::vec max_compute_work_group_size = {-1,-1,-1}; + GLint max_compute_shared_memory_size = -1; // bytes + GLint max_shader_storage_block_size = -1; // bytes? + GLint max_shader_storage_buffer_bindings = -1; + GLint max_texture_image_units = -1; + GLint max_texture_size = -1; // bytes? + GLint max_combined_texture_image_units = -1; + GLint max_image_units = -1; + + // For frame count timing + static constexpr unsigned int nframes = 1000; + static constexpr double nframes_d = nframes; + static constexpr double nframes_d_us = nframes_d * 1000000; + unsigned int frame_count = 0; + sc::time_point t0, t1; + + // Measure the time to execute nframes frames and output an FPS message. Client + // code has to call this with every call to compute() to get the measurement + // (though its use is entirely optional). + void measure_compute() + { + if ((frame_count++ % nframes) == 0) { + this->t1 = sc::now(); + sc::duration t_d = t1 - t0; + double s_per_frame = duration_cast(t_d).count() / nframes_d_us; + std::cout << "FPS: " << 1.0/s_per_frame << std::endl; + this->t0 = this->t1; } + } - //! Set to true when the program should end - bool readyToFinish = false; - - protected: - - void init_glfw() - { - mplot::VisualGlfw::i().init(); - // See https://www.glfw.org/docs/latest/monitor_guide.html - GLFWmonitor* primary = glfwGetPrimaryMonitor(); - glfwGetMonitorContentScale (primary, &this->monitor_xscale, &this->monitor_yscale); - glfwGetMonitorWorkarea (primary, &this->workarea_xpos, &this->workarea_ypos, &this->workarea_width, &this->workarea_height); - } + //! An error callback function for the GLFW windowing library + static void errorCallback (int error, const char* description) + { + std::cerr << "Error: " << description << " (code " << error << ")\n"; + } - void init_window() - { - this->window = glfwCreateWindow (this->win_sz[0], this->win_sz[1], this->title.c_str(), NULL, NULL); - if (!this->window) { - throw std::runtime_error("GLFW compute window creation failed!"); - } - // Set up GLFW callbacks - glfwSetWindowUserPointer (this->window, this); // Bind window to this object. Required for callbacks - glfwSetKeyCallback (this->window, key_callback_dispatch); - glfwSetWindowCloseCallback (this->window, window_close_callback_dispatch); - - // Lastly make the context current - glfwMakeContextCurrent (this->window); - glfwSwapInterval (0); + private: + static void key_callback_dispatch (GLFWwindow* _window, int key, int scancode, int action, int mods) + { + compute_manager* self = static_cast*>(glfwGetWindowUserPointer (_window)); + if (self->key_callback (key, scancode, action, mods)) { + std::cout << "key_callback returned\n"; + self->compute(); } + } + static void window_close_callback_dispatch (GLFWwindow* _window) + { + compute_manager* self = static_cast*>(glfwGetWindowUserPointer (_window)); + self->window_close_callback(); + } - // Initialize OpenGL shaders, set any GL flags required - void init_gl() - { - // Swap as fast as possible to compute as fast as possible - glfwSwapInterval (0); - - unsigned char* glv = (unsigned char*)glGetString(GL_VERSION); - std::cout << "compute_manager<" << mplot::gl::version::vstring (glver) - << "> running on OpenGL Version " << glv << std::endl; - - // Store, and also output to stdout, some info about the GL resources available - glGetIntegerv (GL_MAX_COMPUTE_ATOMIC_COUNTERS, &this->max_compute_atomic_counters); - mplot::gl::Util::checkError (__FILE__, __LINE__); - std::cout << "GL_MAX_COMPUTE_ATOMIC_COUNTERS: " << this->max_compute_atomic_counters << std::endl; - - glGetIntegerv (GL_MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS, &this->max_compute_atomic_counters_buffers); - mplot::gl::Util::checkError (__FILE__, __LINE__); - std::cout << "GL_MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS: " << this->max_compute_atomic_counters_buffers << std::endl; - - glGetIntegerv (GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS, &this->max_compute_shader_storage_blocks); - mplot::gl::Util::checkError (__FILE__, __LINE__); - std::cout << "GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS: " << this->max_compute_shader_storage_blocks << std::endl; - - glGetIntegerv (GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS, &this->max_compute_texture_image_units); - mplot::gl::Util::checkError (__FILE__, __LINE__); - std::cout << "GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS: " << this->max_compute_texture_image_units << std::endl; - - glGetIntegerv (GL_MAX_COMPUTE_UNIFORM_BLOCKS, &this->max_compute_uniform_blocks); - mplot::gl::Util::checkError (__FILE__, __LINE__); - std::cout << "GL_MAX_COMPUTE_UNIFORM_BLOCKS: " << this->max_compute_uniform_blocks << std::endl; - - glGetIntegerv (GL_MAX_COMPUTE_UNIFORM_COMPONENTS, &this->max_compute_uniform_components); - mplot::gl::Util::checkError (__FILE__, __LINE__); - std::cout << "GL_MAX_COMPUTE_UNIFORM_COMPONENTS: " << this->max_compute_uniform_components << std::endl; - - glGetInteger64v (GL_MAX_COMPUTE_WORK_GROUP_INVOCATIONS, &this->max_compute_work_group_invocations); - std::cout << "GL_MAX_COMPUTE_WORK_GROUP_INVOCATIONS: " << this->max_compute_work_group_invocations << std::endl; - - glGetInteger64i_v (GL_MAX_COMPUTE_WORK_GROUP_COUNT, 0, &this->max_compute_work_group_count[0]); - glGetInteger64i_v (GL_MAX_COMPUTE_WORK_GROUP_COUNT, 1, &this->max_compute_work_group_count[1]); - glGetInteger64i_v (GL_MAX_COMPUTE_WORK_GROUP_COUNT, 2, &this->max_compute_work_group_count[2]); - std::cout << "GL_MAX_COMPUTE_WORK_GROUP_COUNTS (x, y, z): " << this->max_compute_work_group_count << std::endl; - - glGetInteger64i_v (GL_MAX_COMPUTE_WORK_GROUP_SIZE, 0, &this->max_compute_work_group_size[0]); - glGetInteger64i_v (GL_MAX_COMPUTE_WORK_GROUP_SIZE, 1, &this->max_compute_work_group_size[1]); - glGetInteger64i_v (GL_MAX_COMPUTE_WORK_GROUP_SIZE, 2, &this->max_compute_work_group_size[2]); - std::cout << "GL_MAX_COMPUTE_WORK_GROUP_SIZE (x, y, z): " << this->max_compute_work_group_size << std::endl; - - glGetIntegerv (GL_MAX_COMPUTE_SHARED_MEMORY_SIZE, &this->max_compute_shared_memory_size); - mplot::gl::Util::checkError (__FILE__, __LINE__); - std::cout << "GL_MAX_COMPUTE_SHARED_MEMORY_SIZE: " << this->max_compute_shared_memory_size << " bytes" << std::endl; - - // Shader storage - glGetIntegerv (GL_MAX_SHADER_STORAGE_BLOCK_SIZE, &this->max_shader_storage_block_size); - mplot::gl::Util::checkError (__FILE__, __LINE__); - std::cout << "GL_MAX_SHADER_STORAGE_BLOCK_SIZE: " << this->max_shader_storage_block_size << std::endl; - - glGetIntegerv (GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS, &this->max_shader_storage_buffer_bindings); - mplot::gl::Util::checkError (__FILE__, __LINE__); - std::cout << "GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS: " << this->max_shader_storage_buffer_bindings << std::endl; - - // Combined - glGetIntegerv (GL_MAX_TEXTURE_IMAGE_UNITS, &this->max_texture_image_units); - mplot::gl::Util::checkError (__FILE__, __LINE__); - std::cout << "GL_MAX_TEXTURE_IMAGE_UNITS: " << this->max_texture_image_units << std::endl; - - glGetIntegerv (GL_MAX_TEXTURE_SIZE, &this->max_texture_size); - mplot::gl::Util::checkError (__FILE__, __LINE__); - std::cout << "GL_MAX_TEXTURE_SIZE: " << this->max_texture_size << std::endl; - - glGetIntegerv (GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &this->max_combined_texture_image_units); - mplot::gl::Util::checkError (__FILE__, __LINE__); - std::cout << "GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS: " << this->max_combined_texture_image_units << std::endl; - - // Not mentioned on es3.1 Reference page https://registry.khronos.org/OpenGL-Refpages/es3.1/html/glGet.xhtml but can be queried: - glGetIntegerv (GL_MAX_IMAGE_UNITS, &this->max_image_units); - mplot::gl::Util::checkError (__FILE__, __LINE__); - std::cout << "GL_MAX_IMAGE_UNITS: " << this->max_image_units << std::endl; - - load_shaders(); - - // No need to set any GL flags (though a derived class may need to if it is to render any graphics) - - mplot::gl::Util::checkError (__FILE__, __LINE__); - } + public: + /* + * Generic callback handlers + */ + using keyaction = mplot::keyaction; + using keymod = mplot::keymod; + using key = mplot::key; + // The key_callback handler uses GLFW codes, but they're in a mplot header (keys.h) + virtual bool key_callback (int _key, int scancode, int action, int mods) + { + bool needs_render = false; - public: - // Add an implementation of load_shaders looking something like: - // - // void load_shaders() finals - // { - // std::vector shaders1 = { - // {GL_COMPUTE_SHADER, "Default.compute1.glsl", mplot::gl::nonCompilingComputeShader, 0 } - // }; - // this->my_compute_program_1.load_shaders (shaders1); - // - // std::vector shaders2 = { - // {GL_COMPUTE_SHADER, "Default.compute2.glsl", mplot::gl::nonCompilingComputeShader, 0 } - // }; - // this->my_compute_program_2.load_shaders (shaders2); - // } - // - // Here "Default.compute.glsl" is the path to a file containing the GLSL - // code. mplot::defaultComputeShader is a const char* of some default GLSL code - // text that will be used if the file cannot be accessed. - // - virtual void load_shaders() = 0; - - protected: - //! The window (and OpenGL context) for this gl::compute_manager - GLFWwindow* window = nullptr; - - //! Monitor info, obtained from glfw - float monitor_xscale = 0.0f; - float monitor_yscale = 0.0f; - - //! Desktop environment workarea info, obtained from glfw. - int workarea_xpos=0; - int workarea_ypos=0; - int workarea_width=0; - int workarea_height=0; - - //! Window size, if the derived class creates a Window - sm::vec win_sz = { 640, 480 }; - //! The title for the object, if needed - std::string title = "mplot::gl_compute"; - - // Various runtime-queryable limits on computation. The GL names for each of these can - // be obtained by upper-casing and prepending 'GL_'. E.g.: max_compute_atomic_counters will - // be set from a query of GL_MAX_COMPUTE_ATOMIC_COUNTERS. - GLint max_compute_atomic_counters = -1; - GLint max_compute_atomic_counters_buffers = -1; - GLint max_compute_shader_storage_blocks = -1; - GLint max_compute_texture_image_units = -1; - GLint max_compute_uniform_blocks = -1; - GLint max_compute_uniform_components = -1; - GLint64 max_compute_work_group_invocations = -1; - sm::vec max_compute_work_group_count = {-1,-1,-1}; - sm::vec max_compute_work_group_size = {-1,-1,-1}; - GLint max_compute_shared_memory_size = -1; // bytes - GLint max_shader_storage_block_size = -1; // bytes? - GLint max_shader_storage_buffer_bindings = -1; - GLint max_texture_image_units = -1; - GLint max_texture_size = -1; // bytes? - GLint max_combined_texture_image_units = -1; - GLint max_image_units = -1; - - // For frame count timing - static constexpr unsigned int nframes = 1000; - static constexpr double nframes_d = nframes; - static constexpr double nframes_d_us = nframes_d * 1000000; - unsigned int frame_count = 0; - sc::time_point t0, t1; - - // Measure the time to execute nframes frames and output an FPS message. Client - // code has to call this with every call to compute() to get the measurement - // (though its use is entirely optional). - void measure_compute() - { - if ((frame_count++ % nframes) == 0) { - this->t1 = sc::now(); - sc::duration t_d = t1 - t0; - double s_per_frame = duration_cast(t_d).count() / nframes_d_us; - std::cout << "FPS: " << 1.0/s_per_frame << std::endl; - this->t0 = this->t1; - } + // Exit action + if (_key == key::q && (mods & keymod::control) && action == keyaction::press) { + this->signal_to_quit(); } - //! An error callback function for the GLFW windowing library - static void errorCallback (int error, const char* description) - { - std::cerr << "Error: " << description << " (code " << error << ")\n"; + if (_key == key::h && (mods & keymod::control) && action == keyaction::press) { + std::cout << "Ctrl-h: Output this help to stdout\n"; + std::cout << "Ctrl-q: Quit\n"; } - private: - static void key_callback_dispatch (GLFWwindow* _window, int key, int scancode, int action, int mods) - { - compute_manager* self = static_cast*>(glfwGetWindowUserPointer (_window)); - if (self->key_callback (key, scancode, action, mods)) { - std::cout << "key_callback returned\n"; - self->compute(); - } - } - static void window_close_callback_dispatch (GLFWwindow* _window) - { - compute_manager* self = static_cast*>(glfwGetWindowUserPointer (_window)); - self->window_close_callback(); - } + this->key_callback_extra (_key, scancode, action, mods); - public: - /* - * Generic callback handlers - */ - using keyaction = mplot::keyaction; - using keymod = mplot::keymod; - using key = mplot::key; - // The key_callback handler uses GLFW codes, but they're in a mplot header (keys.h) - virtual bool key_callback (int _key, int scancode, int action, int mods) - { - bool needs_render = false; - - // Exit action - if (_key == key::q && (mods & keymod::control) && action == keyaction::press) { - this->signal_to_quit(); - } - - if (_key == key::h && (mods & keymod::control) && action == keyaction::press) { - std::cout << "Ctrl-h: Output this help to stdout\n"; - std::cout << "Ctrl-q: Quit\n"; - } - - this->key_callback_extra (_key, scancode, action, mods); - - return needs_render; - } + return needs_render; + } - virtual void window_close_callback() { this->signal_to_quit(); } + virtual void window_close_callback() { this->signal_to_quit(); } - //! Extra key callback handling, making it easy for client programs to implement their own actions - static constexpr bool debug_callback_extra = false; - virtual void key_callback_extra (int key, int scancode, int action, int mods) - { - if constexpr (debug_callback_extra) { - std::cout << "Visual::key_callback_extra called for key=" << key << " scancode=" - << scancode << " action=" << action << " and mods=" << mods << std::endl; - } + //! Extra key callback handling, making it easy for client programs to implement their own actions + static constexpr bool debug_callback_extra = false; + virtual void key_callback_extra (int key, int scancode, int action, int mods) + { + if constexpr (debug_callback_extra) { + std::cout << "Visual::key_callback_extra called for key=" << key << " scancode=" + << scancode << " action=" << action << " and mods=" << mods << std::endl; } + } - //! A callback that client code can set so that it knows when user has signalled to - //! mplot::gl_compute that it's quit time. - std::function external_quit_callback; - - protected: - //! This internal quit function could set a 'readyToFinish' flag that your code can respond - //! to, and calls an external callback function that you may have set up. - void signal_to_quit() - { - std::cout << "User requested exit.\n"; - // 1. Set our 'readyToFinish' flag to true - this->readyToFinish = true; - // 2. Call any external callback that's been set by client code - if (this->external_quit_callback) { this->external_quit_callback(); } - } - }; + //! A callback that client code can set so that it knows when user has signalled to + //! mplot::gl_compute that it's quit time. + std::function external_quit_callback; - } // namespace gl -} // namespace mplot + protected: + //! This internal quit function could set a 'readyToFinish' flag that your code can respond + //! to, and calls an external callback function that you may have set up. + void signal_to_quit() + { + std::cout << "User requested exit.\n"; + // 1. Set our 'readyToFinish' flag to true + this->readyToFinish = true; + // 2. Call any external callback that's been set by client code + if (this->external_quit_callback) { this->external_quit_callback(); } + } + }; +} // namespace mplot::gl diff --git a/mplot/gl/compute_manager_cli.h b/mplot/gl/compute_manager_cli.h index 48356219..99912324 100644 --- a/mplot/gl/compute_manager_cli.h +++ b/mplot/gl/compute_manager_cli.h @@ -30,272 +30,269 @@ #include #include -namespace mplot { - namespace gl { +namespace mplot::gl +{ + using namespace std::chrono; + using sc = std::chrono::steady_clock; + + // A default shader which won't compile (better than having an empty no-op default shader) + const char* defaultComputeShader = "This is an intentionally non-compiling non-shader\n"; + + // You may wish to pass a compiled-in shader that will fail, so that your system MUST find the + // file-based shader in mplot::gl::LoadShaders. + const char* nonCompilingComputeShader = "This is an intentionally non-compiling non-shader\n"; + + /*! + * A gl compute environment. I think user will extend this class to add their data structures + * and then run with their own GLSL compute shader code. + */ + template + struct compute_manager_cli + { + compute_manager_cli() { this->t0 = sc::now(); } + ~compute_manager_cli() + { + // cleanup + } + + //! Init GLFW and then the GLFW window. What if you want to set window width + //! based on GLFW info such as this->workarea_width? In that case, instead + //! of calling this do-it-all init function, just call the init functions separately: + //! init_glfw(); do_stuff(); init_window(); init_gl(); + void init() + { + this->init_context(); + this->setContext(); + // Finally init GL + this->init_gl(); + } + + void setContext() + { + bool res = eglMakeCurrent (this->egl_dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, this->core_ctx); + if (res == false) { + throw std::runtime_error ("Failed to eglMakeCurrent for headless GL"); + } + } + void releaseContext() + { + } - using namespace std::chrono; - using sc = std::chrono::steady_clock; + // You will need to re-implement this function + virtual void compute() = 0; - // A default shader which won't compile (better than having an empty no-op default shader) - const char* defaultComputeShader = "This is an intentionally non-compiling non-shader\n"; + //! Set to true when the program should end + bool readyToFinish = false; - // You may wish to pass a compiled-in shader that will fail, so that your system MUST find the - // file-based shader in mplot::gl::LoadShaders. - const char* nonCompilingComputeShader = "This is an intentionally non-compiling non-shader\n"; + protected: - /*! - * A gl compute environment. I think user will extend this class to add their data structures - * and then run with their own GLSL compute shader code. - */ - template - struct compute_manager_cli + void init_context() { - compute_manager_cli() { this->t0 = sc::now(); } - ~compute_manager_cli() - { - // cleanup + // Set up a GBM device + int fd = open ("/dev/dri/renderD128", O_RDWR); + if (fd <= 0) { + throw std::runtime_error ("Failed to open renderD128 device for headless GL"); } - - //! Init GLFW and then the GLFW window. What if you want to set window width - //! based on GLFW info such as this->workarea_width? In that case, instead - //! of calling this do-it-all init function, just call the init functions separately: - //! init_glfw(); do_stuff(); init_window(); init_gl(); - void init() - { - this->init_context(); - this->setContext(); - // Finally init GL - this->init_gl(); + struct gbm_device* gbm = gbm_create_device (fd); + if (gbm == nullptr) { + throw std::runtime_error ("Failed to gbm_create_device for headless GL"); } - void setContext() - { - bool res = eglMakeCurrent (this->egl_dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, this->core_ctx); - if (res == false) { - throw std::runtime_error ("Failed to eglMakeCurrent for headless GL"); - } - } - void releaseContext() - { + // setup EGL from the GBM device + this->egl_dpy = eglGetPlatformDisplay (EGL_PLATFORM_GBM_MESA, gbm, NULL); + if (this->egl_dpy == NULL) { + throw std::runtime_error ("Failed to eglGetPlatformDisplay for headless GL"); } - // You will need to re-implement this function - virtual void compute() = 0; - - //! Set to true when the program should end - bool readyToFinish = false; - - protected: - - void init_context() - { - // Set up a GBM device - int fd = open ("/dev/dri/renderD128", O_RDWR); - if (fd <= 0) { - throw std::runtime_error ("Failed to open renderD128 device for headless GL"); - } - struct gbm_device* gbm = gbm_create_device (fd); - if (gbm == nullptr) { - throw std::runtime_error ("Failed to gbm_create_device for headless GL"); - } - - // setup EGL from the GBM device - this->egl_dpy = eglGetPlatformDisplay (EGL_PLATFORM_GBM_MESA, gbm, NULL); - if (this->egl_dpy == NULL) { - throw std::runtime_error ("Failed to eglGetPlatformDisplay for headless GL"); - } - - bool res = eglInitialize (this->egl_dpy, NULL, NULL); - if (res == false) { - throw std::runtime_error ("Failed to eglInitialize display for headless GL"); - } - - const char* egl_extension_st = eglQueryString (egl_dpy, EGL_EXTENSIONS); - if (strstr (egl_extension_st, "EGL_KHR_create_context") == NULL) { - throw std::runtime_error ("query response did not contain EGL_KHR_create_context"); - } - if (strstr (egl_extension_st, "EGL_KHR_surfaceless_context") == NULL) { - throw std::runtime_error ("query response did not contain EGL_KHR_surfaceless_context"); - } - static const EGLint config_attribs[] = { - EGL_RENDERABLE_TYPE, EGL_OPENGL_ES3_BIT_KHR, - EGL_NONE - }; - EGLConfig cfg; - EGLint count; - - res = eglChooseConfig (this->egl_dpy, config_attribs, &cfg, 1, &count); - if (res == false) { - throw std::runtime_error ("Failed to eglChooseConfig for headless GL"); - } - - res = eglBindAPI (EGL_OPENGL_ES_API); - if (res == false) { - throw std::runtime_error ("Failed to eglBindAPI for headless GL"); - } - - static const EGLint attribs[] = { - EGL_CONTEXT_MAJOR_VERSION, mplot::gl::version::major(glver), - EGL_CONTEXT_MINOR_VERSION, mplot::gl::version::minor(glver), - EGL_NONE - }; - this->core_ctx = eglCreateContext (this->egl_dpy, cfg, EGL_NO_CONTEXT, attribs); - if (this->core_ctx == EGL_NO_CONTEXT) { - throw std::runtime_error ("Failed to eglCreateContext for headless GL"); - } + bool res = eglInitialize (this->egl_dpy, NULL, NULL); + if (res == false) { + throw std::runtime_error ("Failed to eglInitialize display for headless GL"); } - // Initialize OpenGL shaders, set any GL flags required - void init_gl() - { - unsigned char* glv = (unsigned char*)glGetString(GL_VERSION); - std::cout << "compute_manager_cli<" << mplot::gl::version::vstring (glver) - << "> running on OpenGL Version " << glv << std::endl; - - // Store, and also output to stdout, some info about the GL resources available - glGetIntegerv (GL_MAX_COMPUTE_ATOMIC_COUNTERS, &this->max_compute_atomic_counters); - mplot::gl::Util::checkError (__FILE__, __LINE__); - std::cout << "GL_MAX_COMPUTE_ATOMIC_COUNTERS: " << this->max_compute_atomic_counters << std::endl; - - glGetIntegerv (GL_MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS, &this->max_compute_atomic_counters_buffers); - mplot::gl::Util::checkError (__FILE__, __LINE__); - std::cout << "GL_MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS: " << this->max_compute_atomic_counters_buffers << std::endl; - - glGetIntegerv (GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS, &this->max_compute_shader_storage_blocks); - mplot::gl::Util::checkError (__FILE__, __LINE__); - std::cout << "GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS: " << this->max_compute_shader_storage_blocks << std::endl; - - glGetIntegerv (GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS, &this->max_compute_texture_image_units); - mplot::gl::Util::checkError (__FILE__, __LINE__); - std::cout << "GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS: " << this->max_compute_texture_image_units << std::endl; - - glGetIntegerv (GL_MAX_COMPUTE_UNIFORM_BLOCKS, &this->max_compute_uniform_blocks); - mplot::gl::Util::checkError (__FILE__, __LINE__); - std::cout << "GL_MAX_COMPUTE_UNIFORM_BLOCKS: " << this->max_compute_uniform_blocks << std::endl; - - glGetIntegerv (GL_MAX_COMPUTE_UNIFORM_COMPONENTS, &this->max_compute_uniform_components); - mplot::gl::Util::checkError (__FILE__, __LINE__); - std::cout << "GL_MAX_COMPUTE_UNIFORM_COMPONENTS: " << this->max_compute_uniform_components << std::endl; - - glGetInteger64v (GL_MAX_COMPUTE_WORK_GROUP_INVOCATIONS, &this->max_compute_work_group_invocations); - std::cout << "GL_MAX_COMPUTE_WORK_GROUP_INVOCATIONS: " << this->max_compute_work_group_invocations << std::endl; - - glGetInteger64i_v (GL_MAX_COMPUTE_WORK_GROUP_COUNT, 0, &this->max_compute_work_group_count[0]); - glGetInteger64i_v (GL_MAX_COMPUTE_WORK_GROUP_COUNT, 1, &this->max_compute_work_group_count[1]); - glGetInteger64i_v (GL_MAX_COMPUTE_WORK_GROUP_COUNT, 2, &this->max_compute_work_group_count[2]); - std::cout << "GL_MAX_COMPUTE_WORK_GROUP_COUNTS (x, y, z): " << this->max_compute_work_group_count << std::endl; - - glGetInteger64i_v (GL_MAX_COMPUTE_WORK_GROUP_SIZE, 0, &this->max_compute_work_group_size[0]); - glGetInteger64i_v (GL_MAX_COMPUTE_WORK_GROUP_SIZE, 1, &this->max_compute_work_group_size[1]); - glGetInteger64i_v (GL_MAX_COMPUTE_WORK_GROUP_SIZE, 2, &this->max_compute_work_group_size[2]); - std::cout << "GL_MAX_COMPUTE_WORK_GROUP_SIZE (x, y, z): " << this->max_compute_work_group_size << std::endl; - - glGetIntegerv (GL_MAX_COMPUTE_SHARED_MEMORY_SIZE, &this->max_compute_shared_memory_size); - mplot::gl::Util::checkError (__FILE__, __LINE__); - std::cout << "GL_MAX_COMPUTE_SHARED_MEMORY_SIZE: " << this->max_compute_shared_memory_size << " bytes" << std::endl; - - // Shader storage - glGetIntegerv (GL_MAX_SHADER_STORAGE_BLOCK_SIZE, &this->max_shader_storage_block_size); - mplot::gl::Util::checkError (__FILE__, __LINE__); - std::cout << "GL_MAX_SHADER_STORAGE_BLOCK_SIZE: " << this->max_shader_storage_block_size << std::endl; - - glGetIntegerv (GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS, &this->max_shader_storage_buffer_bindings); - mplot::gl::Util::checkError (__FILE__, __LINE__); - std::cout << "GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS: " << this->max_shader_storage_buffer_bindings << std::endl; - - // Combined - glGetIntegerv (GL_MAX_TEXTURE_IMAGE_UNITS, &this->max_texture_image_units); - mplot::gl::Util::checkError (__FILE__, __LINE__); - std::cout << "GL_MAX_TEXTURE_IMAGE_UNITS: " << this->max_texture_image_units << std::endl; - - glGetIntegerv (GL_MAX_TEXTURE_SIZE, &this->max_texture_size); - mplot::gl::Util::checkError (__FILE__, __LINE__); - std::cout << "GL_MAX_TEXTURE_SIZE: " << this->max_texture_size << std::endl; - - glGetIntegerv (GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &this->max_combined_texture_image_units); - mplot::gl::Util::checkError (__FILE__, __LINE__); - std::cout << "GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS: " << this->max_combined_texture_image_units << std::endl; - - // Not mentioned on es3.1 Reference page https://registry.khronos.org/OpenGL-Refpages/es3.1/html/glGet.xhtml but can be queried: - glGetIntegerv (GL_MAX_IMAGE_UNITS, &this->max_image_units); - mplot::gl::Util::checkError (__FILE__, __LINE__); - std::cout << "GL_MAX_IMAGE_UNITS: " << this->max_image_units << std::endl; - - load_shaders(); - - // No need to set any GL flags (though a derived class may need to if it is to render any graphics) + const char* egl_extension_st = eglQueryString (egl_dpy, EGL_EXTENSIONS); + if (strstr (egl_extension_st, "EGL_KHR_create_context") == NULL) { + throw std::runtime_error ("query response did not contain EGL_KHR_create_context"); + } + if (strstr (egl_extension_st, "EGL_KHR_surfaceless_context") == NULL) { + throw std::runtime_error ("query response did not contain EGL_KHR_surfaceless_context"); + } + static const EGLint config_attribs[] = { + EGL_RENDERABLE_TYPE, EGL_OPENGL_ES3_BIT_KHR, + EGL_NONE + }; + EGLConfig cfg; + EGLint count; + + res = eglChooseConfig (this->egl_dpy, config_attribs, &cfg, 1, &count); + if (res == false) { + throw std::runtime_error ("Failed to eglChooseConfig for headless GL"); + } - mplot::gl::Util::checkError (__FILE__, __LINE__); + res = eglBindAPI (EGL_OPENGL_ES_API); + if (res == false) { + throw std::runtime_error ("Failed to eglBindAPI for headless GL"); } - public: - // Add an implementation of load_shaders looking something like: - // - // void load_shaders() finals - // { - // std::vector shaders1 = { - // {GL_COMPUTE_SHADER, "Default.compute1.glsl", mplot::gl::nonCompilingComputeShader, 0 } - // }; - // this->my_compute_program_1.load_shaders (shaders1); - // - // std::vector shaders2 = { - // {GL_COMPUTE_SHADER, "Default.compute2.glsl", mplot::gl::nonCompilingComputeShader, 0 } - // }; - // this->my_compute_program_2.load_shaders (shaders2); - // } - // - // Here "Default.compute.glsl" is the path to a file containing the GLSL - // code. mplot::defaultComputeShader is a const char* of some default GLSL code - // text that will be used if the file cannot be accessed. - // - virtual void load_shaders() = 0; - - protected: - //! OpenGL context for this gl::compute_manager_cli goes here - EGLDisplay egl_dpy; - EGLContext core_ctx; - - // Various runtime-queryable limits on computation. The GL names for each of these can - // be obtained by upper-casing and prepending 'GL_'. E.g.: max_compute_atomic_counters will - // be set from a query of GL_MAX_COMPUTE_ATOMIC_COUNTERS. - GLint max_compute_atomic_counters = -1; - GLint max_compute_atomic_counters_buffers = -1; - GLint max_compute_shader_storage_blocks = -1; - GLint max_compute_texture_image_units = -1; - GLint max_compute_uniform_blocks = -1; - GLint max_compute_uniform_components = -1; - GLint64 max_compute_work_group_invocations = -1; - sm::vec max_compute_work_group_count = {-1,-1,-1}; - sm::vec max_compute_work_group_size = {-1,-1,-1}; - GLint max_compute_shared_memory_size = -1; // bytes - GLint max_shader_storage_block_size = -1; // bytes? - GLint max_shader_storage_buffer_bindings = -1; - GLint max_texture_image_units = -1; - GLint max_texture_size = -1; // bytes? - GLint max_combined_texture_image_units = -1; - GLint max_image_units = -1; - - // For frame count timing - static constexpr unsigned int nframes = 1000; - static constexpr double nframes_d = nframes; - static constexpr double nframes_d_us = nframes_d * 1000000; - unsigned int frame_count = 0; - sc::time_point t0, t1; - - // Measure the time to execute nframes frames and output an FPS message. Client - // code has to call this with every call to compute() to get the measurement - // (though its use is entirely optional). - void measure_compute() - { - if ((frame_count++ % nframes) == 0) { - this->t1 = sc::now(); - sc::duration t_d = t1 - t0; - double s_per_frame = duration_cast(t_d).count() / nframes_d_us; - std::cout << "FPS: " << 1.0/s_per_frame << std::endl; - this->t0 = this->t1; - } + static const EGLint attribs[] = { + EGL_CONTEXT_MAJOR_VERSION, mplot::gl::version::major(glver), + EGL_CONTEXT_MINOR_VERSION, mplot::gl::version::minor(glver), + EGL_NONE + }; + this->core_ctx = eglCreateContext (this->egl_dpy, cfg, EGL_NO_CONTEXT, attribs); + if (this->core_ctx == EGL_NO_CONTEXT) { + throw std::runtime_error ("Failed to eglCreateContext for headless GL"); } - }; + } - } // namespace gl -} // namespace mplot + // Initialize OpenGL shaders, set any GL flags required + void init_gl() + { + unsigned char* glv = (unsigned char*)glGetString(GL_VERSION); + std::cout << "compute_manager_cli<" << mplot::gl::version::vstring (glver) + << "> running on OpenGL Version " << glv << std::endl; + + // Store, and also output to stdout, some info about the GL resources available + glGetIntegerv (GL_MAX_COMPUTE_ATOMIC_COUNTERS, &this->max_compute_atomic_counters); + mplot::gl::Util::checkError (__FILE__, __LINE__); + std::cout << "GL_MAX_COMPUTE_ATOMIC_COUNTERS: " << this->max_compute_atomic_counters << std::endl; + + glGetIntegerv (GL_MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS, &this->max_compute_atomic_counters_buffers); + mplot::gl::Util::checkError (__FILE__, __LINE__); + std::cout << "GL_MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS: " << this->max_compute_atomic_counters_buffers << std::endl; + + glGetIntegerv (GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS, &this->max_compute_shader_storage_blocks); + mplot::gl::Util::checkError (__FILE__, __LINE__); + std::cout << "GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS: " << this->max_compute_shader_storage_blocks << std::endl; + + glGetIntegerv (GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS, &this->max_compute_texture_image_units); + mplot::gl::Util::checkError (__FILE__, __LINE__); + std::cout << "GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS: " << this->max_compute_texture_image_units << std::endl; + + glGetIntegerv (GL_MAX_COMPUTE_UNIFORM_BLOCKS, &this->max_compute_uniform_blocks); + mplot::gl::Util::checkError (__FILE__, __LINE__); + std::cout << "GL_MAX_COMPUTE_UNIFORM_BLOCKS: " << this->max_compute_uniform_blocks << std::endl; + + glGetIntegerv (GL_MAX_COMPUTE_UNIFORM_COMPONENTS, &this->max_compute_uniform_components); + mplot::gl::Util::checkError (__FILE__, __LINE__); + std::cout << "GL_MAX_COMPUTE_UNIFORM_COMPONENTS: " << this->max_compute_uniform_components << std::endl; + + glGetInteger64v (GL_MAX_COMPUTE_WORK_GROUP_INVOCATIONS, &this->max_compute_work_group_invocations); + std::cout << "GL_MAX_COMPUTE_WORK_GROUP_INVOCATIONS: " << this->max_compute_work_group_invocations << std::endl; + + glGetInteger64i_v (GL_MAX_COMPUTE_WORK_GROUP_COUNT, 0, &this->max_compute_work_group_count[0]); + glGetInteger64i_v (GL_MAX_COMPUTE_WORK_GROUP_COUNT, 1, &this->max_compute_work_group_count[1]); + glGetInteger64i_v (GL_MAX_COMPUTE_WORK_GROUP_COUNT, 2, &this->max_compute_work_group_count[2]); + std::cout << "GL_MAX_COMPUTE_WORK_GROUP_COUNTS (x, y, z): " << this->max_compute_work_group_count << std::endl; + + glGetInteger64i_v (GL_MAX_COMPUTE_WORK_GROUP_SIZE, 0, &this->max_compute_work_group_size[0]); + glGetInteger64i_v (GL_MAX_COMPUTE_WORK_GROUP_SIZE, 1, &this->max_compute_work_group_size[1]); + glGetInteger64i_v (GL_MAX_COMPUTE_WORK_GROUP_SIZE, 2, &this->max_compute_work_group_size[2]); + std::cout << "GL_MAX_COMPUTE_WORK_GROUP_SIZE (x, y, z): " << this->max_compute_work_group_size << std::endl; + + glGetIntegerv (GL_MAX_COMPUTE_SHARED_MEMORY_SIZE, &this->max_compute_shared_memory_size); + mplot::gl::Util::checkError (__FILE__, __LINE__); + std::cout << "GL_MAX_COMPUTE_SHARED_MEMORY_SIZE: " << this->max_compute_shared_memory_size << " bytes" << std::endl; + + // Shader storage + glGetIntegerv (GL_MAX_SHADER_STORAGE_BLOCK_SIZE, &this->max_shader_storage_block_size); + mplot::gl::Util::checkError (__FILE__, __LINE__); + std::cout << "GL_MAX_SHADER_STORAGE_BLOCK_SIZE: " << this->max_shader_storage_block_size << std::endl; + + glGetIntegerv (GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS, &this->max_shader_storage_buffer_bindings); + mplot::gl::Util::checkError (__FILE__, __LINE__); + std::cout << "GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS: " << this->max_shader_storage_buffer_bindings << std::endl; + + // Combined + glGetIntegerv (GL_MAX_TEXTURE_IMAGE_UNITS, &this->max_texture_image_units); + mplot::gl::Util::checkError (__FILE__, __LINE__); + std::cout << "GL_MAX_TEXTURE_IMAGE_UNITS: " << this->max_texture_image_units << std::endl; + + glGetIntegerv (GL_MAX_TEXTURE_SIZE, &this->max_texture_size); + mplot::gl::Util::checkError (__FILE__, __LINE__); + std::cout << "GL_MAX_TEXTURE_SIZE: " << this->max_texture_size << std::endl; + + glGetIntegerv (GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &this->max_combined_texture_image_units); + mplot::gl::Util::checkError (__FILE__, __LINE__); + std::cout << "GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS: " << this->max_combined_texture_image_units << std::endl; + + // Not mentioned on es3.1 Reference page https://registry.khronos.org/OpenGL-Refpages/es3.1/html/glGet.xhtml but can be queried: + glGetIntegerv (GL_MAX_IMAGE_UNITS, &this->max_image_units); + mplot::gl::Util::checkError (__FILE__, __LINE__); + std::cout << "GL_MAX_IMAGE_UNITS: " << this->max_image_units << std::endl; + + load_shaders(); + + // No need to set any GL flags (though a derived class may need to if it is to render any graphics) + + mplot::gl::Util::checkError (__FILE__, __LINE__); + } + + public: + // Add an implementation of load_shaders looking something like: + // + // void load_shaders() finals + // { + // std::vector shaders1 = { + // {GL_COMPUTE_SHADER, "Default.compute1.glsl", mplot::gl::nonCompilingComputeShader, 0 } + // }; + // this->my_compute_program_1.load_shaders (shaders1); + // + // std::vector shaders2 = { + // {GL_COMPUTE_SHADER, "Default.compute2.glsl", mplot::gl::nonCompilingComputeShader, 0 } + // }; + // this->my_compute_program_2.load_shaders (shaders2); + // } + // + // Here "Default.compute.glsl" is the path to a file containing the GLSL + // code. mplot::defaultComputeShader is a const char* of some default GLSL code + // text that will be used if the file cannot be accessed. + // + virtual void load_shaders() = 0; + + protected: + //! OpenGL context for this gl::compute_manager_cli goes here + EGLDisplay egl_dpy; + EGLContext core_ctx; + + // Various runtime-queryable limits on computation. The GL names for each of these can + // be obtained by upper-casing and prepending 'GL_'. E.g.: max_compute_atomic_counters will + // be set from a query of GL_MAX_COMPUTE_ATOMIC_COUNTERS. + GLint max_compute_atomic_counters = -1; + GLint max_compute_atomic_counters_buffers = -1; + GLint max_compute_shader_storage_blocks = -1; + GLint max_compute_texture_image_units = -1; + GLint max_compute_uniform_blocks = -1; + GLint max_compute_uniform_components = -1; + GLint64 max_compute_work_group_invocations = -1; + sm::vec max_compute_work_group_count = {-1,-1,-1}; + sm::vec max_compute_work_group_size = {-1,-1,-1}; + GLint max_compute_shared_memory_size = -1; // bytes + GLint max_shader_storage_block_size = -1; // bytes? + GLint max_shader_storage_buffer_bindings = -1; + GLint max_texture_image_units = -1; + GLint max_texture_size = -1; // bytes? + GLint max_combined_texture_image_units = -1; + GLint max_image_units = -1; + + // For frame count timing + static constexpr unsigned int nframes = 1000; + static constexpr double nframes_d = nframes; + static constexpr double nframes_d_us = nframes_d * 1000000; + unsigned int frame_count = 0; + sc::time_point t0, t1; + + // Measure the time to execute nframes frames and output an FPS message. Client + // code has to call this with every call to compute() to get the measurement + // (though its use is entirely optional). + void measure_compute() + { + if ((frame_count++ % nframes) == 0) { + this->t1 = sc::now(); + sc::duration t_d = t1 - t0; + double s_per_frame = duration_cast(t_d).count() / nframes_d_us; + std::cout << "FPS: " << 1.0/s_per_frame << std::endl; + this->t0 = this->t1; + } + } + }; +} // namespace mplot::gl diff --git a/mplot/gl/compute_shaderprog.h b/mplot/gl/compute_shaderprog.h index a2a30fd3..2f825795 100644 --- a/mplot/gl/compute_shaderprog.h +++ b/mplot/gl/compute_shaderprog.h @@ -13,103 +13,100 @@ #include #include -namespace mplot { - namespace gl { +namespace mplot::gl +{ + template + struct compute_shaderprog + { + GLuint prog_id = 0; - template - struct compute_shaderprog - { - GLuint prog_id = 0; - - // Default constructor - compute_shaderprog() {} + // Default constructor + compute_shaderprog() {} - /* - * Construct with a structure of shader files looking like this: - * - * std::vector shaders = { - * {GL_COMPUTE_SHADER, "my_compute_shader.glsl", mplot::defaultComputeShader } - * }; - */ - compute_shaderprog (const std::vector& shaders) - { - this->load_shaders (shaders); - } + /* + * Construct with a structure of shader files looking like this: + * + * std::vector shaders = { + * {GL_COMPUTE_SHADER, "my_compute_shader.glsl", mplot::defaultComputeShader } + * }; + */ + compute_shaderprog (const std::vector& shaders) + { + this->load_shaders (shaders); + } - ~compute_shaderprog() - { - if (this->prog_id) { - glDeleteProgram (this->prog_id); - this->prog_id = 0; - } + ~compute_shaderprog() + { + if (this->prog_id) { + glDeleteProgram (this->prog_id); + this->prog_id = 0; } + } - void load_shaders (const std::vector& shaders) - { - this->prog_id = mplot::gl::LoadShaders (shaders); - } + void load_shaders (const std::vector& shaders) + { + this->prog_id = mplot::gl::LoadShaders (shaders); + } - void use() const { glUseProgram (this->prog_id); } + void use() const { glUseProgram (this->prog_id); } - // Convenience wrapper for dispatch - void dispatch (GLuint ngrps_x, GLuint ngrps_y, GLuint ngrps_z) const - { - glDispatchCompute (ngrps_x, ngrps_y, ngrps_z); - // Choices of GL_SHADER_IMAGE_ACCESS_BARRIER_BIT, GL_SHADER_STORAGE_BARRIER_BIT or GL_ALL_BARRIER_BITS (or others). - glMemoryBarrier (GL_ALL_BARRIER_BITS); - } + // Convenience wrapper for dispatch + void dispatch (GLuint ngrps_x, GLuint ngrps_y, GLuint ngrps_z) const + { + glDispatchCompute (ngrps_x, ngrps_y, ngrps_z); + // Choices of GL_SHADER_IMAGE_ACCESS_BARRIER_BIT, GL_SHADER_STORAGE_BARRIER_BIT or GL_ALL_BARRIER_BITS (or others). + glMemoryBarrier (GL_ALL_BARRIER_BITS); + } - // Set a uniform variable into the OpenGL context associated with this shader program - template - void set_uniform (const std::string& glsl_varname, const T& value) - { - GLint uloc = glGetUniformLocation (this->prog_id, static_cast(glsl_varname.c_str())); - this->check_uniform_location (glsl_varname, uloc); - if constexpr (std::is_same, float>::value == true) { - if (uloc != -1) { glUniform1f (uloc, static_cast(value)); } - } else if constexpr (std::is_same, int>::value == true) { - if (uloc != -1) { glUniform1i (uloc, static_cast(value)); } - } else if constexpr (std::is_same, unsigned int>::value == true) { - if (uloc != -1) { glUniform1ui (uloc, static_cast(value)); } - } else { - []() { static_assert(flag, "Can't set that type as a uniform in an OpenGL context"); }(); - } + // Set a uniform variable into the OpenGL context associated with this shader program + template + void set_uniform (const std::string& glsl_varname, const T& value) + { + GLint uloc = glGetUniformLocation (this->prog_id, static_cast(glsl_varname.c_str())); + this->check_uniform_location (glsl_varname, uloc); + if constexpr (std::is_same, float>::value == true) { + if (uloc != -1) { glUniform1f (uloc, static_cast(value)); } + } else if constexpr (std::is_same, int>::value == true) { + if (uloc != -1) { glUniform1i (uloc, static_cast(value)); } + } else if constexpr (std::is_same, unsigned int>::value == true) { + if (uloc != -1) { glUniform1ui (uloc, static_cast(value)); } + } else { + []() { static_assert(flag, "Can't set that type as a uniform in an OpenGL context"); }(); } + } - // Set an array into the OpenGL context - template - void set_uniform (const std::string& glsl_varname, const sm::vec& value) - { - GLint uloc = glGetUniformLocation (this->prog_id, static_cast(glsl_varname.c_str())); - this->check_uniform_location (glsl_varname, uloc); - if constexpr (std::is_same, float>::value == true) { - if (uloc != -1) { glUniform1fv (uloc, N, value.data()); } - } else if constexpr (std::is_same, int>::value == true) { - if (uloc != -1) { glUniform1iv (uloc, N, value.data()); } - } else if constexpr (std::is_same, unsigned int>::value == true) { - if (uloc != -1) { glUniform1uiv (uloc, N, value.data()); } - } else { - []() { static_assert(flag, "Can't set that type as a uniform array in an OpenGL context"); }(); - } + // Set an array into the OpenGL context + template + void set_uniform (const std::string& glsl_varname, const sm::vec& value) + { + GLint uloc = glGetUniformLocation (this->prog_id, static_cast(glsl_varname.c_str())); + this->check_uniform_location (glsl_varname, uloc); + if constexpr (std::is_same, float>::value == true) { + if (uloc != -1) { glUniform1fv (uloc, N, value.data()); } + } else if constexpr (std::is_same, int>::value == true) { + if (uloc != -1) { glUniform1iv (uloc, N, value.data()); } + } else if constexpr (std::is_same, unsigned int>::value == true) { + if (uloc != -1) { glUniform1uiv (uloc, N, value.data()); } + } else { + []() { static_assert(flag, "Can't set that type as a uniform array in an OpenGL context"); }(); } + } - private: - // Runtime check on a uniform location. If -1 throw exception. This is useful because - // any uniform variable in a GLSL program which is not used may be compiled out and thus - // be not 'active'. In this case, glGetUniformLocation will return -1. Our programmer - // should be told in an exception, and either not try to set_uniform on an inactive - // variable, or they should ensure the uniform IS actually used in their program. - void check_uniform_location (const std::string& glsl_varname, const GLint uloc) const - { - if (uloc == -1) { - std::stringstream ee; - ee << "Error: glGetUniformLocation returned -1\n" - << "Failed to get uniform location for the ACTIVE uniform " << glsl_varname.c_str() - << "\n(Hint: Make sure you USE your uniform in your GLSL code)" << std::endl; - throw std::runtime_error (ee.str()); - } + private: + // Runtime check on a uniform location. If -1 throw exception. This is useful because + // any uniform variable in a GLSL program which is not used may be compiled out and thus + // be not 'active'. In this case, glGetUniformLocation will return -1. Our programmer + // should be told in an exception, and either not try to set_uniform on an inactive + // variable, or they should ensure the uniform IS actually used in their program. + void check_uniform_location (const std::string& glsl_varname, const GLint uloc) const + { + if (uloc == -1) { + std::stringstream ee; + ee << "Error: glGetUniformLocation returned -1\n" + << "Failed to get uniform location for the ACTIVE uniform " << glsl_varname.c_str() + << "\n(Hint: Make sure you USE your uniform in your GLSL code)" << std::endl; + throw std::runtime_error (ee.str()); } - }; - - } // namespace gl -} // namespace mplot + } + }; +} // namespace mplot::gl diff --git a/mplot/gl/loadshaders_mx.h b/mplot/gl/loadshaders_mx.h index bb11cd79..a2ec95e7 100644 --- a/mplot/gl/loadshaders_mx.h +++ b/mplot/gl/loadshaders_mx.h @@ -12,111 +12,108 @@ #include #include -namespace mplot { +namespace mplot::gl +{ + //! Shader loading code. + GLuint LoadShadersMX (const std::vector& shader_info, GladGLContext* glfn) + { + if (shader_info.empty()) { return 0; } - namespace gl { - - //! Shader loading code. - GLuint LoadShadersMX (const std::vector& shader_info, GladGLContext* glfn) - { - if (shader_info.empty()) { return 0; } - - GLuint program = glfn->CreateProgram(); + GLuint program = glfn->CreateProgram(); #ifdef GL_SHADER_COMPILER - GLboolean shaderCompilerPresent = GL_FALSE; - glfn->GetBooleanv (GL_SHADER_COMPILER, &shaderCompilerPresent); - if (shaderCompilerPresent == GL_FALSE) { - std::cerr << "Shader compiler NOT present!\n"; - } else { - if constexpr (debug_shaders == true) { - std::cout << "Shader compiler present\n"; - } + GLboolean shaderCompilerPresent = GL_FALSE; + glfn->GetBooleanv (GL_SHADER_COMPILER, &shaderCompilerPresent); + if (shaderCompilerPresent == GL_FALSE) { + std::cerr << "Shader compiler NOT present!\n"; + } else { + if constexpr (debug_shaders == true) { + std::cout << "Shader compiler present\n"; } + } #endif - for (auto entry : shader_info) { - GLuint shader = glfn->CreateShader (entry.type); - entry.shader = shader; - // Test entry.filename. If this GLSL file can be read, then do so, otherwise, - // compile the default version specified in the ShaderInfo - std::unique_ptr source; + for (auto entry : shader_info) { + GLuint shader = glfn->CreateShader (entry.type); + entry.shader = shader; + // Test entry.filename. If this GLSL file can be read, then do so, otherwise, + // compile the default version specified in the ShaderInfo + std::unique_ptr source; + if constexpr (debug_shaders == true) { + std::cout << "Check file exists for " << entry.filename << std::endl; + } + if (mplot::tools::fileExists (entry.filename)) { + std::cout << "Using " << mplot::gl::shader_type_str(entry.type) + << " shader from the file " << entry.filename << std::endl; + source = mplot::gl::ReadShader (entry.filename); + } else { if constexpr (debug_shaders == true) { - std::cout << "Check file exists for " << entry.filename << std::endl; - } - if (mplot::tools::fileExists (entry.filename)) { - std::cout << "Using " << mplot::gl::shader_type_str(entry.type) - << " shader from the file " << entry.filename << std::endl; - source = mplot::gl::ReadShader (entry.filename); - } else { - if constexpr (debug_shaders == true) { - std::cout << "Using compiled-in " << mplot::gl::shader_type_str(entry.type) << " shader\n"; - } - source = mplot::gl::ReadDefaultShader (entry.compiledIn); - } - if (source == nullptr) { - for (auto entry : shader_info) { - glfn->DeleteShader (entry.shader); - entry.shader = 0; - } - return 0; - - } else { - if constexpr (debug_shaders == true) { - std::cout << "Compiling this shader: \n" << "-----\n"; - std::cout << source.get() << "-----\n"; - } + std::cout << "Using compiled-in " << mplot::gl::shader_type_str(entry.type) << " shader\n"; } - GLint slen = (GLint)std::strlen (source.get()); - const GLchar* sptr = source.get(); - glfn->ShaderSource (shader, 1, &sptr, &slen); - glfn->CompileShader (shader); - GLint shaderCompileSuccess = GL_FALSE; - char infoLog[512]; - glfn->GetShaderiv(shader, GL_COMPILE_STATUS, &shaderCompileSuccess); - if (!shaderCompileSuccess) { - glfn->GetShaderInfoLog(shader, 512, NULL, infoLog); - std::cerr << "\nShader compilation failed!"; - std::cerr << "\n--------------------------\n\n"; - std::cerr << source.get(); - std::cerr << "\n\n--------------------------\n"; - std::cerr << infoLog << std::endl; - std::cerr << "Exiting.\n"; - exit (2); + source = mplot::gl::ReadDefaultShader (entry.compiledIn); + } + if (source == nullptr) { + for (auto entry : shader_info) { + glfn->DeleteShader (entry.shader); + entry.shader = 0; } + return 0; - // Test glGetError: - GLenum shaderError = glfn->GetError(); - if (shaderError == GL_INVALID_VALUE) { - std::cerr << "Shader compilation resulted in GL_INVALID_VALUE\n"; - exit (3); - } else if (shaderError == GL_INVALID_OPERATION) { - std::cerr << "Shader compilation resulted in GL_INVALID_OPERATION\n"; - exit (4); - } // shaderError is 0 - + } else { if constexpr (debug_shaders == true) { - std::cout << "Successfully compiled a " << mplot::gl::shader_type_str(entry.type) << " shader!\n"; + std::cout << "Compiling this shader: \n" << "-----\n"; + std::cout << source.get() << "-----\n"; } - glfn->AttachShader (program, shader); - glfn->DeleteShader (shader); // Note it's correct to glDeleteShader after attaching it to program + } + GLint slen = (GLint)std::strlen (source.get()); + const GLchar* sptr = source.get(); + glfn->ShaderSource (shader, 1, &sptr, &slen); + glfn->CompileShader (shader); + GLint shaderCompileSuccess = GL_FALSE; + char infoLog[512]; + glfn->GetShaderiv(shader, GL_COMPILE_STATUS, &shaderCompileSuccess); + if (!shaderCompileSuccess) { + glfn->GetShaderInfoLog(shader, 512, NULL, infoLog); + std::cerr << "\nShader compilation failed!"; + std::cerr << "\n--------------------------\n\n"; + std::cerr << source.get(); + std::cerr << "\n\n--------------------------\n"; + std::cerr << infoLog << std::endl; + std::cerr << "Exiting.\n"; + exit (2); } - GLint linked = 0; - glfn->LinkProgram (program); - glfn->GetProgramiv (program, GL_LINK_STATUS, &linked); - if (!linked) { - GLsizei len = 0; - glfn->GetProgramiv (program, GL_INFO_LOG_LENGTH, &len); - { - std::unique_ptr log = std::make_unique(len+1); - glfn->GetProgramInfoLog (program, len, &len, log.get()); - std::cerr << "Shader linking failed: " << log.get() << std::endl << "Exiting.\n"; - } - glfn->DeleteProgram (program); - exit (5); - } // else successfully linked + // Test glGetError: + GLenum shaderError = glfn->GetError(); + if (shaderError == GL_INVALID_VALUE) { + std::cerr << "Shader compilation resulted in GL_INVALID_VALUE\n"; + exit (3); + } else if (shaderError == GL_INVALID_OPERATION) { + std::cerr << "Shader compilation resulted in GL_INVALID_OPERATION\n"; + exit (4); + } // shaderError is 0 - return program; + if constexpr (debug_shaders == true) { + std::cout << "Successfully compiled a " << mplot::gl::shader_type_str(entry.type) << " shader!\n"; + } + glfn->AttachShader (program, shader); + glfn->DeleteShader (shader); // Note it's correct to glDeleteShader after attaching it to program } - } // namespace gl + + GLint linked = 0; + glfn->LinkProgram (program); + glfn->GetProgramiv (program, GL_LINK_STATUS, &linked); + if (!linked) { + GLsizei len = 0; + glfn->GetProgramiv (program, GL_INFO_LOG_LENGTH, &len); + { + std::unique_ptr log = std::make_unique(len+1); + glfn->GetProgramInfoLog (program, len, &len, log.get()); + std::cerr << "Shader linking failed: " << log.get() << std::endl << "Exiting.\n"; + } + glfn->DeleteProgram (program); + exit (5); + } // else successfully linked + + return program; + } } // namespace diff --git a/mplot/gl/loadshaders_nomx.h b/mplot/gl/loadshaders_nomx.h index c7401ac3..6f166ebb 100644 --- a/mplot/gl/loadshaders_nomx.h +++ b/mplot/gl/loadshaders_nomx.h @@ -12,111 +12,108 @@ #include #include -namespace mplot { +namespace mplot::gl +{ + //! Shader loading code. + GLuint LoadShaders (const std::vector& shader_info) + { + if (shader_info.empty()) { return 0; } - namespace gl { - - //! Shader loading code. - GLuint LoadShaders (const std::vector& shader_info) - { - if (shader_info.empty()) { return 0; } - - GLuint program = glCreateProgram(); + GLuint program = glCreateProgram(); #ifdef GL_SHADER_COMPILER - GLboolean shaderCompilerPresent = GL_FALSE; - glGetBooleanv (GL_SHADER_COMPILER, &shaderCompilerPresent); - if (shaderCompilerPresent == GL_FALSE) { - std::cerr << "Shader compiler NOT present!\n"; - } else { - if constexpr (debug_shaders == true) { - std::cout << "Shader compiler present\n"; - } + GLboolean shaderCompilerPresent = GL_FALSE; + glGetBooleanv (GL_SHADER_COMPILER, &shaderCompilerPresent); + if (shaderCompilerPresent == GL_FALSE) { + std::cerr << "Shader compiler NOT present!\n"; + } else { + if constexpr (debug_shaders == true) { + std::cout << "Shader compiler present\n"; } + } #endif - for (auto entry : shader_info) { - GLuint shader = glCreateShader (entry.type); - entry.shader = shader; - // Test entry.filename. If this GLSL file can be read, then do so, otherwise, - // compile the default version specified in the ShaderInfo - std::unique_ptr source; + for (auto entry : shader_info) { + GLuint shader = glCreateShader (entry.type); + entry.shader = shader; + // Test entry.filename. If this GLSL file can be read, then do so, otherwise, + // compile the default version specified in the ShaderInfo + std::unique_ptr source; + if constexpr (debug_shaders == true) { + std::cout << "Check file exists for " << entry.filename << std::endl; + } + if (mplot::tools::fileExists (entry.filename)) { + std::cout << "Using " << mplot::gl::shader_type_str(entry.type) + << " shader from the file " << entry.filename << std::endl; + source = mplot::gl::ReadShader (entry.filename); + } else { if constexpr (debug_shaders == true) { - std::cout << "Check file exists for " << entry.filename << std::endl; - } - if (mplot::tools::fileExists (entry.filename)) { - std::cout << "Using " << mplot::gl::shader_type_str(entry.type) - << " shader from the file " << entry.filename << std::endl; - source = mplot::gl::ReadShader (entry.filename); - } else { - if constexpr (debug_shaders == true) { - std::cout << "Using compiled-in " << mplot::gl::shader_type_str(entry.type) << " shader\n"; - } - source = mplot::gl::ReadDefaultShader (entry.compiledIn); - } - if (source == nullptr) { - for (auto entry : shader_info) { - glDeleteShader (entry.shader); - entry.shader = 0; - } - return 0; - - } else { - if constexpr (debug_shaders == true) { - std::cout << "Compiling this shader: \n" << "-----\n"; - std::cout << source.get() << "-----\n"; - } + std::cout << "Using compiled-in " << mplot::gl::shader_type_str(entry.type) << " shader\n"; } - GLint slen = (GLint)strlen (source.get()); - const GLchar* sptr = source.get(); - glShaderSource (shader, 1, &sptr, &slen); - glCompileShader (shader); - GLint shaderCompileSuccess = GL_FALSE; - char infoLog[512]; - glGetShaderiv(shader, GL_COMPILE_STATUS, &shaderCompileSuccess); - if (!shaderCompileSuccess) { - glGetShaderInfoLog(shader, 512, NULL, infoLog); - std::cerr << "\nShader compilation failed!"; - std::cerr << "\n--------------------------\n\n"; - std::cerr << source.get(); - std::cerr << "\n\n--------------------------\n"; - std::cerr << infoLog << std::endl; - std::cerr << "Exiting.\n"; - exit (2); + source = mplot::gl::ReadDefaultShader (entry.compiledIn); + } + if (source == nullptr) { + for (auto entry : shader_info) { + glDeleteShader (entry.shader); + entry.shader = 0; } + return 0; - // Test glGetError: - GLenum shaderError = glGetError(); - if (shaderError == GL_INVALID_VALUE) { - std::cerr << "Shader compilation resulted in GL_INVALID_VALUE\n"; - exit (3); - } else if (shaderError == GL_INVALID_OPERATION) { - std::cerr << "Shader compilation resulted in GL_INVALID_OPERATION\n"; - exit (4); - } // shaderError is 0 - + } else { if constexpr (debug_shaders == true) { - std::cout << "Successfully compiled a " << mplot::gl::shader_type_str(entry.type) << " shader!\n"; + std::cout << "Compiling this shader: \n" << "-----\n"; + std::cout << source.get() << "-----\n"; } - glAttachShader (program, shader); - glDeleteShader (shader); // Note it's correct to glDeleteShader after attaching it to program + } + GLint slen = (GLint)strlen (source.get()); + const GLchar* sptr = source.get(); + glShaderSource (shader, 1, &sptr, &slen); + glCompileShader (shader); + GLint shaderCompileSuccess = GL_FALSE; + char infoLog[512]; + glGetShaderiv(shader, GL_COMPILE_STATUS, &shaderCompileSuccess); + if (!shaderCompileSuccess) { + glGetShaderInfoLog(shader, 512, NULL, infoLog); + std::cerr << "\nShader compilation failed!"; + std::cerr << "\n--------------------------\n\n"; + std::cerr << source.get(); + std::cerr << "\n\n--------------------------\n"; + std::cerr << infoLog << std::endl; + std::cerr << "Exiting.\n"; + exit (2); } - GLint linked = 0; - glLinkProgram (program); - glGetProgramiv (program, GL_LINK_STATUS, &linked); - if (!linked) { - GLsizei len = 0; - glGetProgramiv (program, GL_INFO_LOG_LENGTH, &len); - { - std::unique_ptr log = std::make_unique(len+1); - glGetProgramInfoLog (program, len, &len, log.get()); - std::cerr << "Shader linking failed: " << log.get() << std::endl << "Exiting.\n"; - } - glDeleteProgram (program); - exit (5); - } // else successfully linked + // Test glGetError: + GLenum shaderError = glGetError(); + if (shaderError == GL_INVALID_VALUE) { + std::cerr << "Shader compilation resulted in GL_INVALID_VALUE\n"; + exit (3); + } else if (shaderError == GL_INVALID_OPERATION) { + std::cerr << "Shader compilation resulted in GL_INVALID_OPERATION\n"; + exit (4); + } // shaderError is 0 - return program; + if constexpr (debug_shaders == true) { + std::cout << "Successfully compiled a " << mplot::gl::shader_type_str(entry.type) << " shader!\n"; + } + glAttachShader (program, shader); + glDeleteShader (shader); // Note it's correct to glDeleteShader after attaching it to program } - } // namespace gl + + GLint linked = 0; + glLinkProgram (program); + glGetProgramiv (program, GL_LINK_STATUS, &linked); + if (!linked) { + GLsizei len = 0; + glGetProgramiv (program, GL_INFO_LOG_LENGTH, &len); + { + std::unique_ptr log = std::make_unique(len+1); + glGetProgramInfoLog (program, len, &len, log.get()); + std::cerr << "Shader linking failed: " << log.get() << std::endl << "Exiting.\n"; + } + glDeleteProgram (program); + exit (5); + } // else successfully linked + + return program; + } } // namespace diff --git a/mplot/gl/shaders.h b/mplot/gl/shaders.h index 73f0b766..e98258e2 100644 --- a/mplot/gl/shaders.h +++ b/mplot/gl/shaders.h @@ -16,84 +16,81 @@ #include #include -namespace mplot { +namespace mplot::gl +{ + /*! + * Data structure for shader info. + * + * LoadShaders() takes an array of ShaderFile structures, each of which contains the + * type of the shader, and a pointer a C-style character string (i.e., a + * NULL-terminated array of characters) containing the filename of a GLSL file to + * use, and another pointer to the compiled-in version of the shader. + * + * The array of structures is terminated by a final Shader with + * the "type" field set to GL_NONE. + * + * LoadShaders() returns the shader program value (as returned by + * glCreateProgram()) on success, or zero on failure. + */ + struct ShaderInfo + { + // GLenum is, in practice, a 32 bit unsigned int. The type appears not to be defined in + // OpenGL 3.1 ES (though it does appear in 3.2 ES), so here I use unsigned int. + unsigned int type; // rather than GLenum + std::string filename; + std::string compiledIn; + GLuint shader; + }; - namespace gl { + // To enable debugging, set true. + const bool debug_shaders = false; - /*! - * Data structure for shader info. - * - * LoadShaders() takes an array of ShaderFile structures, each of which contains the - * type of the shader, and a pointer a C-style character string (i.e., a - * NULL-terminated array of characters) containing the filename of a GLSL file to - * use, and another pointer to the compiled-in version of the shader. - * - * The array of structures is terminated by a final Shader with - * the "type" field set to GL_NONE. - * - * LoadShaders() returns the shader program value (as returned by - * glCreateProgram()) on success, or zero on failure. - */ - struct ShaderInfo - { - // GLenum is, in practice, a 32 bit unsigned int. The type appears not to be defined in - // OpenGL 3.1 ES (though it does appear in 3.2 ES), so here I use unsigned int. - unsigned int type; // rather than GLenum - std::string filename; - std::string compiledIn; - GLuint shader; - }; - - // To enable debugging, set true. - const bool debug_shaders = false; - - //! Read a shader from a file. - std::unique_ptr ReadShader (const std::string& filename) - { - if (!std::filesystem::is_regular_file (filename)) { // restrict to regular files - std::cerr << "'" << filename << "' is not a regular file\n"; - return nullptr; - } - size_t len = std::filesystem::file_size (filename); - std::unique_ptr source = std::make_unique(len + 1); - std::ifstream fin (filename.c_str(), std::ios::in); - if (!fin.is_open()) { - std::cerr << "Unable to open file '" << filename << "'\n"; - return nullptr; - } - if (!fin.eof()) { fin.read (source.get(), len); } - source[len] = 0; - return source; + //! Read a shader from a file. + std::unique_ptr ReadShader (const std::string& filename) + { + if (!std::filesystem::is_regular_file (filename)) { // restrict to regular files + std::cerr << "'" << filename << "' is not a regular file\n"; + return nullptr; } - - /*! - * Read a default shader, stored as a const char*. ReadDefaultShader reads a - * file: allocates some memory, copies the text into the new memory and then - * returns a GLchar* pointer to the memory. - */ - std::unique_ptr ReadDefaultShader (const std::string& shadercontent) - { - std::size_t len = shadercontent.size(); - std::unique_ptr source = std::make_unique(len + 1); - std::memcpy (static_cast(source.get()), static_cast(shadercontent.c_str()), len); - source[len] = 0; - return source; + size_t len = std::filesystem::file_size (filename); + std::unique_ptr source = std::make_unique(len + 1); + std::ifstream fin (filename.c_str(), std::ios::in); + if (!fin.is_open()) { + std::cerr << "Unable to open file '" << filename << "'\n"; + return nullptr; } + if (!fin.eof()) { fin.read (source.get(), len); } + source[len] = 0; + return source; + } + + /*! + * Read a default shader, stored as a const char*. ReadDefaultShader reads a + * file: allocates some memory, copies the text into the new memory and then + * returns a GLchar* pointer to the memory. + */ + std::unique_ptr ReadDefaultShader (const std::string& shadercontent) + { + std::size_t len = shadercontent.size(); + std::unique_ptr source = std::make_unique(len + 1); + std::memcpy (static_cast(source.get()), static_cast(shadercontent.c_str()), len); + source[len] = 0; + return source; + } - std::string shader_type_str (GLuint shader_type) - { - std::string type("unknown"); - if (shader_type == GL_VERTEX_SHADER) { - type = "vertex"; - } else if (shader_type == GL_FRAGMENT_SHADER) { - type = "fragment"; + std::string shader_type_str (GLuint shader_type) + { + std::string type("unknown"); + if (shader_type == GL_VERTEX_SHADER) { + type = "vertex"; + } else if (shader_type == GL_FRAGMENT_SHADER) { + type = "fragment"; #ifdef GL_COMPUTE_SHADER - } else if (shader_type == GL_COMPUTE_SHADER) { - type = "compute"; + } else if (shader_type == GL_COMPUTE_SHADER) { + type = "compute"; #endif - } - return type; } + return type; + } - } // namespace gl } // namespace diff --git a/mplot/gl/ssbo.h b/mplot/gl/ssbo.h index 07070689..6a7e83a9 100644 --- a/mplot/gl/ssbo.h +++ b/mplot/gl/ssbo.h @@ -15,150 +15,52 @@ #include #include -namespace mplot { - namespace gl { - - // An SSBO and its data - // @tparam index: The index of the buffer, used in the GLSL - // @tparam T: The type of the data in the SSBO - // @tparam N: The number of elements of type T in the SSBO - template // Could add version template params if necessary, to select correct gl function calls - struct ssbo +namespace mplot::gl +{ + // An SSBO and its data + // @tparam index: The index of the buffer, used in the GLSL + // @tparam T: The type of the data in the SSBO + // @tparam N: The number of elements of type T in the SSBO + template // Could add version template params if necessary, to select correct gl function calls + struct ssbo + { + // The name of the buffer, generated with glGenBuffers() + unsigned int name = 0; + // The CPU-side data for the buffer + sm::vec data; + + ssbo() {} + ~ssbo() {} + + // Init is not built into the constructor, as client code must ensure there is an OpenGL context available + void init() { - // The name of the buffer, generated with glGenBuffers() - unsigned int name = 0; - // The CPU-side data for the buffer - sm::vec data; - - ssbo() {} - ~ssbo() {} - - // Init is not built into the constructor, as client code must ensure there is an OpenGL context available - void init() - { - glGenBuffers (1, &this->name); - this->copy_to_gpu(); - } - - // Copy the data in the sm::vec data over to the GPU - void copy_to_gpu() - { - glBindBufferBase (GL_SHADER_STORAGE_BUFFER, index, this->name); - mplot::gl::Util::checkError (__FILE__, __LINE__); - glBufferData (GL_SHADER_STORAGE_BUFFER, N * sizeof(T), this->data.data(), GL_STATIC_DRAW); - mplot::gl::Util::checkError (__FILE__, __LINE__); - glBindBuffer (GL_SHADER_STORAGE_BUFFER, 0); - mplot::gl::Util::checkError (__FILE__, __LINE__); - } - - // Map the GPU memory to CPU space, then copy the values into this->data. NB: it's a - // performance hit to *copy* to the mapped data to our sm::vec, because the data is - // *already in CPU accessible memory* after glMapBufferRange(). - // However, in case you need it, here it is. - void copy_from_gpu() - { - glBindBufferBase (GL_SHADER_STORAGE_BUFFER, index, this->name); - mplot::gl::Util::checkError (__FILE__, __LINE__); - T* cpuptr = static_cast(glMapBufferRange (GL_SHADER_STORAGE_BUFFER, 0, N*sizeof(T), GL_MAP_READ_BIT)); - mplot::gl::Util::checkError (__FILE__, __LINE__); - for (unsigned int i = 0; i < N; ++i) { this->data[i] = cpuptr[i]; } - glUnmapBuffer (GL_SHADER_STORAGE_BUFFER); - glBindBuffer (GL_SHADER_STORAGE_BUFFER, 0); - mplot::gl::Util::checkError (__FILE__, __LINE__); - } - - // Find the range of the data in the given Shader Storage Buffer Object - // - // ssbo_idx: The Index of the Shader Storage Buffer Object that we're reading from - // ssbo_name: The name (really a number) of the Shader Storage Buffer Object that we're reading from - // ssbo_num_elements: The number of elements of type T in the SSBO. - sm::range get_range() - { - sm::range r; - r.search_init(); - glBindBufferBase (GL_SHADER_STORAGE_BUFFER, index, this->name); - mplot::gl::Util::checkError (__FILE__, __LINE__); - T* cpuptr = static_cast(glMapBufferRange (GL_SHADER_STORAGE_BUFFER, 0, N*sizeof(T), GL_MAP_READ_BIT)); - mplot::gl::Util::checkError (__FILE__, __LINE__); - for (unsigned int i = 0; i < N; ++i) { r.update (cpuptr[i]); } - glUnmapBuffer (GL_SHADER_STORAGE_BUFFER); - glBindBuffer (GL_SHADER_STORAGE_BUFFER, 0); - mplot::gl::Util::checkError (__FILE__, __LINE__); - return r; - } - }; - - // Set up a Shader Storage Buffer Object (SSBO) and buffer data into it (from a sm::vvec) - template - void setup_ssbo (const GLuint target_index, unsigned int& ssbo_id, const sm::vvec& data) - { - glGenBuffers (1, &ssbo_id); - glBindBufferBase (GL_SHADER_STORAGE_BUFFER, target_index, ssbo_id); - // Mutable, re-locatable storage: - glBufferData (GL_SHADER_STORAGE_BUFFER, data.size() * sizeof(T), data.data(), GL_STATIC_DRAW); - // Immutable storage would be: - // void glBufferStorage(GLenum target​, GLsizeiptr size​, const GLvoid * data​, GLbitfield flags​); - //glBufferStorage (GL_SHADER_STORAGE_BUFFER, data.size() * sizeof(T), data.data(), GL_CLIENT_STORAGE_BIT | GL_MAP_READ_BIT); - glBindBuffer (GL_SHADER_STORAGE_BUFFER, 0); - mplot::gl::Util::checkError (__FILE__, __LINE__); + glGenBuffers (1, &this->name); + this->copy_to_gpu(); } - // Set up a Shader Storage Buffer Object (SSBO) and buffer data into it (sm::vec version) - template - void setup_ssbo (const GLuint target_index, unsigned int& ssbo_id, const sm::vec& data) + // Copy the data in the sm::vec data over to the GPU + void copy_to_gpu() { - glGenBuffers (1, &ssbo_id); - glBindBufferBase (GL_SHADER_STORAGE_BUFFER, target_index, ssbo_id); - glBufferData (GL_SHADER_STORAGE_BUFFER, N * sizeof(T), data.data(), GL_STATIC_DRAW); - glBindBuffer (GL_SHADER_STORAGE_BUFFER, 0); + glBindBufferBase (GL_SHADER_STORAGE_BUFFER, index, this->name); mplot::gl::Util::checkError (__FILE__, __LINE__); - } - - // Copy data to an existing SSBO - template - void copy_vvec_to_ssbo (const GLuint target_index, const unsigned int ssbo_id, const sm::vvec& data) - { - glBindBufferBase (GL_SHADER_STORAGE_BUFFER, target_index, ssbo_id); - glBufferData (GL_SHADER_STORAGE_BUFFER, data.size() * sizeof(T), data.data(), GL_STATIC_DRAW); - glBindBuffer (GL_SHADER_STORAGE_BUFFER, 0); + glBufferData (GL_SHADER_STORAGE_BUFFER, N * sizeof(T), this->data.data(), GL_STATIC_DRAW); mplot::gl::Util::checkError (__FILE__, __LINE__); - } - - template - void copy_vvec_to_ssbo (const GLuint target_index, const unsigned int ssbo_id, const sm::vvec& data) - { - glBindBufferBase (GL_SHADER_STORAGE_BUFFER, target_index, ssbo_id); - glBufferData (GL_SHADER_STORAGE_BUFFER, N * sizeof(T), data.data(), GL_STATIC_DRAW); glBindBuffer (GL_SHADER_STORAGE_BUFFER, 0); mplot::gl::Util::checkError (__FILE__, __LINE__); } - // Map the SSBO to cpu space, then make a copy of the data into a passed-in vvec. - // - // ssbo_idx: The Index of the Shader Storage Buffer Object that we're reading from - // ssbo_name: The name (really a number) of the Shader Storage Buffer Object that we're reading from - // cpu_data: A vvec of the right size to receive the data in the SSBO into 'CPU accessible memory' - template - void ssbo_copy_to_vvec (const unsigned int ssbo_idx, const unsigned int ssbo_name, sm::vvec& cpu_side) + // Map the GPU memory to CPU space, then copy the values into this->data. NB: it's a + // performance hit to *copy* to the mapped data to our sm::vec, because the data is + // *already in CPU accessible memory* after glMapBufferRange(). + // However, in case you need it, here it is. + void copy_from_gpu() { - glBindBufferBase (GL_SHADER_STORAGE_BUFFER, ssbo_idx, ssbo_name); - // Really, it's crazy to *copy* because the data is *already in CPU - // accessible memory* after glMapBufferRange. BUT here's the copy: - T* cpuptr = static_cast(glMapBufferRange (GL_SHADER_STORAGE_BUFFER, 0, cpu_side.size()*sizeof(T), GL_MAP_READ_BIT)); - for (unsigned int i = 0; i < cpu_side.size(); ++i) { cpu_side[i] = cpuptr[i]; } - glUnmapBuffer (GL_SHADER_STORAGE_BUFFER); - glBindBuffer (GL_SHADER_STORAGE_BUFFER, 0); + glBindBufferBase (GL_SHADER_STORAGE_BUFFER, index, this->name); mplot::gl::Util::checkError (__FILE__, __LINE__); - } - - template - void ssbo_copy_to_vec (const unsigned int ssbo_idx, const unsigned int ssbo_name, sm::vec& cpu_side) - { - glBindBufferBase (GL_SHADER_STORAGE_BUFFER, ssbo_idx, ssbo_name); - // Really, it's crazy to *copy* because the data is *already in CPU - // accessible memory* after glMapBufferRange. BUT here's the copy: T* cpuptr = static_cast(glMapBufferRange (GL_SHADER_STORAGE_BUFFER, 0, N*sizeof(T), GL_MAP_READ_BIT)); - for (unsigned int i = 0; i < N; ++i) { cpu_side[i] = cpuptr[i]; } + mplot::gl::Util::checkError (__FILE__, __LINE__); + for (unsigned int i = 0; i < N; ++i) { this->data[i] = cpuptr[i]; } glUnmapBuffer (GL_SHADER_STORAGE_BUFFER); glBindBuffer (GL_SHADER_STORAGE_BUFFER, 0); mplot::gl::Util::checkError (__FILE__, __LINE__); @@ -169,19 +71,115 @@ namespace mplot { // ssbo_idx: The Index of the Shader Storage Buffer Object that we're reading from // ssbo_name: The name (really a number) of the Shader Storage Buffer Object that we're reading from // ssbo_num_elements: The number of elements of type T in the SSBO. - template - sm::range ssbo_get_range (const unsigned int ssbo_idx, const unsigned int ssbo_name, const unsigned int ssbo_num_elements) + sm::range get_range() { sm::range r; r.search_init(); - glBindBufferBase (GL_SHADER_STORAGE_BUFFER, ssbo_idx, ssbo_name); - T* cpuptr = static_cast(glMapBufferRange (GL_SHADER_STORAGE_BUFFER, 0, ssbo_num_elements*sizeof(T), GL_MAP_READ_BIT)); - for (unsigned int i = 0; i < ssbo_num_elements; ++i) { r.update (cpuptr[i]); } + glBindBufferBase (GL_SHADER_STORAGE_BUFFER, index, this->name); + mplot::gl::Util::checkError (__FILE__, __LINE__); + T* cpuptr = static_cast(glMapBufferRange (GL_SHADER_STORAGE_BUFFER, 0, N*sizeof(T), GL_MAP_READ_BIT)); + mplot::gl::Util::checkError (__FILE__, __LINE__); + for (unsigned int i = 0; i < N; ++i) { r.update (cpuptr[i]); } glUnmapBuffer (GL_SHADER_STORAGE_BUFFER); glBindBuffer (GL_SHADER_STORAGE_BUFFER, 0); mplot::gl::Util::checkError (__FILE__, __LINE__); return r; } - - } // gl -} // mplot + }; + + // Set up a Shader Storage Buffer Object (SSBO) and buffer data into it (from a sm::vvec) + template + void setup_ssbo (const GLuint target_index, unsigned int& ssbo_id, const sm::vvec& data) + { + glGenBuffers (1, &ssbo_id); + glBindBufferBase (GL_SHADER_STORAGE_BUFFER, target_index, ssbo_id); + // Mutable, re-locatable storage: + glBufferData (GL_SHADER_STORAGE_BUFFER, data.size() * sizeof(T), data.data(), GL_STATIC_DRAW); + // Immutable storage would be: + // void glBufferStorage(GLenum target​, GLsizeiptr size​, const GLvoid * data​, GLbitfield flags​); + //glBufferStorage (GL_SHADER_STORAGE_BUFFER, data.size() * sizeof(T), data.data(), GL_CLIENT_STORAGE_BIT | GL_MAP_READ_BIT); + glBindBuffer (GL_SHADER_STORAGE_BUFFER, 0); + mplot::gl::Util::checkError (__FILE__, __LINE__); + } + + // Set up a Shader Storage Buffer Object (SSBO) and buffer data into it (sm::vec version) + template + void setup_ssbo (const GLuint target_index, unsigned int& ssbo_id, const sm::vec& data) + { + glGenBuffers (1, &ssbo_id); + glBindBufferBase (GL_SHADER_STORAGE_BUFFER, target_index, ssbo_id); + glBufferData (GL_SHADER_STORAGE_BUFFER, N * sizeof(T), data.data(), GL_STATIC_DRAW); + glBindBuffer (GL_SHADER_STORAGE_BUFFER, 0); + mplot::gl::Util::checkError (__FILE__, __LINE__); + } + + // Copy data to an existing SSBO + template + void copy_vvec_to_ssbo (const GLuint target_index, const unsigned int ssbo_id, const sm::vvec& data) + { + glBindBufferBase (GL_SHADER_STORAGE_BUFFER, target_index, ssbo_id); + glBufferData (GL_SHADER_STORAGE_BUFFER, data.size() * sizeof(T), data.data(), GL_STATIC_DRAW); + glBindBuffer (GL_SHADER_STORAGE_BUFFER, 0); + mplot::gl::Util::checkError (__FILE__, __LINE__); + } + + template + void copy_vvec_to_ssbo (const GLuint target_index, const unsigned int ssbo_id, const sm::vvec& data) + { + glBindBufferBase (GL_SHADER_STORAGE_BUFFER, target_index, ssbo_id); + glBufferData (GL_SHADER_STORAGE_BUFFER, N * sizeof(T), data.data(), GL_STATIC_DRAW); + glBindBuffer (GL_SHADER_STORAGE_BUFFER, 0); + mplot::gl::Util::checkError (__FILE__, __LINE__); + } + + // Map the SSBO to cpu space, then make a copy of the data into a passed-in vvec. + // + // ssbo_idx: The Index of the Shader Storage Buffer Object that we're reading from + // ssbo_name: The name (really a number) of the Shader Storage Buffer Object that we're reading from + // cpu_data: A vvec of the right size to receive the data in the SSBO into 'CPU accessible memory' + template + void ssbo_copy_to_vvec (const unsigned int ssbo_idx, const unsigned int ssbo_name, sm::vvec& cpu_side) + { + glBindBufferBase (GL_SHADER_STORAGE_BUFFER, ssbo_idx, ssbo_name); + // Really, it's crazy to *copy* because the data is *already in CPU + // accessible memory* after glMapBufferRange. BUT here's the copy: + T* cpuptr = static_cast(glMapBufferRange (GL_SHADER_STORAGE_BUFFER, 0, cpu_side.size()*sizeof(T), GL_MAP_READ_BIT)); + for (unsigned int i = 0; i < cpu_side.size(); ++i) { cpu_side[i] = cpuptr[i]; } + glUnmapBuffer (GL_SHADER_STORAGE_BUFFER); + glBindBuffer (GL_SHADER_STORAGE_BUFFER, 0); + mplot::gl::Util::checkError (__FILE__, __LINE__); + } + + template + void ssbo_copy_to_vec (const unsigned int ssbo_idx, const unsigned int ssbo_name, sm::vec& cpu_side) + { + glBindBufferBase (GL_SHADER_STORAGE_BUFFER, ssbo_idx, ssbo_name); + // Really, it's crazy to *copy* because the data is *already in CPU + // accessible memory* after glMapBufferRange. BUT here's the copy: + T* cpuptr = static_cast(glMapBufferRange (GL_SHADER_STORAGE_BUFFER, 0, N*sizeof(T), GL_MAP_READ_BIT)); + for (unsigned int i = 0; i < N; ++i) { cpu_side[i] = cpuptr[i]; } + glUnmapBuffer (GL_SHADER_STORAGE_BUFFER); + glBindBuffer (GL_SHADER_STORAGE_BUFFER, 0); + mplot::gl::Util::checkError (__FILE__, __LINE__); + } + + // Find the range of the data in the given Shader Storage Buffer Object + // + // ssbo_idx: The Index of the Shader Storage Buffer Object that we're reading from + // ssbo_name: The name (really a number) of the Shader Storage Buffer Object that we're reading from + // ssbo_num_elements: The number of elements of type T in the SSBO. + template + sm::range ssbo_get_range (const unsigned int ssbo_idx, const unsigned int ssbo_name, const unsigned int ssbo_num_elements) + { + sm::range r; + r.search_init(); + glBindBufferBase (GL_SHADER_STORAGE_BUFFER, ssbo_idx, ssbo_name); + T* cpuptr = static_cast(glMapBufferRange (GL_SHADER_STORAGE_BUFFER, 0, ssbo_num_elements*sizeof(T), GL_MAP_READ_BIT)); + for (unsigned int i = 0; i < ssbo_num_elements; ++i) { r.update (cpuptr[i]); } + glUnmapBuffer (GL_SHADER_STORAGE_BUFFER); + glBindBuffer (GL_SHADER_STORAGE_BUFFER, 0); + mplot::gl::Util::checkError (__FILE__, __LINE__); + return r; + } + +} // mplot::gl diff --git a/mplot/gl/texture.h b/mplot/gl/texture.h index 0fa77fe1..16e3d5c7 100644 --- a/mplot/gl/texture.h +++ b/mplot/gl/texture.h @@ -14,168 +14,166 @@ #include #include -namespace mplot { - namespace gl { - - // Set up a single texture suitable for filling with values within the - // compute shader. Note: fixed format of GL_RGBA and GL_FLOAT; could set these - // with template params. - void setup_texture (const GLuint image_texture_unit, unsigned int& texture_id, sm::vec dims) - { - glGenTextures (1, &texture_id); // generate a texture name and place it in texture_id - // Bind a texture (GL_TEXTURE_2D) to the texture name +namespace mplot::gl +{ + // Set up a single texture suitable for filling with values within the + // compute shader. Note: fixed format of GL_RGBA and GL_FLOAT; could set these + // with template params. + void setup_texture (const GLuint image_texture_unit, unsigned int& texture_id, sm::vec dims) + { + glGenTextures (1, &texture_id); // generate a texture name and place it in texture_id + // Bind a texture (GL_TEXTURE_2D) to the texture name + glBindTexture (GL_TEXTURE_2D, texture_id); + // Set some parameters for the texture + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + // In 3.1 ES, GL_INVALID_OPERATION is generated by glBindImageTexture if texture_id is not the name of + // an *immutable* texture object. Calling glTexStorage2D seems to create an immutable texture object. + glTexStorage2D (GL_TEXTURE_2D, 1, GL_RGBA32F, dims[0], dims[1]); + mplot::gl::Util::checkError (__FILE__, __LINE__); + glBindImageTexture (image_texture_unit, texture_id, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F); + mplot::gl::Util::checkError (__FILE__, __LINE__); + } + + // Set up a shader-read-only texture with the provided rgb image data + template + void setup_texture (const GLuint image_texture_unit, unsigned int& texture_id, + sm::vec dims, float* rgb_data) + { + if constexpr (gles == false) { + // This may not be perfect, but seemed to work with a non-GLES context + glGenTextures (1, &texture_id); glBindTexture (GL_TEXTURE_2D, texture_id); - // Set some parameters for the texture + // Because we WRITING image data to this texture, we HAVE TO gtActiveTexture(): + glActiveTexture (GL_TEXTURE0+image_texture_unit); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - // In 3.1 ES, GL_INVALID_OPERATION is generated by glBindImageTexture if texture_id is not the name of - // an *immutable* texture object. Calling glTexStorage2D seems to create an immutable texture object. - glTexStorage2D (GL_TEXTURE_2D, 1, GL_RGBA32F, dims[0], dims[1]); - mplot::gl::Util::checkError (__FILE__, __LINE__); - glBindImageTexture (image_texture_unit, texture_id, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F); + /////////////////////////////// internal format pixel format + glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA32F, dims[0], dims[1], 0, GL_RGB, GL_FLOAT, rgb_data); + glBindImageTexture (image_texture_unit, texture_id, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA32F); mplot::gl::Util::checkError (__FILE__, __LINE__); + } else { + throw std::runtime_error ("Fix setup_texture (const GLuint, unsigned int&, sm::vec, float* rgb_data) to work on OpenGL ES"); } - - // Set up a shader-read-only texture with the provided rgb image data - template - void setup_texture (const GLuint image_texture_unit, unsigned int& texture_id, - sm::vec dims, float* rgb_data) - { - if constexpr (gles == false) { - // This may not be perfect, but seemed to work with a non-GLES context - glGenTextures (1, &texture_id); - glBindTexture (GL_TEXTURE_2D, texture_id); - // Because we WRITING image data to this texture, we HAVE TO gtActiveTexture(): - glActiveTexture (GL_TEXTURE0+image_texture_unit); - glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - /////////////////////////////// internal format pixel format - glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA32F, dims[0], dims[1], 0, GL_RGB, GL_FLOAT, rgb_data); - glBindImageTexture (image_texture_unit, texture_id, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA32F); - mplot::gl::Util::checkError (__FILE__, __LINE__); - } else { - throw std::runtime_error ("Fix setup_texture (const GLuint, unsigned int&, sm::vec, float* rgb_data) to work on OpenGL ES"); - } - } + } #ifdef I_HAD_FIGURED_OUT_SETUP_TEXTURE_WITH_DATA_PROPERLY # define USE_IMMUTABLE_STORAGE 1 // Should use immutable texture storage in order to use glBindImageTexture - // Set up a shader-read-only texture with the provided rgb image data. - // Just can't figure out how to make this work in GL 3.1 ES! - void setup_texture (const GLuint image_texture_unit, unsigned int& texture_id, - sm::vec dims, float* rgb_data) - { - std::cout << "setup_texture for READ_ONLY access of an image in shader\n"; + // Set up a shader-read-only texture with the provided rgb image data. + // Just can't figure out how to make this work in GL 3.1 ES! + void setup_texture (const GLuint image_texture_unit, unsigned int& texture_id, + sm::vec dims, float* rgb_data) + { + std::cout << "setup_texture for READ_ONLY access of an image in shader\n"; - glGenTextures (1, &texture_id); // Generates texture name, placing it in texture_id. - std::cout << "After glGenTextures, we have texture_id: " << texture_id - << " and image_texture_unit is " << image_texture_unit << std::endl; + glGenTextures (1, &texture_id); // Generates texture name, placing it in texture_id. + std::cout << "After glGenTextures, we have texture_id: " << texture_id + << " and image_texture_unit is " << image_texture_unit << std::endl; - // Bind a texture (GL_TEXTURE_2D) to the texture name - glBindTexture (GL_TEXTURE_2D, texture_id); + // Bind a texture (GL_TEXTURE_2D) to the texture name + glBindTexture (GL_TEXTURE_2D, texture_id); # ifndef USE_IMMUTABLE_STORAGE - // Because we WRITING image data to this texture, we HAVE TO glActiveTexture(): - glActiveTexture (GL_TEXTURE0+image_texture_unit); + // Because we WRITING image data to this texture, we HAVE TO glActiveTexture(): + glActiveTexture (GL_TEXTURE0+image_texture_unit); # endif - // Set some parameters - glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - mplot::gl::Util::checkError (__FILE__, __LINE__); + // Set some parameters + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + mplot::gl::Util::checkError (__FILE__, __LINE__); # ifndef USE_IMMUTABLE_STORAGE - // This creates a *mutable* texture containing rgb_data - glTexImage2D (GL_TEXTURE_2D, 0, GL_RGB32F, dims[0], dims[1], 0, GL_RGB, GL_FLOAT, rgb_data); + // This creates a *mutable* texture containing rgb_data + glTexImage2D (GL_TEXTURE_2D, 0, GL_RGB32F, dims[0], dims[1], 0, GL_RGB, GL_FLOAT, rgb_data); # else - // Create *immutable* storage like this, but I *don't know how to subsequently transfer the rgb_data to the texture*. - glTexStorage2D (GL_TEXTURE_2D, 1, GL_RGB32F, dims[0], dims[1]); + // Create *immutable* storage like this, but I *don't know how to subsequently transfer the rgb_data to the texture*. + glTexStorage2D (GL_TEXTURE_2D, 1, GL_RGB32F, dims[0], dims[1]); # endif - mplot::gl::Util::checkError (__FILE__, __LINE__); + mplot::gl::Util::checkError (__FILE__, __LINE__); - GLint imstatus; - glGetTexParameteriv (GL_TEXTURE_2D, GL_TEXTURE_IMMUTABLE_FORMAT, &imstatus); - std::cout << "IMMUTABLE_TEXTURE?: " << (imstatus?"Yes! immutable":"No, mutable") << std::endl; + GLint imstatus; + glGetTexParameteriv (GL_TEXTURE_2D, GL_TEXTURE_IMMUTABLE_FORMAT, &imstatus); + std::cout << "IMMUTABLE_TEXTURE?: " << (imstatus?"Yes! immutable":"No, mutable") << std::endl; # ifdef USE_IMMUTABLE_STORAGE - // Transferring/loading data has to do with glBindImageTexture (See the spec.) - - // GL_INVALID_VALUE if: - // "unit greater than or equal to the value of GL_MAX_IMAGE_UNITS." Well, unit is 4, GL_MAX_IMAGE_UNITS is 128 or 8. - // "level or layer is less than zero." Both are 0, below. - // "texture is not the name of an existing texture object" I filled texture_id with glGenTextures, above. - // So WHY DO I STILL GET GL_INVALID_VALUE????? - glBindImageTexture (image_texture_unit, texture_id, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGB32F); // GL_INVALID_VALUE - mplot::gl::Util::checkError (__FILE__, __LINE__); + // Transferring/loading data has to do with glBindImageTexture (See the spec.) + + // GL_INVALID_VALUE if: + // "unit greater than or equal to the value of GL_MAX_IMAGE_UNITS." Well, unit is 4, GL_MAX_IMAGE_UNITS is 128 or 8. + // "level or layer is less than zero." Both are 0, below. + // "texture is not the name of an existing texture object" I filled texture_id with glGenTextures, above. + // So WHY DO I STILL GET GL_INVALID_VALUE????? + glBindImageTexture (image_texture_unit, texture_id, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGB32F); // GL_INVALID_VALUE + mplot::gl::Util::checkError (__FILE__, __LINE__); # endif - } - - // Set up a shader-read-only texture with the provided rgb image data. This is an - // attempt to create one mutable texture, and an immutable one and copy the texture from - // the mutable to the immutable. Doesn't work. - void setup_texture_alt (const GLuint image_texture_unit, unsigned int& texture_id, - sm::vec dims, float* rgb_data) - { - std::cout << "setup_texture for READ_ONLY access of an image in shader\n"; - - unsigned int texture_id_tmp = 0; - glGenTextures (1, &texture_id_tmp); - - glGenTextures (1, &texture_id); // Generates texture name, placing it in texture_id. - std::cout << "After glGenTextures, we have texture_id: " << texture_id - << " and image_texture_unit is " << image_texture_unit << std::endl; - - GLuint image_texture_unit_tmp = image_texture_unit + 10; - - // Bind a texture (GL_TEXTURE_2D) to the texture name - glBindTexture (GL_TEXTURE_2D, texture_id_tmp); - mplot::gl::Util::checkError (__FILE__, __LINE__); + } - // Set some parameters for GL_TEXTURE_2D - glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - mplot::gl::Util::checkError (__FILE__, __LINE__); - - // Because we WRITING some image data to the temporary texture, we HAVE TO glActiveTexture(): - glActiveTexture (GL_TEXTURE0+image_texture_unit_tmp); - mplot::gl::Util::checkError (__FILE__, __LINE__); - // This creates a *mutable* texture containing rgb_data for the active texture - glTexImage2D (GL_TEXTURE_2D, 0, GL_RGB32F, dims[0], dims[1], 0, GL_RGB, GL_FLOAT, rgb_data); - mplot::gl::Util::checkError (__FILE__, __LINE__); - - // Switch to the other texture - glBindTexture (GL_TEXTURE_2D, texture_id); - mplot::gl::Util::checkError (__FILE__, __LINE__); - glActiveTexture (GL_TEXTURE0+image_texture_unit); - mplot::gl::Util::checkError (__FILE__, __LINE__); - - GLint imstatus; - glGetTexParameteriv (GL_TEXTURE_2D, GL_TEXTURE_IMMUTABLE_FORMAT, &imstatus); - std::cout << "IMMUTABLE_TEXTURE?: " << (imstatus?"Yes! immutable":"No, mutable") << std::endl; - - // Create *immutable* storage like this, but I *don't know how to subsequently transfer the rgb_data to the texture*. - glTexStorage2D (GL_TEXTURE_2D, 1, GL_RGB32F, dims[0], dims[1]); - mplot::gl::Util::checkError (__FILE__, __LINE__); - - // Transferring/loading data has to do with glBindImageTexture (See the spec.) - - // GL_INVALID_VALUE if: - // "unit greater than or equal to the value of GL_MAX_IMAGE_UNITS." Well, unit is 4, GL_MAX_IMAGE_UNITS is 128 or 8. - // "level or layer is less than zero." Both are 0, below. - // "texture is not the name of an existing texture object" I filled texture_id with glGenTextures, above. - // So WHY DO I STILL GET GL_INVALID_VALUE????? - glBindImageTexture (image_texture_unit_tmp, texture_id, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGB32F); // GL_INVALID_VALUE - mplot::gl::Util::checkError (__FILE__, __LINE__); - } + // Set up a shader-read-only texture with the provided rgb image data. This is an + // attempt to create one mutable texture, and an immutable one and copy the texture from + // the mutable to the immutable. Doesn't work. + void setup_texture_alt (const GLuint image_texture_unit, unsigned int& texture_id, + sm::vec dims, float* rgb_data) + { + std::cout << "setup_texture for READ_ONLY access of an image in shader\n"; + + unsigned int texture_id_tmp = 0; + glGenTextures (1, &texture_id_tmp); + + glGenTextures (1, &texture_id); // Generates texture name, placing it in texture_id. + std::cout << "After glGenTextures, we have texture_id: " << texture_id + << " and image_texture_unit is " << image_texture_unit << std::endl; + + GLuint image_texture_unit_tmp = image_texture_unit + 10; + + // Bind a texture (GL_TEXTURE_2D) to the texture name + glBindTexture (GL_TEXTURE_2D, texture_id_tmp); + mplot::gl::Util::checkError (__FILE__, __LINE__); + + // Set some parameters for GL_TEXTURE_2D + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + mplot::gl::Util::checkError (__FILE__, __LINE__); + + // Because we WRITING some image data to the temporary texture, we HAVE TO glActiveTexture(): + glActiveTexture (GL_TEXTURE0+image_texture_unit_tmp); + mplot::gl::Util::checkError (__FILE__, __LINE__); + // This creates a *mutable* texture containing rgb_data for the active texture + glTexImage2D (GL_TEXTURE_2D, 0, GL_RGB32F, dims[0], dims[1], 0, GL_RGB, GL_FLOAT, rgb_data); + mplot::gl::Util::checkError (__FILE__, __LINE__); + + // Switch to the other texture + glBindTexture (GL_TEXTURE_2D, texture_id); + mplot::gl::Util::checkError (__FILE__, __LINE__); + glActiveTexture (GL_TEXTURE0+image_texture_unit); + mplot::gl::Util::checkError (__FILE__, __LINE__); + + GLint imstatus; + glGetTexParameteriv (GL_TEXTURE_2D, GL_TEXTURE_IMMUTABLE_FORMAT, &imstatus); + std::cout << "IMMUTABLE_TEXTURE?: " << (imstatus?"Yes! immutable":"No, mutable") << std::endl; + + // Create *immutable* storage like this, but I *don't know how to subsequently transfer the rgb_data to the texture*. + glTexStorage2D (GL_TEXTURE_2D, 1, GL_RGB32F, dims[0], dims[1]); + mplot::gl::Util::checkError (__FILE__, __LINE__); + + // Transferring/loading data has to do with glBindImageTexture (See the spec.) + + // GL_INVALID_VALUE if: + // "unit greater than or equal to the value of GL_MAX_IMAGE_UNITS." Well, unit is 4, GL_MAX_IMAGE_UNITS is 128 or 8. + // "level or layer is less than zero." Both are 0, below. + // "texture is not the name of an existing texture object" I filled texture_id with glGenTextures, above. + // So WHY DO I STILL GET GL_INVALID_VALUE????? + glBindImageTexture (image_texture_unit_tmp, texture_id, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGB32F); // GL_INVALID_VALUE + mplot::gl::Util::checkError (__FILE__, __LINE__); + } #endif // I_HAD_FIGURED_OUT_SETUP_TEXTURE_WITH_DATA_PROPERLY - } // namespace gl -} // namespace mplot +} // namespace mplot::gl diff --git a/mplot/gl/util_mx.h b/mplot/gl/util_mx.h index a30cfa1f..54c41aa9 100644 --- a/mplot/gl/util_mx.h +++ b/mplot/gl/util_mx.h @@ -10,68 +10,64 @@ #include #include -namespace mplot { - namespace gl { - //! A GL error checking function. The additional namespace was a class, but didn't need to be. - namespace Util { - GLenum checkError (const char *file, int line, GladGLContext* glfn) - { - GLenum errorCode = 0; +namespace mplot::gl::Util +{ + GLenum checkError (const char *file, int line, GladGLContext* glfn) + { + GLenum errorCode = 0; #ifndef __APPLE__ // MacOS didn't like multiple calls to glGetError(); don't know why - unsigned int ecount = 0; - std::string error; + unsigned int ecount = 0; + std::string error; - while ((errorCode = glfn->GetError()) != GL_NO_ERROR) { + while ((errorCode = glfn->GetError()) != GL_NO_ERROR) { - switch (errorCode) { - case GL_INVALID_ENUM: - { - error = "GL error: GL_INVALID_ENUM"; - break; - } - case GL_INVALID_VALUE: - { - error = "GL error: GL_INVALID_VALUE"; - break; - } - case GL_INVALID_OPERATION: - { - error = "GL error: GL_INVALID_OPERATION"; - break; - } - case 1283: // Not part of GL3? - { - error = "GL error: GL_STACK_OVERFLOW"; - break; - } - case 1284: // Not part of GL3? - { - error = "GL error: GL_STACK_UNDERFLOW"; - break; - } - case GL_OUT_OF_MEMORY: - { - error = "GL error: GL_OUT_OF_MEMORY"; - break; - } - case GL_INVALID_FRAMEBUFFER_OPERATION: - { - error = "GL error: GL_INVALID_FRAMEBUFFER_OPERATION"; - break; - } - default: - { - error = "GL checkError: Unknown GL error code"; - break; - } - } - std::cout << error << " | " << file << ":" << line << std::endl; - ++ecount; - } - if (ecount) { throw std::runtime_error (error); } -#endif - return errorCode; + switch (errorCode) { + case GL_INVALID_ENUM: + { + error = "GL error: GL_INVALID_ENUM"; + break; + } + case GL_INVALID_VALUE: + { + error = "GL error: GL_INVALID_VALUE"; + break; } - } // namespace Util - } // namespace gl + case GL_INVALID_OPERATION: + { + error = "GL error: GL_INVALID_OPERATION"; + break; + } + case 1283: // Not part of GL3? + { + error = "GL error: GL_STACK_OVERFLOW"; + break; + } + case 1284: // Not part of GL3? + { + error = "GL error: GL_STACK_UNDERFLOW"; + break; + } + case GL_OUT_OF_MEMORY: + { + error = "GL error: GL_OUT_OF_MEMORY"; + break; + } + case GL_INVALID_FRAMEBUFFER_OPERATION: + { + error = "GL error: GL_INVALID_FRAMEBUFFER_OPERATION"; + break; + } + default: + { + error = "GL checkError: Unknown GL error code"; + break; + } + } + std::cout << error << " | " << file << ":" << line << std::endl; + ++ecount; + } + if (ecount) { throw std::runtime_error (error); } +#endif + return errorCode; + } } // namespace diff --git a/mplot/gl/util_nomx.h b/mplot/gl/util_nomx.h index eae36c84..e5284fa5 100644 --- a/mplot/gl/util_nomx.h +++ b/mplot/gl/util_nomx.h @@ -13,68 +13,64 @@ #include #include -namespace mplot { - namespace gl { - //! A GL error checking function. The additional namespace was a class, but didn't need to be. - namespace Util { - GLenum checkError (const char *file, int line) - { - GLenum errorCode = 0; +namespace mplot::gl::Util +{ + GLenum checkError (const char *file, int line) + { + GLenum errorCode = 0; #ifndef __APPLE__ // MacOS didn't like multiple calls to glGetError(); don't know why - unsigned int ecount = 0; - std::string error; + unsigned int ecount = 0; + std::string error; - while ((errorCode = glGetError()) != GL_NO_ERROR) { + while ((errorCode = glGetError()) != GL_NO_ERROR) { - switch (errorCode) { - case GL_INVALID_ENUM: - { - error = "GL error: GL_INVALID_ENUM"; - break; - } - case GL_INVALID_VALUE: - { - error = "GL error: GL_INVALID_VALUE"; - break; - } - case GL_INVALID_OPERATION: - { - error = "GL error: GL_INVALID_OPERATION"; - break; - } - case 1283: // Not part of GL3? - { - error = "GL error: GL_STACK_OVERFLOW"; - break; - } - case 1284: // Not part of GL3? - { - error = "GL error: GL_STACK_UNDERFLOW"; - break; - } - case GL_OUT_OF_MEMORY: - { - error = "GL error: GL_OUT_OF_MEMORY"; - break; - } - case GL_INVALID_FRAMEBUFFER_OPERATION: - { - error = "GL error: GL_INVALID_FRAMEBUFFER_OPERATION"; - break; - } - default: - { - error = "GL checkError: Unknown GL error code"; - break; - } - } - std::cout << error << " | " << file << ":" << line << std::endl; - ++ecount; - } - if (ecount) { throw std::runtime_error (error); } -#endif - return errorCode; + switch (errorCode) { + case GL_INVALID_ENUM: + { + error = "GL error: GL_INVALID_ENUM"; + break; + } + case GL_INVALID_VALUE: + { + error = "GL error: GL_INVALID_VALUE"; + break; } - } // namespace Util - } // namespace gl + case GL_INVALID_OPERATION: + { + error = "GL error: GL_INVALID_OPERATION"; + break; + } + case 1283: // Not part of GL3? + { + error = "GL error: GL_STACK_OVERFLOW"; + break; + } + case 1284: // Not part of GL3? + { + error = "GL error: GL_STACK_UNDERFLOW"; + break; + } + case GL_OUT_OF_MEMORY: + { + error = "GL error: GL_OUT_OF_MEMORY"; + break; + } + case GL_INVALID_FRAMEBUFFER_OPERATION: + { + error = "GL error: GL_INVALID_FRAMEBUFFER_OPERATION"; + break; + } + default: + { + error = "GL checkError: Unknown GL error code"; + break; + } + } + std::cout << error << " | " << file << ":" << line << std::endl; + ++ecount; + } + if (ecount) { throw std::runtime_error (error); } +#endif + return errorCode; + } } // namespace diff --git a/mplot/gl/version.h b/mplot/gl/version.h index 3e126b75..b8b61e62 100644 --- a/mplot/gl/version.h +++ b/mplot/gl/version.h @@ -11,119 +11,117 @@ #include -namespace mplot { - namespace gl { +namespace mplot::gl +{ + //!@{ + /*! + * I encode the OpenGL version in a single int value, which can be passed as a template + * argument to mplot::Visual and friends. These are the human-readable definitions. You can + * pass, for example `mplot::gl::version_4_3` as the argument to your template. + */ + static constexpr int version_4_1 = 0x00040001; + static constexpr int version_4_1_compat = 0x20040001; + static constexpr int version_4_2 = 0x00040002; + static constexpr int version_4_2_compat = 0x20040002; + static constexpr int version_4_3 = 0x00040003; + static constexpr int version_4_3_compat = 0x20040003; + static constexpr int version_4_4 = 0x00040004; + static constexpr int version_4_4_compat = 0x20040004; + static constexpr int version_4_5 = 0x00040005; + static constexpr int version_4_5_compat = 0x20040005; + static constexpr int version_4_6 = 0x00040006; + static constexpr int version_4_6_compat = 0x20040006; + static constexpr int version_3_0_es = 0x40030000; // OpenGL 3.0 ES is a subset of OpenGL 3.3 + static constexpr int version_3_1_es = 0x40030001; // OpenGL 3.1 ES is a subset of OpenGL 4.3 + static constexpr int version_3_2_es = 0x40030002; + //!@{ - //!@{ - /*! - * I encode the OpenGL version in a single int value, which can be passed as a template - * argument to mplot::Visual and friends. These are the human-readable definitions. You can - * pass, for example `mplot::gl::version_4_3` as the argument to your template. - */ - static constexpr int version_4_1 = 0x00040001; - static constexpr int version_4_1_compat = 0x20040001; - static constexpr int version_4_2 = 0x00040002; - static constexpr int version_4_2_compat = 0x20040002; - static constexpr int version_4_3 = 0x00040003; - static constexpr int version_4_3_compat = 0x20040003; - static constexpr int version_4_4 = 0x00040004; - static constexpr int version_4_4_compat = 0x20040004; - static constexpr int version_4_5 = 0x00040005; - static constexpr int version_4_5_compat = 0x20040005; - static constexpr int version_4_6 = 0x00040006; - static constexpr int version_4_6_compat = 0x20040006; - static constexpr int version_3_0_es = 0x40030000; // OpenGL 3.0 ES is a subset of OpenGL 3.3 - static constexpr int version_3_1_es = 0x40030001; // OpenGL 3.1 ES is a subset of OpenGL 4.3 - static constexpr int version_3_2_es = 0x40030002; - //!@{ - - /* - * The mplot::gl::version namespace contains static and constexpr methods to decode the - * single OpenGL version integer into minor, major, compat, gles and to generate strings - * which describe the version. The bottom 16 bits encode the minor version number. The next - * 13 bits encode the major version number. bit 29 encodes the 'compatibility' flag and bit - * 30 encodes the OpenGL ES flag. Note that outdated versions with a 3rd number such as - * OpenGL 1.2.1 are NOT supported here. - */ - namespace version { - - // Open GL minor version number - static int constexpr minor (const int gl_version_number) - { - return (gl_version_number & 0xffff); - } - // Open GL major version number - static int constexpr major (const int gl_version_number) - { - return (gl_version_number >> 16 & 0x1fff); - } - // True if this is the compatibility profile (by default it's the core profile) - static bool constexpr compat (const int gl_version_number) - { - return (((gl_version_number >> 29) & 0x1) > 0x0) ? true : false; - } - // True if this is an OpenGL ES version - static bool constexpr gles (const int gl_version_number) - { - return (((gl_version_number >> 30) & 0x1) > 0x0) ? true : false; + /* + * The mplot::gl::version namespace contains static and constexpr methods to decode the + * single OpenGL version integer into minor, major, compat, gles and to generate strings + * which describe the version. The bottom 16 bits encode the minor version number. The next + * 13 bits encode the major version number. bit 29 encodes the 'compatibility' flag and bit + * 30 encodes the OpenGL ES flag. Note that outdated versions with a 3rd number such as + * OpenGL 1.2.1 are NOT supported here. + */ + namespace version + { + // Open GL minor version number + static int constexpr minor (const int gl_version_number) + { + return (gl_version_number & 0xffff); + } + // Open GL major version number + static int constexpr major (const int gl_version_number) + { + return (gl_version_number >> 16 & 0x1fff); + } + // True if this is the compatibility profile (by default it's the core profile) + static bool constexpr compat (const int gl_version_number) + { + return (((gl_version_number >> 29) & 0x1) > 0x0) ? true : false; + } + // True if this is an OpenGL ES version + static bool constexpr gles (const int gl_version_number) + { + return (((gl_version_number >> 30) & 0x1) > 0x0) ? true : false; + } + // Output a string describing the version number + static inline std::string vstring (const int gl_version_number) + { + std::string v = std::to_string (version::major(gl_version_number)) + std::string(".") + + std::to_string (version::minor(gl_version_number)); + if (version::compat(gl_version_number)) { + v += " compat"; } - // Output a string describing the version number - static inline std::string vstring (const int gl_version_number) - { - std::string v = std::to_string (version::major(gl_version_number)) + std::string(".") - + std::to_string (version::minor(gl_version_number)); - if (version::compat(gl_version_number)) { - v += " compat"; - } - if (version::gles(gl_version_number)) { - v += " ES"; - } - return v; + if (version::gles(gl_version_number)) { + v += " ES"; } - // Return the version-specific shader preamble as a const char* from a constexpr function - static constexpr const char* shaderpreamble (const int gl_version_number) - { - const char* preamble = "#version unknown\n"; + return v; + } + // Return the version-specific shader preamble as a const char* from a constexpr function + static constexpr const char* shaderpreamble (const int gl_version_number) + { + const char* preamble = "#version unknown\n"; - switch (gl_version_number) { - case mplot::gl::version_3_0_es: - preamble = "#version 300 es\n#extension GL_EXT_shader_io_blocks : enable\nprecision mediump float;\n"; - break; - case mplot::gl::version_3_1_es: - preamble = "#version 310 es\n#extension GL_EXT_shader_io_blocks : enable\nprecision mediump float;\n"; - break; - case mplot::gl::version_3_2_es: - preamble = "#version 320 es\n#extension GL_EXT_shader_io_blocks : enable\nprecision mediump float;\n"; - break; - case mplot::gl::version_4_1: - case mplot::gl::version_4_1_compat: - preamble = "#version 410\n"; - break; - case mplot::gl::version_4_2: - case mplot::gl::version_4_2_compat: - preamble = "#version 420\n"; - break; - case mplot::gl::version_4_3: - case mplot::gl::version_4_3_compat: - preamble = "#version 430\n"; - break; - case mplot::gl::version_4_4: - case mplot::gl::version_4_4_compat: - preamble = "#version 440\n"; - break; - case mplot::gl::version_4_5: - case mplot::gl::version_4_5_compat: - preamble = "#version 450\n"; - break; - case mplot::gl::version_4_6: - case mplot::gl::version_4_6_compat: - preamble = "#version 460\n"; - break; - default: - break; - } - return preamble; + switch (gl_version_number) { + case mplot::gl::version_3_0_es: + preamble = "#version 300 es\n#extension GL_EXT_shader_io_blocks : enable\nprecision mediump float;\n"; + break; + case mplot::gl::version_3_1_es: + preamble = "#version 310 es\n#extension GL_EXT_shader_io_blocks : enable\nprecision mediump float;\n"; + break; + case mplot::gl::version_3_2_es: + preamble = "#version 320 es\n#extension GL_EXT_shader_io_blocks : enable\nprecision mediump float;\n"; + break; + case mplot::gl::version_4_1: + case mplot::gl::version_4_1_compat: + preamble = "#version 410\n"; + break; + case mplot::gl::version_4_2: + case mplot::gl::version_4_2_compat: + preamble = "#version 420\n"; + break; + case mplot::gl::version_4_3: + case mplot::gl::version_4_3_compat: + preamble = "#version 430\n"; + break; + case mplot::gl::version_4_4: + case mplot::gl::version_4_4_compat: + preamble = "#version 440\n"; + break; + case mplot::gl::version_4_5: + case mplot::gl::version_4_5_compat: + preamble = "#version 450\n"; + break; + case mplot::gl::version_4_6: + case mplot::gl::version_4_6_compat: + preamble = "#version 460\n"; + break; + default: + break; } - } // namespace version - } // namespace gl -} // namespace mplot + return preamble; + } + } // namespace version +} // namespace mplot::gl diff --git a/mplot/graphing.h b/mplot/graphing.h index 08cb6957..5c3acadc 100644 --- a/mplot/graphing.h +++ b/mplot/graphing.h @@ -25,8 +25,8 @@ #include #include -namespace mplot::graphing { - +namespace mplot::graphing +{ //! Graph-specific number formatting for tick labels. You must pass in an adjacent //! label (which affects the optimum precision to use for formatting) template diff --git a/mplot/graphstyles.h b/mplot/graphstyles.h index f08d3005..9fa131ae 100644 --- a/mplot/graphstyles.h +++ b/mplot/graphstyles.h @@ -4,8 +4,8 @@ #pragma once -namespace mplot { - +namespace mplot +{ //! What shape for the graph markers? enum class markerstyle { diff --git a/mplot/healpix/healpix_astrometry.hpp b/mplot/healpix/healpix_astrometry.hpp index a57a7d28..afe2fb57 100644 --- a/mplot/healpix/healpix_astrometry.hpp +++ b/mplot/healpix/healpix_astrometry.hpp @@ -142,1732 +142,1728 @@ . healpix_nested_to_xy */ -namespace hp { // Healpix - namespace am { // Astrometry +namespace hp::am // HealPix::AstroMetry +{ + // The maximum healpix Nside that leads to int-sized healpix indices. + // 12 * (13377+1)^2 > 2^31 (since we use signed ints) + // This corresponds to about 16 arcsec side length. + static constexpr int HP_MAX_INT_NSIDE = 13377; + + /** + Converts a healpix index from the XY scheme to the RING scheme. + */ + const int healpix_xy_to_ring(int hp, int Nside); + + /** + Converts a healpix index from the RING scheme to the XY scheme. + */ + const int healpix_ring_to_xy(int ring_index, int Nside); + + /** + Converts a healpix index from the XY scheme to the NESTED scheme. + */ + const int healpix_xy_to_nested(int hp, int Nside); + + /** + Converts a healpix index from the NESTED scheme to the XY scheme. + */ + const int healpix_nested_to_xy(int nested_index, int Nside); + + /** + Decomposes a RING index into the "ring number" (each ring contain + healpixels of equal latitude) and "longitude index". Pixels within a + ring have longitude index starting at zero for the first pixel with + RA >= 0. Different rings contain different numbers of healpixels. + */ + void healpix_decompose_ring(int ring_index, int Nside, + int* p_ring_number, int* p_longitude_index); + + /** + Composes a RING index given the "ring number" and "longitude index". + + Does NOT check that the values are legal! Garbage in, garbage out. + */ + const int healpix_compose_ring(int ring, int longind, int Nside); + + /** + Decomposes an XY index into the "base healpix" and "x" and "y" coordinates + within that healpix. + */ + void healpix_decompose_xy(int finehp, int* bighp, int* x, int* y, int Nside); + + void healpix_decompose_xyl(int64_t finehp, int* bighp, int* x, int* y, int Nside); + + /** + Composes an XY index given the "base healpix" and "x" and "y" coordinates + within that healpix. + */ + const int healpix_compose_xy(int bighp, int x, int y, int Nside); + + const int64_t healpix_compose_xyl(int bighp, int x, int y, int Nside); + + /** + Given (x,y) coordinates of resolution "nside" within a base-level + healpixel, and an output resolution "outnside", returns the output + (x,y) coordinates at the output resolution. + */ + void healpix_convert_xy_nside(int x, int y, int nside, int outnside, + int* outx, int* outy); + + /** + Given a healpix index (in the XY scheme) of resolution "nside", and + an output resolution "outnside", returns the healpix index at the + output resolution. + */ + void healpix_convert_nside(int hp, int nside, int outnside, int* outhp); + void healpix_convert_nsidel(int64_t hp, int nside, int outnside, int64_t* outhp); + + /** + Converts (RA, DEC) coordinates (in radians) to healpix index. + */ + const int radectohealpix(double ra, double dec, int Nside); + + int radectohealpixf(double ra, double dec, int Nside, double* dx, double* dy); + + const int64_t radectohealpixl(double ra, double dec, int Nside); + + int64_t radectohealpixlf(double ra, double dec, int Nside, double* dx, double* dy); + + /** + Converts (RA, DEC) coordinates (in degrees) to healpix index. + */ + const int radecdegtohealpix(double ra, double dec, int Nside); + + int radecdegtohealpixf(double ra, double dec, int Nside, double* dx, double* dy); + + const int64_t radecdegtohealpixl(double ra, double dec, int Nside); + + int64_t radecdegtohealpixlf(double ra, double dec, int Nside, double* dx, double* dy); + + /** + Converts (x,y,z) coordinates on the unit sphere into a healpix index. + */ + const int xyztohealpix(double x, double y, double z, int Nside); + + const int64_t xyztohealpixl(double x, double y, double z, int Nside); + + int xyztohealpixf(double x, double y, double z, int Nside, + double* p_dx, double* p_dy); + + int64_t xyztohealpixlf(double x, double y, double z, int Nside, + double* p_dx, double* p_dy); + + /** + Converts (x,y,z) coordinates (stored in an array) on the unit sphere into + a healpix index. + */ + int xyzarrtohealpix(const double* xyz, int Nside); - // The maximum healpix Nside that leads to int-sized healpix indices. - // 12 * (13377+1)^2 > 2^31 (since we use signed ints) - // This corresponds to about 16 arcsec side length. - static constexpr int HP_MAX_INT_NSIDE = 13377; + int64_t xyzarrtohealpixl(const double* xyz, int Nside); + + int xyzarrtohealpixf(const double* xyz,int Nside, double* p_dx, double* p_dy); - /** - Converts a healpix index from the XY scheme to the RING scheme. - */ - const int healpix_xy_to_ring(int hp, int Nside); - - /** - Converts a healpix index from the RING scheme to the XY scheme. - */ - const int healpix_ring_to_xy(int ring_index, int Nside); - - /** - Converts a healpix index from the XY scheme to the NESTED scheme. - */ - const int healpix_xy_to_nested(int hp, int Nside); - - /** - Converts a healpix index from the NESTED scheme to the XY scheme. - */ - const int healpix_nested_to_xy(int nested_index, int Nside); - - /** - Decomposes a RING index into the "ring number" (each ring contain - healpixels of equal latitude) and "longitude index". Pixels within a - ring have longitude index starting at zero for the first pixel with - RA >= 0. Different rings contain different numbers of healpixels. - */ - void healpix_decompose_ring(int ring_index, int Nside, - int* p_ring_number, int* p_longitude_index); - - /** - Composes a RING index given the "ring number" and "longitude index". - - Does NOT check that the values are legal! Garbage in, garbage out. - */ - const int healpix_compose_ring(int ring, int longind, int Nside); - - /** - Decomposes an XY index into the "base healpix" and "x" and "y" coordinates - within that healpix. - */ - void healpix_decompose_xy(int finehp, int* bighp, int* x, int* y, int Nside); - - void healpix_decompose_xyl(int64_t finehp, int* bighp, int* x, int* y, int Nside); - - /** - Composes an XY index given the "base healpix" and "x" and "y" coordinates - within that healpix. - */ - const int healpix_compose_xy(int bighp, int x, int y, int Nside); - - const int64_t healpix_compose_xyl(int bighp, int x, int y, int Nside); - - /** - Given (x,y) coordinates of resolution "nside" within a base-level - healpixel, and an output resolution "outnside", returns the output - (x,y) coordinates at the output resolution. - */ - void healpix_convert_xy_nside(int x, int y, int nside, int outnside, - int* outx, int* outy); - - /** - Given a healpix index (in the XY scheme) of resolution "nside", and - an output resolution "outnside", returns the healpix index at the - output resolution. - */ - void healpix_convert_nside(int hp, int nside, int outnside, int* outhp); - void healpix_convert_nsidel(int64_t hp, int nside, int outnside, int64_t* outhp); - - /** - Converts (RA, DEC) coordinates (in radians) to healpix index. - */ - const int radectohealpix(double ra, double dec, int Nside); - - int radectohealpixf(double ra, double dec, int Nside, double* dx, double* dy); - - const int64_t radectohealpixl(double ra, double dec, int Nside); + /** + Converts a healpix index, plus fractional offsets (dx,dy), into (x,y,z) + coordinates on the unit sphere. (dx,dy) must be in [0, 1]. (0.5, 0.5) + is the center of the healpix. (0,0) is the southernmost corner, (1,1) is + the northernmost corner, (1,0) is the easternmost, and (0,1) the + westernmost. + */ + void healpix_to_xyz(int hp, int Nside, double dx, double dy, + double* p_x, double *p_y, double *p_z); - int64_t radectohealpixlf(double ra, double dec, int Nside, double* dx, double* dy); + /** + Same as healpix_to_xyz, but (x,y,z) are stored in an array. + */ + void healpix_to_xyzarr(int hp, int Nside, double dx, double dy, + double* xyz); - /** - Converts (RA, DEC) coordinates (in degrees) to healpix index. - */ - const int radecdegtohealpix(double ra, double dec, int Nside); - - int radecdegtohealpixf(double ra, double dec, int Nside, double* dx, double* dy); - - const int64_t radecdegtohealpixl(double ra, double dec, int Nside); - - int64_t radecdegtohealpixlf(double ra, double dec, int Nside, double* dx, double* dy); - - /** - Converts (x,y,z) coordinates on the unit sphere into a healpix index. - */ - const int xyztohealpix(double x, double y, double z, int Nside); - - const int64_t xyztohealpixl(double x, double y, double z, int Nside); - - int xyztohealpixf(double x, double y, double z, int Nside, - double* p_dx, double* p_dy); - - int64_t xyztohealpixlf(double x, double y, double z, int Nside, - double* p_dx, double* p_dy); - - /** - Converts (x,y,z) coordinates (stored in an array) on the unit sphere into - a healpix index. - */ - int xyzarrtohealpix(const double* xyz, int Nside); - - int64_t xyzarrtohealpixl(const double* xyz, int Nside); - - int xyzarrtohealpixf(const double* xyz,int Nside, double* p_dx, double* p_dy); + void healpixl_to_xyzarr(int64_t hp, int Nside, double dx, double dy, + double* xyz); - /** - Converts a healpix index, plus fractional offsets (dx,dy), into (x,y,z) - coordinates on the unit sphere. (dx,dy) must be in [0, 1]. (0.5, 0.5) - is the center of the healpix. (0,0) is the southernmost corner, (1,1) is - the northernmost corner, (1,0) is the easternmost, and (0,1) the - westernmost. - */ - void healpix_to_xyz(int hp, int Nside, double dx, double dy, - double* p_x, double *p_y, double *p_z); - - /** - Same as healpix_to_xyz, but (x,y,z) are stored in an array. - */ - void healpix_to_xyzarr(int hp, int Nside, double dx, double dy, - double* xyz); - void healpixl_to_xyzarr(int64_t hp, int Nside, double dx, double dy, - double* xyz); + /** + Same as healpix_to_xyz, but returns (RA,DEC) in radians. + */ + void healpix_to_radec(int hp, int Nside, double dx, double dy, + double* ra, double* dec); + void healpix_to_radecdeg(int hp, int Nside, double dx, double dy, + double* ra, double* dec); - /** - Same as healpix_to_xyz, but returns (RA,DEC) in radians. - */ - void healpix_to_radec(int hp, int Nside, double dx, double dy, + void healpixl_to_radecdeg(int64_t hp, int Nside, double dx, double dy, double* ra, double* dec); - void healpix_to_radecdeg(int hp, int Nside, double dx, double dy, - double* ra, double* dec); - - void healpixl_to_radecdeg(int64_t hp, int Nside, double dx, double dy, - double* ra, double* dec); - - /** - Same as healpix_to_radec, but (RA,DEC) are stored in an array. - */ - void healpix_to_radecarr(int hp, int Nside, double dx, double dy, - double* radec); - - void healpix_to_radecdegarr(int hp, int Nside, double dx, double dy, - double* radec); - - /** - Computes the approximate side length of a healpix, in arcminutes. - */ - const double healpix_side_length_arcmin(int Nside); - - /** - Computes the approximate Nside you need to get healpixes with side - length about "arcmin" arcminutes. (inverse of - healpix_side_length_arcmin) - */ - double healpix_nside_for_side_length_arcmin(double arcmin); - - /** - Finds the healpixes neighbouring the given healpix, placing them in the - array "neighbour". Returns the number of neighbours. You must ensure - that "neighbour" has 8 elements. + /** + Same as healpix_to_radec, but (RA,DEC) are stored in an array. + */ + void healpix_to_radecarr(int hp, int Nside, double dx, double dy, + double* radec); + + void healpix_to_radecdegarr(int hp, int Nside, double dx, double dy, + double* radec); + + /** + Computes the approximate side length of a healpix, in arcminutes. + */ + const double healpix_side_length_arcmin(int Nside); + + /** + Computes the approximate Nside you need to get healpixes with side + length about "arcmin" arcminutes. (inverse of + healpix_side_length_arcmin) + */ + double healpix_nside_for_side_length_arcmin(double arcmin); + + /** + Finds the healpixes neighbouring the given healpix, placing them in the + array "neighbour". Returns the number of neighbours. You must ensure + that "neighbour" has 8 elements. + + Healpixes in the interior of a large healpix will have eight neighbours; + pixels near the edges can have fewer. + */ + int healpix_get_neighbours(int hp, int* neighbours, int Nside); + + /** + Same as above, but for Nsides big enough that it overflows 32-bit int. + */ + int healpix_get_neighboursl(int64_t pix, int64_t* neighbour, int Nside); + + /** + Finds the healpixes containing and neighbouring the given xyz + position which are within distance 'range' (in units of distance of + the unit sphere). Places the results in 'healpixes', which must have + at least 9 elements. Returns the number of 'healpixes' set. + + Returns -1 if "Nside" < 0. + */ + int healpix_get_neighbours_within_range(double* xyz, double range, int* healpixes, + int Nside); + + /** + Same as above, but RA,Dec,radius in degrees. + */ + int healpix_get_neighbours_within_range_radec(double ra, double dec, double radius, + int* healpixes, int Nside); + + /** + Returns the minimum distance (in degrees) between the given healpix + and the given RA,Dec (in degrees). + */ + double healpix_distance_to_radec(int hp, int Nside, double ra, double dec, + double* closestradec); - Healpixes in the interior of a large healpix will have eight neighbours; - pixels near the edges can have fewer. - */ - int healpix_get_neighbours(int hp, int* neighbours, int Nside); - - /** - Same as above, but for Nsides big enough that it overflows 32-bit int. - */ - int healpix_get_neighboursl(int64_t pix, int64_t* neighbour, int Nside); - - /** - Finds the healpixes containing and neighbouring the given xyz - position which are within distance 'range' (in units of distance of - the unit sphere). Places the results in 'healpixes', which must have - at least 9 elements. Returns the number of 'healpixes' set. - - Returns -1 if "Nside" < 0. - */ - int healpix_get_neighbours_within_range(double* xyz, double range, int* healpixes, - int Nside); +#ifdef ENABLE_FUNCTIONS_REQUIRING_QSORT + /** + Returns the minimum distance (in degrees) between the given healpix + and the given xyz (point on unit sphere). + */ + double healpix_distance_to_xyz(int hp, int Nside, const double* xyz, + double* closestxyz); + + /** + Returns true if the closest distance between the given healpix and + the given RA,Dec (in degrees) is less than then given radius (in degrees). + */ + int healpix_within_range_of_radec(int hp, int Nside, double ra, double dec, + double radius); + int healpix_within_range_of_xyz(int hp, int Nside, const double* xyz, + double radius); + + + /** + Computes the RA,Dec bounding-box of the given healpix. Results are + in degrees. RA may be wacky for healpixes spanning RA=0. + */ + void healpix_radec_bounds(int hp, int nside, + double* ralo, double* rahi, + double* declo, double* dechi); +#endif +} - /** - Same as above, but RA,Dec,radius in degrees. - */ - int healpix_get_neighbours_within_range_radec(double ra, double dec, double radius, - int* healpixes, int Nside); +namespace hp::am +{ + // "borrowed" from from linux-2.4 + static unsigned int my_hweight32(unsigned int w) { + unsigned int res = (w & 0x55555555) + ((w >> 1) & 0x55555555); + res = (res & 0x33333333) + ((res >> 2) & 0x33333333); + res = (res & 0x0F0F0F0F) + ((res >> 4) & 0x0F0F0F0F); + res = (res & 0x00FF00FF) + ((res >> 8) & 0x00FF00FF); + return (res & 0x0000FFFF) + ((res >> 16) & 0x0000FFFF); + } - /** - Returns the minimum distance (in degrees) between the given healpix - and the given RA,Dec (in degrees). - */ - double healpix_distance_to_radec(int hp, int Nside, double ra, double dec, - double* closestradec); + int is_power_of_two(unsigned int x) { + return (my_hweight32(x) == 1); + } -#ifdef ENABLE_FUNCTIONS_REQUIRING_QSORT - /** - Returns the minimum distance (in degrees) between the given healpix - and the given xyz (point on unit sphere). - */ - double healpix_distance_to_xyz(int hp, int Nside, const double* xyz, - double* closestxyz); + // Internal type + struct hp_s { + int bighp; + int x; + int y; + }; + typedef struct hp_s hp_t; - /** - Returns true if the closest distance between the given healpix and - the given RA,Dec (in degrees) is less than then given radius (in degrees). - */ - int healpix_within_range_of_radec(int hp, int Nside, double ra, double dec, - double radius); - int healpix_within_range_of_xyz(int hp, int Nside, const double* xyz, - double radius); + static int64_t hptointl(hp_t hp, int Nside) { + return healpix_compose_xyl(hp.bighp, hp.x, hp.y, Nside); + } + static int hptoint(hp_t hp, int Nside) { + return healpix_compose_xy(hp.bighp, hp.x, hp.y, Nside); + } - /** - Computes the RA,Dec bounding-box of the given healpix. Results are - in degrees. RA may be wacky for healpixes spanning RA=0. - */ - void healpix_radec_bounds(int hp, int nside, - double* ralo, double* rahi, - double* declo, double* dechi); -#endif + static void intltohp(int64_t pix, hp_t* hp, int Nside) { + healpix_decompose_xyl(pix, &hp->bighp, &hp->x, &hp->y, Nside); } -} -namespace hp { - namespace am { + static void inttohp(int pix, hp_t* hp, int Nside) { + healpix_decompose_xy(pix, &hp->bighp, &hp->x, &hp->y, Nside); + } + static void longtohp(int64_t pix, hp_t* hp, int Nside) { + healpix_decompose_xyl(pix, &hp->bighp, &hp->x, &hp->y, Nside); + } - // "borrowed" from from linux-2.4 - static unsigned int my_hweight32(unsigned int w) { - unsigned int res = (w & 0x55555555) + ((w >> 1) & 0x55555555); - res = (res & 0x33333333) + ((res >> 2) & 0x33333333); - res = (res & 0x0F0F0F0F) + ((res >> 4) & 0x0F0F0F0F); - res = (res & 0x00FF00FF) + ((res >> 8) & 0x00FF00FF); - return (res & 0x0000FFFF) + ((res >> 16) & 0x0000FFFF); - } + static void hp_decompose(hp_t* hp, int* php, int* px, int* py) { + if (php) { *php = hp->bighp; } + if (px) { *px = hp->x; } + if (py) { *py = hp->y; } + } - int is_power_of_two(unsigned int x) { - return (my_hweight32(x) == 1); - } + const static double mysquare(double d) { return d*d; } - // Internal type - struct hp_s { - int bighp; - int x; - int y; - }; - typedef struct hp_s hp_t; + const int healpix_xy_to_nested(int hp, int Nside) { + int bighp,x,y; + int index; + int i; - static int64_t hptointl(hp_t hp, int Nside) { - return healpix_compose_xyl(hp.bighp, hp.x, hp.y, Nside); + healpix_decompose_xy(hp, &bighp, &x, &y, Nside); + if (!is_power_of_two(Nside)) { + fprintf(stderr, "healpix_xy_to_nested: Nside must be a power of two.\n"); + return -1; } - static int hptoint(hp_t hp, int Nside) { - return healpix_compose_xy(hp.bighp, hp.x, hp.y, Nside); + // We construct the index called p_n' in the healpix paper, whose bits + // are taken from the bits of x and y: + // x = ... b4 b2 b0 + // y = ... b5 b3 b1 + // We go through the bits of x,y, building up "index": + index = 0; + for (i=0; i<(8*static_cast(sizeof(int))/2); i++) { + index |= (((y & 1) << 1) | (x & 1)) << (i*2); + y >>= 1; + x >>= 1; + if (!x && !y) break; } - static void intltohp(int64_t pix, hp_t* hp, int Nside) { - healpix_decompose_xyl(pix, &hp->bighp, &hp->x, &hp->y, Nside); - } + return index + bighp * Nside * Nside; + } - static void inttohp(int pix, hp_t* hp, int Nside) { - healpix_decompose_xy(pix, &hp->bighp, &hp->x, &hp->y, Nside); - } - static void longtohp(int64_t pix, hp_t* hp, int Nside) { - healpix_decompose_xyl(pix, &hp->bighp, &hp->x, &hp->y, Nside); + const int healpix_nested_to_xy(int hp, int Nside) { + int bighp, x, y; + int index; + int i; + if (!is_power_of_two(Nside)) { + fprintf(stderr, "healpix_xy_to_nested: Nside must be a power of two.\n"); + return -1; } + bighp = hp / (Nside*Nside); + index = hp % (Nside*Nside); + x = y = 0; + for (i=0; i<(8*static_cast(sizeof(int))/2); i++) { + x |= (index & 0x1) << i; + index >>= 1; + y |= (index & 0x1) << i; + index >>= 1; + if (!index) break; + } + return healpix_compose_xy(bighp, x, y, Nside); + } - static void hp_decompose(hp_t* hp, int* php, int* px, int* py) { - if (php) { *php = hp->bighp; } - if (px) { *px = hp->x; } - if (py) { *py = hp->y; } + const int healpix_compose_ring(int ring, int longind, int Nside) { + if (ring <= Nside) + // north polar + return ring * (ring-1) * 2 + longind; + if (ring < 3*Nside) + // equatorial + return Nside*(Nside-1)*2 + Nside*4*(ring-Nside) + longind; + { + int ri; + ri = 4*Nside - ring; + return 12*Nside*Nside-1 - ( ri*(ri-1)*2 + (ri*4 - 1 - longind) ); } + } - const static double mysquare(double d) { return d*d; } - - const int healpix_xy_to_nested(int hp, int Nside) { - int bighp,x,y; - int index; - int i; - - healpix_decompose_xy(hp, &bighp, &x, &y, Nside); - if (!is_power_of_two(Nside)) { - fprintf(stderr, "healpix_xy_to_nested: Nside must be a power of two.\n"); - return -1; - } - - // We construct the index called p_n' in the healpix paper, whose bits - // are taken from the bits of x and y: - // x = ... b4 b2 b0 - // y = ... b5 b3 b1 - // We go through the bits of x,y, building up "index": - index = 0; - for (i=0; i<(8*static_cast(sizeof(int))/2); i++) { - index |= (((y & 1) << 1) | (x & 1)) << (i*2); - y >>= 1; - x >>= 1; - if (!x && !y) break; + void healpix_decompose_ring(int hp, int Nside, int* p_ring, int* p_longind) { + // FIXME: this could be written in closed form... + int longind; + int ring; + int offset = 0; + for (ring=1; ring<=Nside; ring++) { + if (offset + ring*4 > hp) { + longind = hp - offset; + goto gotit; } - - return index + bighp * Nside * Nside; + offset += ring*4; } - - const int healpix_nested_to_xy(int hp, int Nside) { - int bighp, x, y; - int index; - int i; - if (!is_power_of_two(Nside)) { - fprintf(stderr, "healpix_xy_to_nested: Nside must be a power of two.\n"); - return -1; - } - bighp = hp / (Nside*Nside); - index = hp % (Nside*Nside); - x = y = 0; - for (i=0; i<(8*static_cast(sizeof(int))/2); i++) { - x |= (index & 0x1) << i; - index >>= 1; - y |= (index & 0x1) << i; - index >>= 1; - if (!index) break; + for (; ring<(3*Nside); ring++) { + if (offset + Nside*4 > hp) { + longind = hp - offset; + goto gotit; } - return healpix_compose_xy(bighp, x, y, Nside); + offset += Nside*4; } - - const int healpix_compose_ring(int ring, int longind, int Nside) { - if (ring <= Nside) - // north polar - return ring * (ring-1) * 2 + longind; - if (ring < 3*Nside) - // equatorial - return Nside*(Nside-1)*2 + Nside*4*(ring-Nside) + longind; - { - int ri; - ri = 4*Nside - ring; - return 12*Nside*Nside-1 - ( ri*(ri-1)*2 + (ri*4 - 1 - longind) ); + for (; ring<(4*Nside); ring++) { + if (offset + (Nside*4 - ring)*4 > hp) { + longind = hp - offset; + goto gotit; } - } + offset += (Nside*4 - ring)*4; + } + fprintf(stderr, "healpix_decompose_ring: shouldn't get here!\n"); + if (p_ring) *p_ring = -1; + if (p_longind) *p_longind = -1; + return; + gotit: + if (p_ring) + *p_ring = ring; + if (p_longind) + *p_longind = longind; + } - void healpix_decompose_ring(int hp, int Nside, int* p_ring, int* p_longind) { - // FIXME: this could be written in closed form... - int longind; - int ring; - int offset = 0; - for (ring=1; ring<=Nside; ring++) { - if (offset + ring*4 > hp) { - longind = hp - offset; - goto gotit; - } - offset += ring*4; - } - for (; ring<(3*Nside); ring++) { - if (offset + Nside*4 > hp) { - longind = hp - offset; - goto gotit; - } - offset += Nside*4; - } - for (; ring<(4*Nside); ring++) { - if (offset + (Nside*4 - ring)*4 > hp) { - longind = hp - offset; - goto gotit; + const int healpix_ring_to_xy(int ring, int Nside) { + int bighp, x, y; + int ringind, longind; + healpix_decompose_ring(ring, Nside, &ringind, &longind); + if (ringind <= Nside) { + int ind; + int v; + int F1; + int frow; + bighp = longind / ringind; + ind = longind - bighp * ringind; + y = (Nside - 1 - ind); + frow = bighp / 4; + F1 = frow + 2; + v = F1*Nside - ringind - 1; + x = v - y; + return healpix_compose_xy(bighp, x, y, Nside); + } else if (ringind < 3*Nside) { + int panel; + int ind; + int bottomleft; + int topleft; + int frow, F1, F2, s, v, h; + int bighp = -1; + int x, y; + int hp; + int R = 0; + + panel = longind / Nside; + ind = longind % Nside; + bottomleft = ind < (ringind - Nside + 1) / 2; + topleft = ind < (3*Nside - ringind + 1)/2; + + if (!bottomleft && topleft) { + // top row. + bighp = panel; + } else if (bottomleft && !topleft) { + // bottom row. + bighp = 8 + panel; + } else if (bottomleft && topleft) { + // left side. + bighp = 4 + panel; + } else if (!bottomleft && !topleft) { + // right side. + bighp = 4 + (panel + 1) % 4; + if (bighp == 4) { + longind -= (4*Nside - 1); + // Gah! Wacky hack - it seems that since + // "longind" is negative in this case, the + // rounding behaves differently, so we end up + // computing the wrong "h" and have to correct + // for it. + R = 1; } - offset += (Nside*4 - ring)*4; } - fprintf(stderr, "healpix_decompose_ring: shouldn't get here!\n"); - if (p_ring) *p_ring = -1; - if (p_longind) *p_longind = -1; - return; - gotit: - if (p_ring) - *p_ring = ring; - if (p_longind) - *p_longind = longind; - } - const int healpix_ring_to_xy(int ring, int Nside) { - int bighp, x, y; - int ringind, longind; - healpix_decompose_ring(ring, Nside, &ringind, &longind); - if (ringind <= Nside) { - int ind; - int v; - int F1; - int frow; - bighp = longind / ringind; - ind = longind - bighp * ringind; - y = (Nside - 1 - ind); - frow = bighp / 4; - F1 = frow + 2; - v = F1*Nside - ringind - 1; - x = v - y; - return healpix_compose_xy(bighp, x, y, Nside); - } else if (ringind < 3*Nside) { - int panel; - int ind; - int bottomleft; - int topleft; - int frow, F1, F2, s, v, h; - int bighp = -1; - int x, y; - int hp; - int R = 0; - - panel = longind / Nside; - ind = longind % Nside; - bottomleft = ind < (ringind - Nside + 1) / 2; - topleft = ind < (3*Nside - ringind + 1)/2; - - if (!bottomleft && topleft) { - // top row. - bighp = panel; - } else if (bottomleft && !topleft) { - // bottom row. - bighp = 8 + panel; - } else if (bottomleft && topleft) { - // left side. - bighp = 4 + panel; - } else if (!bottomleft && !topleft) { - // right side. - bighp = 4 + (panel + 1) % 4; - if (bighp == 4) { - longind -= (4*Nside - 1); - // Gah! Wacky hack - it seems that since - // "longind" is negative in this case, the - // rounding behaves differently, so we end up - // computing the wrong "h" and have to correct - // for it. - R = 1; - } - } - - frow = bighp / 4; - F1 = frow + 2; - F2 = 2*(bighp % 4) - (frow % 2) + 1; - s = (ringind - Nside) % 2; - v = F1*Nside - ringind - 1; - h = 2*longind - s - F2*Nside; - if (R) - h--; + frow = bighp / 4; + F1 = frow + 2; + F2 = 2*(bighp % 4) - (frow % 2) + 1; + s = (ringind - Nside) % 2; + v = F1*Nside - ringind - 1; + h = 2*longind - s - F2*Nside; + if (R) + h--; + x = (v + h) / 2; + y = (v - h) / 2; + + if ((v != (x+y)) || (h != (x-y))) { + h++; x = (v + h) / 2; y = (v - h) / 2; if ((v != (x+y)) || (h != (x-y))) { - h++; - x = (v + h) / 2; - y = (v - h) / 2; - - if ((v != (x+y)) || (h != (x-y))) { - // There was just a comment in here - throw std::runtime_error ("This is still not right"); - } + // There was just a comment in here + throw std::runtime_error ("This is still not right"); } - hp = healpix_compose_xy(bighp, x, y, Nside); - return hp; - } else { - int ind; - int v; - int F1; - int frow; - int ri; - ri = 4*Nside - ringind; - bighp = 8 + longind / ri; - ind = longind - (bighp%4) * ri; - y = (ri-1) - ind; - frow = bighp / 4; - F1 = frow + 2; - v = F1*Nside - ringind - 1; - x = v - y; - return healpix_compose_xy(bighp, x, y, Nside); } - } - - const int healpix_xy_to_ring(int hp, int Nside) { - int bighp,x,y; - int frow; - int F1; + hp = healpix_compose_xy(bighp, x, y, Nside); + return hp; + } else { + int ind; int v; - int ring; - int index; - - healpix_decompose_xy(hp, &bighp, &x, &y, Nside); + int F1; + int frow; + int ri; + ri = 4*Nside - ringind; + bighp = 8 + longind / ri; + ind = longind - (bighp%4) * ri; + y = (ri-1) - ind; frow = bighp / 4; F1 = frow + 2; - v = x + y; - // "ring" starts from 1 at the north pole and goes to 4Nside-1 at - // the south pole; the pixels in each ring have the same latitude. - ring = F1*Nside - v - 1; - /* - ring: - [1, Nside] : n pole - (Nside, 2Nside] : n equatorial - (2Nside+1, 3Nside) : s equat - [3Nside, 4Nside-1] : s pole - */ - // this probably can't happen... - if ((ring < 1) || (ring >= 4*Nside)) { - fprintf(stderr, "Invalid ring index: %i\n", ring); - return -1; - } - if (ring <= Nside) { - // north polar. - // left-to-right coordinate within this healpix - index = (Nside - 1 - y); - // offset from the other big healpixes - index += ((bighp % 4) * ring); - // offset from the other rings - index += ring*(ring-1)*2; - } else if (ring >= 3*Nside) { - // south polar. - // Here I first flip everything so that we label the pixels - // at zero starting in the southeast corner, increasing to the - // west and north, then subtract that from the total number of - // healpixels. - int ri = 4*Nside - ring; - // index within this healpix - index = (ri-1) - x; - // big healpixes - index += ((3-(bighp % 4)) * ri); - // other rings - index += ri*(ri-1)*2; - // flip! - index = 12*Nside*Nside - 1 - index; - } else { - // equatorial. - int s, F2, h; - s = (ring - Nside) % 2; - F2 = 2*((int)bighp % 4) - (frow % 2) + 1; - h = x - y; - index = (F2 * (int)Nside + h + s) / 2; - // offset from the north polar region: - index += Nside*(Nside-1)*2; - // offset within the equatorial region: - index += Nside * 4 * (ring - Nside); - // handle healpix #4 wrap-around - if ((bighp == 4) && (y > x)) - index += (4 * Nside - 1); - } - return index; - } - - const double healpix_side_length_arcmin(int Nside) { - return std::sqrt((sm::mathconst::four_pi * mysquare(180.0 * 60.0 / sm::mathconst::pi)) / - (12.0 * Nside * Nside)); + v = F1*Nside - ringind - 1; + x = v - y; + return healpix_compose_xy(bighp, x, y, Nside); } + } - double healpix_nside_for_side_length_arcmin(double arcmin) { - // arcmin2rad: a*pi/10800.0 - return std::sqrt(sm::mathconst::four_pi / (mysquare(arcmin*sm::mathconst::pi/10800.0) * 12.0)); + const int healpix_xy_to_ring(int hp, int Nside) { + int bighp,x,y; + int frow; + int F1; + int v; + int ring; + int index; + + healpix_decompose_xy(hp, &bighp, &x, &y, Nside); + frow = bighp / 4; + F1 = frow + 2; + v = x + y; + // "ring" starts from 1 at the north pole and goes to 4Nside-1 at + // the south pole; the pixels in each ring have the same latitude. + ring = F1*Nside - v - 1; + /* + ring: + [1, Nside] : n pole + (Nside, 2Nside] : n equatorial + (2Nside+1, 3Nside) : s equat + [3Nside, 4Nside-1] : s pole + */ + // this probably can't happen... + if ((ring < 1) || (ring >= 4*Nside)) { + fprintf(stderr, "Invalid ring index: %i\n", ring); + return -1; } + if (ring <= Nside) { + // north polar. + // left-to-right coordinate within this healpix + index = (Nside - 1 - y); + // offset from the other big healpixes + index += ((bighp % 4) * ring); + // offset from the other rings + index += ring*(ring-1)*2; + } else if (ring >= 3*Nside) { + // south polar. + // Here I first flip everything so that we label the pixels + // at zero starting in the southeast corner, increasing to the + // west and north, then subtract that from the total number of + // healpixels. + int ri = 4*Nside - ring; + // index within this healpix + index = (ri-1) - x; + // big healpixes + index += ((3-(bighp % 4)) * ri); + // other rings + index += ri*(ri-1)*2; + // flip! + index = 12*Nside*Nside - 1 - index; + } else { + // equatorial. + int s, F2, h; + s = (ring - Nside) % 2; + F2 = 2*((int)bighp % 4) - (frow % 2) + 1; + h = x - y; + index = (F2 * (int)Nside + h + s) / 2; + // offset from the north polar region: + index += Nside*(Nside-1)*2; + // offset within the equatorial region: + index += Nside * 4 * (ring - Nside); + // handle healpix #4 wrap-around + if ((bighp == 4) && (y > x)) + index += (4 * Nside - 1); + } + return index; + } - static bool ispolar(int healpix) - { - // the north polar healpixes are 0,1,2,3 - // the south polar healpixes are 8,9,10,11 - return (healpix <= 3) || (healpix >= 8); - } + const double healpix_side_length_arcmin(int Nside) { + return std::sqrt((sm::mathconst::four_pi * mysquare(180.0 * 60.0 / sm::mathconst::pi)) / + (12.0 * Nside * Nside)); + } - static bool isequatorial(int healpix) - { - // the north polar healpixes are 0,1,2,3 - // the south polar healpixes are 8,9,10,11 - return (healpix >= 4) && (healpix <= 7); - } + double healpix_nside_for_side_length_arcmin(double arcmin) { + // arcmin2rad: a*pi/10800.0 + return std::sqrt(sm::mathconst::four_pi / (mysquare(arcmin*sm::mathconst::pi/10800.0) * 12.0)); + } - static bool isnorthpolar(int healpix) - { - return (healpix <= 3); - } + static bool ispolar(int healpix) + { + // the north polar healpixes are 0,1,2,3 + // the south polar healpixes are 8,9,10,11 + return (healpix <= 3) || (healpix >= 8); + } - static bool issouthpolar(int healpix) - { - return (healpix >= 8); - } + static bool isequatorial(int healpix) + { + // the north polar healpixes are 0,1,2,3 + // the south polar healpixes are 8,9,10,11 + return (healpix >= 4) && (healpix <= 7); + } - static int compose_xy(int x, int y, int Nside) { - assert(Nside > 0); - assert(x >= 0); - assert(x < Nside); - assert(y >= 0); - assert(y < Nside); - return (x * Nside) + y; - } + static bool isnorthpolar(int healpix) + { + return (healpix <= 3); + } - const int healpix_compose_xy(int bighp, int x, int y, int Nside) { - assert(bighp >= 0); - assert(bighp < 12); - return (bighp * Nside * Nside) + compose_xy(x, y, Nside); - } + static bool issouthpolar(int healpix) + { + return (healpix >= 8); + } - const int64_t healpix_compose_xyl(int bighp, int x, int y, int Nside) { - int64_t ns = Nside; - assert(Nside > 0); - assert(bighp >= 0); - assert(bighp < 12); - assert(x >= 0); - assert(x < Nside); - assert(y >= 0); - assert(y < Nside); - return ((((int64_t)bighp * ns) + x) * ns) + y; - } + static int compose_xy(int x, int y, int Nside) { + assert(Nside > 0); + assert(x >= 0); + assert(x < Nside); + assert(y >= 0); + assert(y < Nside); + return (x * Nside) + y; + } - void healpix_convert_nside(int hp, int nside, int outnside, int* outhp) { - int basehp, x, y; - int ox, oy; - healpix_decompose_xy(hp, &basehp, &x, &y, nside); - healpix_convert_xy_nside(x, y, nside, outnside, &ox, &oy); - *outhp = healpix_compose_xy(basehp, ox, oy, outnside); - } + const int healpix_compose_xy(int bighp, int x, int y, int Nside) { + assert(bighp >= 0); + assert(bighp < 12); + return (bighp * Nside * Nside) + compose_xy(x, y, Nside); + } - void healpix_convert_nsidel(int64_t hp, int nside, int outnside, int64_t* outhp) { - int basehp, x, y; - int ox, oy; - healpix_decompose_xyl(hp, &basehp, &x, &y, nside); - healpix_convert_xy_nside(x, y, nside, outnside, &ox, &oy); - *outhp = healpix_compose_xyl(basehp, ox, oy, outnside); - } + const int64_t healpix_compose_xyl(int bighp, int x, int y, int Nside) { + int64_t ns = Nside; + assert(Nside > 0); + assert(bighp >= 0); + assert(bighp < 12); + assert(x >= 0); + assert(x < Nside); + assert(y >= 0); + assert(y < Nside); + return ((((int64_t)bighp * ns) + x) * ns) + y; + } - void healpix_convert_xy_nside(int x, int y, int nside, int outnside, - int* outx, int* outy) { - double fx, fy; - int ox, oy; - assert(x >= 0); - assert(x < nside); - assert(y >= 0); - assert(y < nside); + void healpix_convert_nside(int hp, int nside, int outnside, int* outhp) { + int basehp, x, y; + int ox, oy; + healpix_decompose_xy(hp, &basehp, &x, &y, nside); + healpix_convert_xy_nside(x, y, nside, outnside, &ox, &oy); + *outhp = healpix_compose_xy(basehp, ox, oy, outnside); + } - // MAGIC 0.5: assume center of pixel... - fx = (x + 0.5) / (double)nside; - fy = (y + 0.5) / (double)nside; + void healpix_convert_nsidel(int64_t hp, int nside, int outnside, int64_t* outhp) { + int basehp, x, y; + int ox, oy; + healpix_decompose_xyl(hp, &basehp, &x, &y, nside); + healpix_convert_xy_nside(x, y, nside, outnside, &ox, &oy); + *outhp = healpix_compose_xyl(basehp, ox, oy, outnside); + } - ox = floor(fx * outnside); - oy = floor(fy * outnside); + void healpix_convert_xy_nside(int x, int y, int nside, int outnside, + int* outx, int* outy) { + double fx, fy; + int ox, oy; + assert(x >= 0); + assert(x < nside); + assert(y >= 0); + assert(y < nside); + + // MAGIC 0.5: assume center of pixel... + fx = (x + 0.5) / (double)nside; + fy = (y + 0.5) / (double)nside; + + ox = floor(fx * outnside); + oy = floor(fy * outnside); + + if (outx) + *outx = ox; + if (outy) + *outy = oy; + } - if (outx) - *outx = ox; - if (outy) - *outy = oy; + void healpix_decompose_xy(int finehp, int* pbighp, int* px, int* py, int Nside) { + int hp; + assert(Nside > 0); + assert(finehp < (12 * Nside * Nside)); + assert(finehp >= 0); + if (pbighp) { + int bighp = finehp / (Nside * Nside); + assert(bighp >= 0); + assert(bighp < 12); + *pbighp = bighp; } - - void healpix_decompose_xy(int finehp, int* pbighp, int* px, int* py, int Nside) { - int hp; - assert(Nside > 0); - assert(finehp < (12 * Nside * Nside)); - assert(finehp >= 0); - if (pbighp) { - int bighp = finehp / (Nside * Nside); - assert(bighp >= 0); - assert(bighp < 12); - *pbighp = bighp; - } - hp = finehp % (Nside * Nside); - if (px) { - *px = hp / Nside; - assert(*px >= 0); - assert(*px < Nside); - } - if (py) { - *py = hp % Nside; - assert(*py >= 0); - assert(*py < Nside); - } + hp = finehp % (Nside * Nside); + if (px) { + *px = hp / Nside; + assert(*px >= 0); + assert(*px < Nside); + } + if (py) { + *py = hp % Nside; + assert(*py >= 0); + assert(*py < Nside); } + } - void healpix_decompose_xyl(int64_t finehp, - int* pbighp, int* px, int* py, - int Nside) { - int64_t hp; - int64_t ns2 = (int64_t)Nside * (int64_t)Nside; - assert(Nside > 0); - assert(finehp < (12L * ns2)); - assert(finehp >= 0); - if (pbighp) { - int bighp = finehp / ns2; - assert(bighp >= 0); - assert(bighp < 12); - *pbighp = bighp; - } - hp = finehp % ns2; - if (px) { - *px = hp / Nside; - assert(*px >= 0); - assert(*px < Nside); - } - if (py) { - *py = hp % Nside; - assert(*py >= 0); - assert(*py < Nside); - } + void healpix_decompose_xyl(int64_t finehp, + int* pbighp, int* px, int* py, + int Nside) { + int64_t hp; + int64_t ns2 = (int64_t)Nside * (int64_t)Nside; + assert(Nside > 0); + assert(finehp < (12L * ns2)); + assert(finehp >= 0); + if (pbighp) { + int bighp = finehp / ns2; + assert(bighp >= 0); + assert(bighp < 12); + *pbighp = bighp; + } + hp = finehp % ns2; + if (px) { + *px = hp / Nside; + assert(*px >= 0); + assert(*px < Nside); } + if (py) { + *py = hp % Nside; + assert(*py >= 0); + assert(*py < Nside); + } + } - /** - Given a large-scale healpix number, computes its neighbour in the - direction (dx,dy). Returns -1 if there is no such neighbour. - */ - static int healpix_get_neighbour(int hp, int dx, int dy) - { - if (isnorthpolar(hp)) { - if ((dx == 1) && (dy == 0)) return (hp + 1) % 4; - if ((dx == 0) && (dy == 1)) return (hp + 3) % 4; - if ((dx == 1) && (dy == 1)) return (hp + 2) % 4; - if ((dx == -1) && (dy == 0)) return (hp + 4); - if ((dx == 0) && (dy == -1)) return 4 + ((hp + 1) % 4); - if ((dx == -1) && (dy == -1)) return hp + 8; - return -1; - } else if (issouthpolar(hp)) { - if ((dx == 1) && (dy == 0)) return 4 + ((hp + 1) % 4); - if ((dx == 0) && (dy == 1)) return hp - 4; - if ((dx == -1) && (dy == 0)) return 8 + ((hp + 3) % 4); - if ((dx == 0) && (dy == -1)) return 8 + ((hp + 1) % 4); - if ((dx == -1) && (dy == -1)) return 8 + ((hp + 2) % 4); - if ((dx == 1) && (dy == 1)) return hp - 8; - return -1; - } else { - if ((dx == 1) && (dy == 0)) return hp - 4; - if ((dx == 0) && (dy == 1)) return (hp + 3) % 4; - if ((dx == -1) && (dy == 0)) return 8 + ((hp + 3) % 4); - if ((dx == 0) && (dy == -1)) return hp + 4; - if ((dx == 1) && (dy == -1)) return 4 + ((hp + 1) % 4); - if ((dx == -1) && (dy == 1)) return 4 + ((hp - 1) % 4); - return -1; - } + /** + Given a large-scale healpix number, computes its neighbour in the + direction (dx,dy). Returns -1 if there is no such neighbour. + */ + static int healpix_get_neighbour(int hp, int dx, int dy) + { + if (isnorthpolar(hp)) { + if ((dx == 1) && (dy == 0)) return (hp + 1) % 4; + if ((dx == 0) && (dy == 1)) return (hp + 3) % 4; + if ((dx == 1) && (dy == 1)) return (hp + 2) % 4; + if ((dx == -1) && (dy == 0)) return (hp + 4); + if ((dx == 0) && (dy == -1)) return 4 + ((hp + 1) % 4); + if ((dx == -1) && (dy == -1)) return hp + 8; + return -1; + } else if (issouthpolar(hp)) { + if ((dx == 1) && (dy == 0)) return 4 + ((hp + 1) % 4); + if ((dx == 0) && (dy == 1)) return hp - 4; + if ((dx == -1) && (dy == 0)) return 8 + ((hp + 3) % 4); + if ((dx == 0) && (dy == -1)) return 8 + ((hp + 1) % 4); + if ((dx == -1) && (dy == -1)) return 8 + ((hp + 2) % 4); + if ((dx == 1) && (dy == 1)) return hp - 8; + return -1; + } else { + if ((dx == 1) && (dy == 0)) return hp - 4; + if ((dx == 0) && (dy == 1)) return (hp + 3) % 4; + if ((dx == -1) && (dy == 0)) return 8 + ((hp + 3) % 4); + if ((dx == 0) && (dy == -1)) return hp + 4; + if ((dx == 1) && (dy == -1)) return 4 + ((hp + 1) % 4); + if ((dx == -1) && (dy == 1)) return 4 + ((hp - 1) % 4); return -1; } + return -1; + } - static int get_neighbours(hp_t hp, hp_t* neighbour, int Nside) { - int base; - int x, y; - int nn = 0; - int nbase; - int nx, ny; - - base = hp.bighp; - x = hp.x; - y = hp.y; - - // ( + , 0 ) - nx = (x + 1) % Nside; - ny = y; - if (x == (Nside - 1)) { - nbase = healpix_get_neighbour(base, 1, 0); - if (isnorthpolar(base)) { - nx = x; - std::swap(nx, ny); - } - } else - nbase = base; - + static int get_neighbours(hp_t hp, hp_t* neighbour, int Nside) { + int base; + int x, y; + int nn = 0; + int nbase; + int nx, ny; + + base = hp.bighp; + x = hp.x; + y = hp.y; + + // ( + , 0 ) + nx = (x + 1) % Nside; + ny = y; + if (x == (Nside - 1)) { + nbase = healpix_get_neighbour(base, 1, 0); + if (isnorthpolar(base)) { + nx = x; + std::swap(nx, ny); + } + } else + nbase = base; + + neighbour[nn].bighp = nbase; + neighbour[nn].x = nx; + neighbour[nn].y = ny; + nn++; + + // ( + , + ) + nx = (x + 1) % Nside; + ny = (y + 1) % Nside; + if ((x == Nside - 1) && (y == Nside - 1)) { + if (ispolar(base)) + nbase = healpix_get_neighbour(base, 1, 1); + else + nbase = -1; + } else if (x == (Nside - 1)) + nbase = healpix_get_neighbour(base, 1, 0); + else if (y == (Nside - 1)) + nbase = healpix_get_neighbour(base, 0, 1); + else + nbase = base; + + if (isnorthpolar(base)) { + if (x == (Nside - 1)) + nx = Nside - 1; + if (y == (Nside - 1)) + ny = Nside - 1; + if ((x == (Nside - 1)) || (y == (Nside - 1))) + std::swap(nx, ny); + } + + if (nbase != -1) { neighbour[nn].bighp = nbase; neighbour[nn].x = nx; neighbour[nn].y = ny; nn++; + } - // ( + , + ) - nx = (x + 1) % Nside; - ny = (y + 1) % Nside; - if ((x == Nside - 1) && (y == Nside - 1)) { - if (ispolar(base)) - nbase = healpix_get_neighbour(base, 1, 1); - else - nbase = -1; - } else if (x == (Nside - 1)) - nbase = healpix_get_neighbour(base, 1, 0); - else if (y == (Nside - 1)) - nbase = healpix_get_neighbour(base, 0, 1); - else - nbase = base; - + // ( 0 , + ) + nx = x; + ny = (y + 1) % Nside; + if (y == (Nside - 1)) { + nbase = healpix_get_neighbour(base, 0, 1); if (isnorthpolar(base)) { - if (x == (Nside - 1)) - nx = Nside - 1; - if (y == (Nside - 1)) - ny = Nside - 1; - if ((x == (Nside - 1)) || (y == (Nside - 1))) - std::swap(nx, ny); + ny = y; + std::swap(nx, ny); } - - if (nbase != -1) { - neighbour[nn].bighp = nbase; - neighbour[nn].x = nx; - neighbour[nn].y = ny; - nn++; + } else + nbase = base; + + neighbour[nn].bighp = nbase; + neighbour[nn].x = nx; + neighbour[nn].y = ny; + nn++; + + // ( - , + ) + nx = (x + Nside - 1) % Nside; + ny = (y + 1) % Nside; + if ((x == 0) && (y == (Nside - 1))) { + if (isequatorial(base)) + nbase = healpix_get_neighbour(base, -1, 1); + else + nbase = -1; + } else if (x == 0) { + nbase = healpix_get_neighbour(base, -1, 0); + if (issouthpolar(base)) { + nx = 0; + std::swap(nx, ny); } + } else if (y == (Nside - 1)) { + nbase = healpix_get_neighbour(base, 0, 1); + if (isnorthpolar(base)) { + ny = y; + std::swap(nx, ny); + } + } else + nbase = base; - // ( 0 , + ) - nx = x; - ny = (y + 1) % Nside; - if (y == (Nside - 1)) { - nbase = healpix_get_neighbour(base, 0, 1); - if (isnorthpolar(base)) { - ny = y; - std::swap(nx, ny); - } - } else - nbase = base; - + if (nbase != -1) { neighbour[nn].bighp = nbase; neighbour[nn].x = nx; neighbour[nn].y = ny; nn++; + } - // ( - , + ) - nx = (x + Nside - 1) % Nside; - ny = (y + 1) % Nside; - if ((x == 0) && (y == (Nside - 1))) { - if (isequatorial(base)) - nbase = healpix_get_neighbour(base, -1, 1); - else - nbase = -1; - } else if (x == 0) { - nbase = healpix_get_neighbour(base, -1, 0); - if (issouthpolar(base)) { - nx = 0; - std::swap(nx, ny); - } - } else if (y == (Nside - 1)) { - nbase = healpix_get_neighbour(base, 0, 1); - if (isnorthpolar(base)) { - ny = y; - std::swap(nx, ny); - } - } else - nbase = base; - - if (nbase != -1) { - neighbour[nn].bighp = nbase; - neighbour[nn].x = nx; - neighbour[nn].y = ny; - nn++; + // ( - , 0 ) + nx = (x + Nside - 1) % Nside; + ny = y; + if (x == 0) { + nbase = healpix_get_neighbour(base, -1, 0); + if (issouthpolar(base)) { + nx = 0; + std::swap(nx, ny); } - - // ( - , 0 ) - nx = (x + Nside - 1) % Nside; - ny = y; - if (x == 0) { - nbase = healpix_get_neighbour(base, -1, 0); - if (issouthpolar(base)) { - nx = 0; - std::swap(nx, ny); - } - } else - nbase = base; - + } else + nbase = base; + + neighbour[nn].bighp = nbase; + neighbour[nn].x = nx; + neighbour[nn].y = ny; + nn++; + + // ( - , - ) + nx = (x + Nside - 1) % Nside; + ny = (y + Nside - 1) % Nside; + if ((x == 0) && (y == 0)) { + if (ispolar(base)) + nbase = healpix_get_neighbour(base, -1, -1); + else + nbase = -1; + } else if (x == 0) + nbase = healpix_get_neighbour(base, -1, 0); + else if (y == 0) + nbase = healpix_get_neighbour(base, 0, -1); + else + nbase = base; + + if (issouthpolar(base)) { + if (x == 0) + nx = 0; + if (y == 0) + ny = 0; + if ((x == 0) || (y == 0)) + std::swap(nx, ny); + } + + if (nbase != -1) { neighbour[nn].bighp = nbase; neighbour[nn].x = nx; neighbour[nn].y = ny; nn++; + } - // ( - , - ) - nx = (x + Nside - 1) % Nside; - ny = (y + Nside - 1) % Nside; - if ((x == 0) && (y == 0)) { - if (ispolar(base)) - nbase = healpix_get_neighbour(base, -1, -1); - else - nbase = -1; - } else if (x == 0) - nbase = healpix_get_neighbour(base, -1, 0); - else if (y == 0) - nbase = healpix_get_neighbour(base, 0, -1); - else - nbase = base; - + // ( 0 , - ) + ny = (y + Nside - 1) % Nside; + nx = x; + if (y == 0) { + nbase = healpix_get_neighbour(base, 0, -1); if (issouthpolar(base)) { - if (x == 0) - nx = 0; - if (y == 0) - ny = 0; - if ((x == 0) || (y == 0)) - std::swap(nx, ny); + ny = y; + std::swap(nx, ny); } + } else + nbase = base; + + neighbour[nn].bighp = nbase; + neighbour[nn].x = nx; + neighbour[nn].y = ny; + nn++; + + // ( + , - ) + nx = (x + 1) % Nside; + ny = (y + Nside - 1) % Nside; + if ((x == (Nside - 1)) && (y == 0)) { + if (isequatorial(base)) { + nbase = healpix_get_neighbour(base, 1, -1); + } else + nbase = -1; - if (nbase != -1) { - neighbour[nn].bighp = nbase; - neighbour[nn].x = nx; - neighbour[nn].y = ny; - nn++; + } else if (x == (Nside - 1)) { + nbase = healpix_get_neighbour(base, 1, 0); + if (isnorthpolar(base)) { + nx = x; + std::swap(nx, ny); } + } else if (y == 0) { + nbase = healpix_get_neighbour(base, 0, -1); + if (issouthpolar(base)) { + ny = y; + std::swap(nx, ny); + } + } else + nbase = base; - // ( 0 , - ) - ny = (y + Nside - 1) % Nside; - nx = x; - if (y == 0) { - nbase = healpix_get_neighbour(base, 0, -1); - if (issouthpolar(base)) { - ny = y; - std::swap(nx, ny); - } - } else - nbase = base; - + if (nbase != -1) { neighbour[nn].bighp = nbase; neighbour[nn].x = nx; neighbour[nn].y = ny; nn++; - - // ( + , - ) - nx = (x + 1) % Nside; - ny = (y + Nside - 1) % Nside; - if ((x == (Nside - 1)) && (y == 0)) { - if (isequatorial(base)) { - nbase = healpix_get_neighbour(base, 1, -1); - } else - nbase = -1; - - } else if (x == (Nside - 1)) { - nbase = healpix_get_neighbour(base, 1, 0); - if (isnorthpolar(base)) { - nx = x; - std::swap(nx, ny); - } - } else if (y == 0) { - nbase = healpix_get_neighbour(base, 0, -1); - if (issouthpolar(base)) { - ny = y; - std::swap(nx, ny); - } - } else - nbase = base; - - if (nbase != -1) { - neighbour[nn].bighp = nbase; - neighbour[nn].x = nx; - neighbour[nn].y = ny; - nn++; - } - - return nn; } - int healpix_get_neighbours(int pix, int* neighbour, int Nside) { - hp_t neigh[8]; - hp_t hp; - int nn; - int i; - inttohp(pix, &hp, Nside); - nn = get_neighbours(hp, neigh, Nside); - for (i=0; i 0); - - /* Convert our point into cylindrical coordinates for middle ring */ - phi = std::atan2(vy, vx); - if (phi < 0.0) - phi += sm::mathconst::two_pi; - phi_t = std::fmod(phi, sm::mathconst::pi_over_2); - assert (phi_t >= 0.0); - - // North or south polar cap. - if ((vz >= twothirds) || (vz <= -twothirds)) { - double zfactor; - bool north; - int column; - double root; - double xx, yy, kx, ky; - - // Which pole? - if (vz >= twothirds) { - north = true; - zfactor = 1.0; - } else { - north = false; - zfactor = -1.0; - } + int healpix_get_neighboursl(int64_t pix, int64_t* neighbour, int Nside) { + hp_t neigh[8]; + hp_t hp; + int nn; + int i; + intltohp(pix, &hp, Nside); + nn = get_neighbours(hp, neigh, Nside); + for (i=0; i::pi) / sm::mathconst::pi); - kx = (root <= 0.0) ? 0.0 : std::sqrt(root); + static hp_t xyztohp(double vx, double vy, double vz, int Nside, + double* p_dx, double* p_dy) { + double phi; + constexpr double twothirds = 2.0 / 3.0; + double dx, dy; + int basehp; + int x, y; + double sector; + int offset; + double phi_t; + hp_t hp; + + // only used in asserts() + __attribute__ ((unused)) double EPS = 1e-8; + + assert(Nside > 0); + + /* Convert our point into cylindrical coordinates for middle ring */ + phi = std::atan2(vy, vx); + if (phi < 0.0) + phi += sm::mathconst::two_pi; + phi_t = std::fmod(phi, sm::mathconst::pi_over_2); + assert (phi_t >= 0.0); + + // North or south polar cap. + if ((vz >= twothirds) || (vz <= -twothirds)) { + double zfactor; + bool north; + int column; + double root; + double xx, yy, kx, ky; + + // Which pole? + if (vz >= twothirds) { + north = true; + zfactor = 1.0; + } else { + north = false; + zfactor = -1.0; + } - // solve eqn 19 for k = Ns - yy - root = (1.0 - vz*zfactor) * 3.0 * mysquare(Nside * 2.0 * phi_t / sm::mathconst::pi); - ky = (root <= 0.0) ? 0.0 : std::sqrt(root); + // solve eqn 20: k = Ns - xx (in the northern hemi) + root = (1.0 - vz*zfactor) * 3.0 * mysquare(Nside * (2.0 * phi_t - sm::mathconst::pi) / sm::mathconst::pi); + kx = (root <= 0.0) ? 0.0 : std::sqrt(root); - if (north) { - xx = Nside - kx; - yy = Nside - ky; - } else { - xx = ky; - yy = kx; - } + // solve eqn 19 for k = Ns - yy + root = (1.0 - vz*zfactor) * 3.0 * mysquare(Nside * 2.0 * phi_t / sm::mathconst::pi); + ky = (root <= 0.0) ? 0.0 : std::sqrt(root); - // xx, yy should be in [0, Nside]. - x = std::min(static_cast(Nside-1), floor(xx)); - assert(x >= 0); - assert(x < Nside); + if (north) { + xx = Nside - kx; + yy = Nside - ky; + } else { + xx = ky; + yy = kx; + } - y = std::min(static_cast(Nside-1), floor(yy)); - assert(y >= 0); - assert(y < Nside); + // xx, yy should be in [0, Nside]. + x = std::min(static_cast(Nside-1), floor(xx)); + assert(x >= 0); + assert(x < Nside); - dx = xx - x; - dy = yy - y; + y = std::min(static_cast(Nside-1), floor(yy)); + assert(y >= 0); + assert(y < Nside); - sector = (phi - phi_t) / (sm::mathconst::pi_over_2); - offset = (int)std::round(sector); - assert(std::abs(sector - offset) < EPS); - offset = ((offset % 4) + 4) % 4; - assert(offset >= 0); - assert(offset <= 3); - column = offset; + dx = xx - x; + dy = yy - y; - if (north) - basehp = column; - else - basehp = 8 + column; + sector = (phi - phi_t) / (sm::mathconst::pi_over_2); + offset = (int)std::round(sector); + assert(std::abs(sector - offset) < EPS); + offset = ((offset % 4) + 4) % 4; + assert(offset >= 0); + assert(offset <= 3); + column = offset; + if (north) + basehp = column; + else + basehp = 8 + column; + + } else { + // could be polar or equatorial. + double sector; + int offset; + double u1, u2; + double zunits, phiunits; + double xx, yy; + + // project into the unit square z=[-2/3, 2/3], phi=[0, pi/2] + zunits = (vz + twothirds) / (4.0 / 3.0); + phiunits = phi_t / sm::mathconst::pi_over_2; + // convert into diagonal units + // (add 1 to u2 so that they both cover the range [0,2]. + u1 = zunits + phiunits; + u2 = zunits - phiunits + 1.0; + assert(u1 >= 0.); + assert(u1 <= 2.); + assert(u2 >= 0.); + assert(u2 <= 2.); + // x is the northeast direction, y is the northwest. + xx = u1 * Nside; + yy = u2 * Nside; + + // now compute which big healpix it's in. + // (note that we subtract off the modded portion used to + // compute the position within the healpix, so this should be + // very close to one of the boundaries.) + sector = (phi - phi_t) / (sm::mathconst::pi_over_2); + offset = (int)std::round(sector); + assert(std::abs(sector - offset) < EPS); + offset = ((offset % 4) + 4) % 4; + assert(offset >= 0); + assert(offset <= 3); + + // we're looking at a square in z,phi space with an X dividing it. + // we want to know which section we're in. + // xx ranges from 0 in the bottom-left to 2Nside in the top-right. + // yy ranges from 0 in the bottom-right to 2Nside in the top-left. + // (of the phi,z unit box) + if (xx >= Nside) { + xx -= Nside; + if (yy >= Nside) { + // north polar. + yy -= Nside; + basehp = offset; + } else { + // right equatorial. + basehp = ((offset + 1) % 4) + 4; + } } else { - // could be polar or equatorial. - double sector; - int offset; - double u1, u2; - double zunits, phiunits; - double xx, yy; - - // project into the unit square z=[-2/3, 2/3], phi=[0, pi/2] - zunits = (vz + twothirds) / (4.0 / 3.0); - phiunits = phi_t / sm::mathconst::pi_over_2; - // convert into diagonal units - // (add 1 to u2 so that they both cover the range [0,2]. - u1 = zunits + phiunits; - u2 = zunits - phiunits + 1.0; - assert(u1 >= 0.); - assert(u1 <= 2.); - assert(u2 >= 0.); - assert(u2 <= 2.); - // x is the northeast direction, y is the northwest. - xx = u1 * Nside; - yy = u2 * Nside; - - // now compute which big healpix it's in. - // (note that we subtract off the modded portion used to - // compute the position within the healpix, so this should be - // very close to one of the boundaries.) - sector = (phi - phi_t) / (sm::mathconst::pi_over_2); - offset = (int)std::round(sector); - assert(std::abs(sector - offset) < EPS); - offset = ((offset % 4) + 4) % 4; - assert(offset >= 0); - assert(offset <= 3); - - // we're looking at a square in z,phi space with an X dividing it. - // we want to know which section we're in. - // xx ranges from 0 in the bottom-left to 2Nside in the top-right. - // yy ranges from 0 in the bottom-right to 2Nside in the top-left. - // (of the phi,z unit box) - if (xx >= Nside) { - xx -= Nside; - if (yy >= Nside) { - // north polar. - yy -= Nside; - basehp = offset; - } else { - // right equatorial. - basehp = ((offset + 1) % 4) + 4; - } + if (yy >= Nside) { + // left equatorial. + yy -= Nside; + basehp = offset + 4; } else { - if (yy >= Nside) { - // left equatorial. - yy -= Nside; - basehp = offset + 4; - } else { - // south polar. - basehp = 8 + offset; - } + // south polar. + basehp = 8 + offset; } - - assert(xx >= -EPS); - assert(xx < (Nside+EPS)); - x = std::max(0.0, std::min(static_cast(Nside-1), floor(xx))); - assert(x >= 0); - assert(x < Nside); - dx = xx - x; - - assert(yy >= -EPS); - assert(yy < (Nside+EPS)); - y = std::max(0.0, std::min(static_cast(Nside-1), floor(yy))); - assert(y >= 0); - assert(y < Nside); - dy = yy - y; } - hp.bighp = basehp; - hp.x = x; - hp.y = y; - - if (p_dx) *p_dx = dx; - if (p_dy) *p_dy = dy; + assert(xx >= -EPS); + assert(xx < (Nside+EPS)); + x = std::max(0.0, std::min(static_cast(Nside-1), floor(xx))); + assert(x >= 0); + assert(x < Nside); + dx = xx - x; - return hp; + assert(yy >= -EPS); + assert(yy < (Nside+EPS)); + y = std::max(0.0, std::min(static_cast(Nside-1), floor(yy))); + assert(y >= 0); + assert(y < Nside); + dy = yy - y; } - const int xyztohealpix(double x, double y, double z, int Nside) { - return xyztohealpixf(x, y, z, Nside, NULL, NULL); - } + hp.bighp = basehp; + hp.x = x; + hp.y = y; - const int64_t xyztohealpixl(double x, double y, double z, int Nside) { - return xyztohealpixlf(x, y, z, Nside, NULL, NULL); - } + if (p_dx) *p_dx = dx; + if (p_dy) *p_dy = dy; - int64_t xyztohealpixlf(double x, double y, double z, int Nside, - double* p_dx, double* p_dy) { - hp_t hp = xyztohp(x,y,z, Nside, p_dx,p_dy); - return hptointl(hp, Nside); - } + return hp; + } - int xyztohealpixf(double x, double y, double z, int Nside, - double* p_dx, double* p_dy) { - hp_t hp = xyztohp(x,y,z, Nside, p_dx,p_dy); - return hptoint(hp, Nside); - } + const int xyztohealpix(double x, double y, double z, int Nside) { + return xyztohealpixf(x, y, z, Nside, NULL, NULL); + } - // A few functions from starutil - double radec2x (double r, double d) { return std::cos (d) * std::cos (r); } - double radec2y (double r, double d) { return std::cos (d) * std::sin (r); } - double radec2z (double r, double d) { return std::sin (d); } + const int64_t xyztohealpixl(double x, double y, double z, int Nside) { + return xyztohealpixlf(x, y, z, Nside, NULL, NULL); + } - double deg2rad (double d) { return d * sm::mathconst::deg2rad; } - double rad2deg (double r) { return r * sm::mathconst::rad2deg; } + int64_t xyztohealpixlf(double x, double y, double z, int Nside, + double* p_dx, double* p_dy) { + hp_t hp = xyztohp(x,y,z, Nside, p_dx,p_dy); + return hptointl(hp, Nside); + } - double z2dec(double z) { return std::asin(z); } - double xy2ra(double x, double y) { - double a = std::atan2(y, x); - if (a < 0) { a += sm::mathconst::two_pi; } - return a; - } - void xyz2radec(double x, double y, double z, double *ra, double *dec) { - if (ra) { *ra = xy2ra(x, y); } - if (dec) { *dec = z2dec(z); } - } - void xyzarr2radec(const double* xyz, double *ra, double *dec) { - xyz2radec(xyz[0], xyz[1], xyz[2], ra, dec); - } - void xyzarr2radecdeg(const double* xyz, double *ra, double *dec) { - xyzarr2radec(xyz, ra, dec); - if (ra) { *ra = rad2deg(*ra); } - if (dec) { *dec = rad2deg(*dec); } - } + int xyztohealpixf(double x, double y, double z, int Nside, + double* p_dx, double* p_dy) { + hp_t hp = xyztohp(x,y,z, Nside, p_dx,p_dy); + return hptoint(hp, Nside); + } - void radec2xyzarr(double ra, double dec, double* xyz) { - double cosdec = std::cos(dec); - xyz[0] = cosdec * std::cos(ra); - xyz[1] = cosdec * std::sin(ra); - xyz[2] = std::sin(dec); - } - void radecdeg2xyzarr(double ra, double dec, double* xyz) { - radec2xyzarr(deg2rad(ra),deg2rad(dec), xyz); - } + // A few functions from starutil + double radec2x (double r, double d) { return std::cos (d) * std::cos (r); } + double radec2y (double r, double d) { return std::cos (d) * std::sin (r); } + double radec2z (double r, double d) { return std::sin (d); } - double rad2distsq(double x) { return 2.0 * (1.0 - std::cos(x)); } // inverse of distsq2arc; cosine law. - constexpr double RAD_PER_ARCSEC = 4.8481368110953598e-06; - double arcsec2rad(double x) { return x * RAD_PER_ARCSEC; } - double arcsec2distsq(double x) { return rad2distsq(arcsec2rad(x)); } - double arcsec2dist(double arcInArcSec) { return std::sqrt(arcsec2distsq(arcInArcSec)); } - constexpr double ARCSEC_PER_DEG = 3600.0; - double deg2arcsec(double x) { return x * ARCSEC_PER_DEG; } - double deg2dist(double arcInDegrees) { return arcsec2dist(deg2arcsec(arcInDegrees)); } - - const int radectohealpix(double ra, double dec, int Nside) { - return xyztohealpix(radec2x(ra,dec), radec2y(ra,dec), radec2z(ra,dec), Nside); - } + double deg2rad (double d) { return d * sm::mathconst::deg2rad; } + double rad2deg (double r) { return r * sm::mathconst::rad2deg; } - int64_t radectohealpixlf(double ra, double dec, int Nside, double* dx, double* dy) { - return xyztohealpixlf(radec2x(ra,dec), radec2y(ra,dec), radec2z(ra,dec), Nside, dx, dy); - } + double z2dec(double z) { return std::asin(z); } + double xy2ra(double x, double y) { + double a = std::atan2(y, x); + if (a < 0) { a += sm::mathconst::two_pi; } + return a; + } + void xyz2radec(double x, double y, double z, double *ra, double *dec) { + if (ra) { *ra = xy2ra(x, y); } + if (dec) { *dec = z2dec(z); } + } + void xyzarr2radec(const double* xyz, double *ra, double *dec) { + xyz2radec(xyz[0], xyz[1], xyz[2], ra, dec); + } + void xyzarr2radecdeg(const double* xyz, double *ra, double *dec) { + xyzarr2radec(xyz, ra, dec); + if (ra) { *ra = rad2deg(*ra); } + if (dec) { *dec = rad2deg(*dec); } + } - const int64_t radectohealpixl(double ra, double dec, int Nside) { - return xyztohealpixl(radec2x(ra,dec), radec2y(ra,dec), radec2z(ra,dec), Nside); - } + void radec2xyzarr(double ra, double dec, double* xyz) { + double cosdec = std::cos(dec); + xyz[0] = cosdec * std::cos(ra); + xyz[1] = cosdec * std::sin(ra); + xyz[2] = std::sin(dec); + } + void radecdeg2xyzarr(double ra, double dec, double* xyz) { + radec2xyzarr(deg2rad(ra),deg2rad(dec), xyz); + } - int radectohealpixf(double ra, double dec, int Nside, double* dx, double* dy) { - return xyztohealpixf(radec2x(ra,dec), radec2y(ra,dec), radec2z(ra,dec), Nside, dx, dy); - } + double rad2distsq(double x) { return 2.0 * (1.0 - std::cos(x)); } // inverse of distsq2arc; cosine law. + constexpr double RAD_PER_ARCSEC = 4.8481368110953598e-06; + double arcsec2rad(double x) { return x * RAD_PER_ARCSEC; } + double arcsec2distsq(double x) { return rad2distsq(arcsec2rad(x)); } + double arcsec2dist(double arcInArcSec) { return std::sqrt(arcsec2distsq(arcInArcSec)); } + constexpr double ARCSEC_PER_DEG = 3600.0; + double deg2arcsec(double x) { return x * ARCSEC_PER_DEG; } + double deg2dist(double arcInDegrees) { return arcsec2dist(deg2arcsec(arcInDegrees)); } + + const int radectohealpix(double ra, double dec, int Nside) { + return xyztohealpix(radec2x(ra,dec), radec2y(ra,dec), radec2z(ra,dec), Nside); + } - const int radecdegtohealpix(double ra, double dec, int Nside) { - return radectohealpix(deg2rad(ra), deg2rad(dec), Nside); - } + int64_t radectohealpixlf(double ra, double dec, int Nside, double* dx, double* dy) { + return xyztohealpixlf(radec2x(ra,dec), radec2y(ra,dec), radec2z(ra,dec), Nside, dx, dy); + } - const int64_t radecdegtohealpixl(double ra, double dec, int Nside) { - return radectohealpixl(deg2rad(ra), deg2rad(dec), Nside); - } + const int64_t radectohealpixl(double ra, double dec, int Nside) { + return xyztohealpixl(radec2x(ra,dec), radec2y(ra,dec), radec2z(ra,dec), Nside); + } - int64_t radecdegtohealpixlf(double ra, double dec, int Nside, double* dx, double* dy) { - return radectohealpixlf(deg2rad(ra), deg2rad(dec), Nside, dx, dy); - } + int radectohealpixf(double ra, double dec, int Nside, double* dx, double* dy) { + return xyztohealpixf(radec2x(ra,dec), radec2y(ra,dec), radec2z(ra,dec), Nside, dx, dy); + } - int radecdegtohealpixf(double ra, double dec, int Nside, double* dx, double* dy) { - return radectohealpixf(deg2rad(ra), deg2rad(dec), Nside, dx, dy); - } + const int radecdegtohealpix(double ra, double dec, int Nside) { + return radectohealpix(deg2rad(ra), deg2rad(dec), Nside); + } - int xyzarrtohealpix(const double* xyz, int Nside) { - return xyztohealpix(xyz[0], xyz[1], xyz[2], Nside); - } + const int64_t radecdegtohealpixl(double ra, double dec, int Nside) { + return radectohealpixl(deg2rad(ra), deg2rad(dec), Nside); + } - int64_t xyzarrtohealpixl(const double* xyz, int Nside) { - return xyztohealpixl(xyz[0], xyz[1], xyz[2], Nside); - } + int64_t radecdegtohealpixlf(double ra, double dec, int Nside, double* dx, double* dy) { + return radectohealpixlf(deg2rad(ra), deg2rad(dec), Nside, dx, dy); + } - int xyzarrtohealpixf(const double* xyz,int Nside, double* p_dx, double* p_dy) { - return xyztohealpixf(xyz[0], xyz[1], xyz[2], Nside, p_dx, p_dy); - } + int radecdegtohealpixf(double ra, double dec, int Nside, double* dx, double* dy) { + return radectohealpixf(deg2rad(ra), deg2rad(dec), Nside, dx, dy); + } - static void hp_to_xyz(hp_t* hp, int Nside, - double dx, double dy, - double* rx, double *ry, double *rz) { - int chp; - bool equatorial = true; - double zfactor = 1.0; - int xp, yp; - double x, y, z; - double phi; - double rad; - - hp_decompose(hp, &chp, &xp, &yp); - - // this is x,y position in the healpix reference frame - x = xp + dx; - y = yp + dy; - - if (isnorthpolar(chp)) { - if ((x + y) > Nside) { - equatorial = false; - zfactor = 1.0; - } - } - if (issouthpolar(chp)) { - if ((x + y) < Nside) { - equatorial = false; - zfactor = -1.0; - } - } + int xyzarrtohealpix(const double* xyz, int Nside) { + return xyztohealpix(xyz[0], xyz[1], xyz[2], Nside); + } - if (equatorial) { - double zoff=0; - double phioff=0; - x /= (double)Nside; - y /= (double)Nside; - - if (chp <= 3) { - // north - phioff = 1.0; - } else if (chp <= 7) { - // equator - zoff = -1.0; - chp -= 4; - } else if (chp <= 11) { - // south - phioff = 1.0; - zoff = -2.0; - chp -= 8; - } else { - // should never get here - assert(0); - } + int64_t xyzarrtohealpixl(const double* xyz, int Nside) { + return xyztohealpixl(xyz[0], xyz[1], xyz[2], Nside); + } - z = 2.0/3.0*(x + y + zoff); - phi = sm::mathconst::pi_over_4*(x - y + phioff + 2*chp); + int xyzarrtohealpixf(const double* xyz,int Nside, double* p_dx, double* p_dy) { + return xyztohealpixf(xyz[0], xyz[1], xyz[2], Nside, p_dx, p_dy); + } + static void hp_to_xyz(hp_t* hp, int Nside, + double dx, double dy, + double* rx, double *ry, double *rz) { + int chp; + bool equatorial = true; + double zfactor = 1.0; + int xp, yp; + double x, y, z; + double phi; + double rad; + + hp_decompose(hp, &chp, &xp, &yp); + + // this is x,y position in the healpix reference frame + x = xp + dx; + y = yp + dy; + + if (isnorthpolar(chp)) { + if ((x + y) > Nside) { + equatorial = false; + zfactor = 1.0; + } + } + if (issouthpolar(chp)) { + if ((x + y) < Nside) { + equatorial = false; + zfactor = -1.0; + } + } + + if (equatorial) { + double zoff=0; + double phioff=0; + x /= (double)Nside; + y /= (double)Nside; + + if (chp <= 3) { + // north + phioff = 1.0; + } else if (chp <= 7) { + // equator + zoff = -1.0; + chp -= 4; + } else if (chp <= 11) { + // south + phioff = 1.0; + zoff = -2.0; + chp -= 8; } else { - /* - Rearrange eqns (19) and (20) to find phi_t in terms of x,y. + // should never get here + assert(0); + } - y = Ns - k in eq(19) - x - Ns - k in eq(20) + z = 2.0/3.0*(x + y + zoff); + phi = sm::mathconst::pi_over_4*(x - y + phioff + 2*chp); - (Ns - y)^2 / (Ns - x)^2 = (2 phi_t)^2 / (2 phi_t - pi)^2 + } else { + /* + Rearrange eqns (19) and (20) to find phi_t in terms of x,y. - Recall than y<=Ns, x<=Ns and 0<=phi_t::pi * (Nside-y) / (2.0 * ((Nside-x) + (Nside-y))); - } + (Ns - y) (pi - 2 phi_t) = 2 phi_t (Ns - x) + (Ns - y) pi = 2 phi_t (Ns - x + Ns - y) + phi_t = pi (Ns-y) / (2 (Ns - x) + (Ns - y)) + */ + double phi_t; - if (phi_t < sm::mathconst::pi_over_4) { - z = 1.0 - mysquare(sm::mathconst::pi * (Nside - x) / ((2.0 * phi_t - sm::mathconst::pi) * Nside)) / 3.0; - } else { - z = 1.0 - mysquare(sm::mathconst::pi * (Nside - y) / (2.0 * phi_t * Nside)) / 3.0; - } - assert(0.0 <= std::abs(z) && std::abs(z) <= 1.0); - z *= zfactor; - assert(0.0 <= std::abs(z) && std::abs(z) <= 1.0); - - // The big healpix determines the phi offset - if (issouthpolar(chp)) - phi = sm::mathconst::pi_over_2 * (chp-8) + phi_t; - else - phi = sm::mathconst::pi_over_2 * chp + phi_t; + if (zfactor == -1.0) { + std::swap (x, y); + x = (Nside - x); + y = (Nside - y); } - if (phi < 0.0) - phi += sm::mathconst::two_pi; + if (y == Nside && x == Nside) { + phi_t = 0.0; + } else { + phi_t = sm::mathconst::pi * (Nside-y) / (2.0 * ((Nside-x) + (Nside-y))); + } - rad = std::sqrt(1.0 - z*z); - *rx = rad * std::cos(phi); - *ry = rad * std::sin(phi); - *rz = z; - } + if (phi_t < sm::mathconst::pi_over_4) { + z = 1.0 - mysquare(sm::mathconst::pi * (Nside - x) / ((2.0 * phi_t - sm::mathconst::pi) * Nside)) / 3.0; + } else { + z = 1.0 - mysquare(sm::mathconst::pi * (Nside - y) / (2.0 * phi_t * Nside)) / 3.0; + } + assert(0.0 <= std::abs(z) && std::abs(z) <= 1.0); + z *= zfactor; + assert(0.0 <= std::abs(z) && std::abs(z) <= 1.0); - void healpix_to_xyz(int ihp, int Nside, - double dx, double dy, - double* px, double *py, double *pz) { - hp_t hp; - inttohp(ihp, &hp, Nside); - hp_to_xyz(&hp, Nside, dx, dy, px, py, pz); + // The big healpix determines the phi offset + if (issouthpolar(chp)) + phi = sm::mathconst::pi_over_2 * (chp-8) + phi_t; + else + phi = sm::mathconst::pi_over_2 * chp + phi_t; } - void healpixl_to_radecdeg(int64_t ihp, int Nside, double dx, double dy, - double* ra, double* dec) { - hp_t hp; - double xyz[3]; - intltohp(ihp, &hp, Nside); - hp_to_xyz(&hp, Nside, dx, dy, xyz, xyz+1, xyz+2); - xyzarr2radecdeg(xyz, ra, dec); - } + if (phi < 0.0) + phi += sm::mathconst::two_pi; - void healpix_to_xyzarr(int ihp, int Nside, - double dx, double dy, - double* xyz) { - hp_t hp; - inttohp(ihp, &hp, Nside); - hp_to_xyz(&hp, Nside, dx, dy, xyz, xyz+1, xyz+2); - } + rad = std::sqrt(1.0 - z*z); + *rx = rad * std::cos(phi); + *ry = rad * std::sin(phi); + *rz = z; + } - void healpixl_to_xyzarr(int64_t ihp, int Nside, double dx, double dy, - double* xyz) { - hp_t hp; - longtohp(ihp, &hp, Nside); - hp_to_xyz(&hp, Nside, dx, dy, xyz, xyz+1, xyz+2); - } + void healpix_to_xyz(int ihp, int Nside, + double dx, double dy, + double* px, double *py, double *pz) { + hp_t hp; + inttohp(ihp, &hp, Nside); + hp_to_xyz(&hp, Nside, dx, dy, px, py, pz); + } - void healpix_to_radec(int hp, int Nside, - double dx, double dy, + void healpixl_to_radecdeg(int64_t ihp, int Nside, double dx, double dy, double* ra, double* dec) { - double xyz[3]; - healpix_to_xyzarr(hp, Nside, dx, dy, xyz); - xyzarr2radec(xyz, ra, dec); - } - - void healpix_to_radecdeg(int hp, int Nside, - double dx, double dy, - double* ra, double* dec) { - double xyz[3]; - healpix_to_xyzarr(hp, Nside, dx, dy, xyz); - xyzarr2radecdeg(xyz, ra, dec); - } + hp_t hp; + double xyz[3]; + intltohp(ihp, &hp, Nside); + hp_to_xyz(&hp, Nside, dx, dy, xyz, xyz+1, xyz+2); + xyzarr2radecdeg(xyz, ra, dec); + } - void healpix_to_radecarr(int hp, int Nside, - double dx, double dy, - double* radec) { - double xyz[3]; - healpix_to_xyzarr(hp, Nside, dx, dy, xyz); - xyzarr2radec(xyz, radec, radec+1); - } + void healpix_to_xyzarr(int ihp, int Nside, + double dx, double dy, + double* xyz) { + hp_t hp; + inttohp(ihp, &hp, Nside); + hp_to_xyz(&hp, Nside, dx, dy, xyz, xyz+1, xyz+2); + } - void healpix_to_radecdegarr(int hp, int Nside, - double dx, double dy, - double* radec) { - double xyz[3]; - healpix_to_xyzarr(hp, Nside, dx, dy, xyz); - xyzarr2radecdeg(xyz, radec, radec+1); - } + void healpixl_to_xyzarr(int64_t ihp, int Nside, double dx, double dy, + double* xyz) { + hp_t hp; + longtohp(ihp, &hp, Nside); + hp_to_xyz(&hp, Nside, dx, dy, xyz, xyz+1, xyz+2); + } - struct neighbour_dirn { - double x, y; - double dx, dy; - }; - - int healpix_get_neighbours_within_range_radec(double ra, double dec, double radius, - int* healpixes, int Nside) { - double xyz[3]; - double r; - radecdeg2xyzarr(ra, dec, xyz); - r = deg2dist(radius); - return healpix_get_neighbours_within_range(xyz, r, healpixes, Nside); - } + void healpix_to_radec(int hp, int Nside, + double dx, double dy, + double* ra, double* dec) { + double xyz[3]; + healpix_to_xyzarr(hp, Nside, dx, dy, xyz); + xyzarr2radec(xyz, ra, dec); + } - double distsq(const double* d1, const double* d2, int D) { - double dist2; - int i; - dist2 = 0.0; - for (i=0; i 0); - if (Nside <= 0) { - printf("healpix_get_neighbours_within_range: Nside must be > 0.\n"); - return -1; - } + struct neighbour_dirn { + double x, y; + double dx, dy; + }; + + int healpix_get_neighbours_within_range_radec(double ra, double dec, double radius, + int* healpixes, int Nside) { + double xyz[3]; + double r; + radecdeg2xyzarr(ra, dec, xyz); + r = deg2dist(radius); + return healpix_get_neighbours_within_range(xyz, r, healpixes, Nside); + } - hp = xyzarrtohealpixf(xyz, Nside, &fx, &fy); - healpixes[nhp] = hp; - nhp++; - - { - struct neighbour_dirn dirs[] = { - // edges - { fx, 0, 0, -1 }, - { fx, 1, 0, 1 }, - { 0 , fy,-1, 0 }, - { 1 , fy, 1, 0 }, - // bottom corner - { 0, 0, -1, 1 }, - { 0, 0, -1, 0 }, - { 0, 0, -1, -1 }, - { 0, 0, 0, -1 }, - { 0, 0, 1, -1 }, - // right corner - { 1, 0, 1, 1 }, - { 1, 0, 1, 0 }, - { 1, 0, 1, -1 }, - { 1, 0, 0, -1 }, - { 1, 0, -1, -1 }, - // left corner - { 0, 1, 1, 1 }, - { 0, 1, 0, 1 }, - { 0, 1, -1, 1 }, - { 0, 1, -1, 0 }, - { 0, 1, -1, -1 }, - // top corner - { 1, 1, -1, 1 }, - { 1, 1, 0, 1 }, - { 1, 1, 1, 1 }, - { 1, 1, 1, 0 }, - { 1, 1, 1, -1 }, - }; - int ndirs = sizeof(dirs) / sizeof(struct neighbour_dirn); - - double ptx, pty, ptdx, ptdy; - int pthp; - - for (i=0; ix; - pty = dir->y; - ptdx = dir->dx; - ptdy = dir->dy; - - // pt = point on the edge nearest to the query point. - // FIXME -- check that this is true, esp in the polar regions! - healpix_to_xyzarr(hp, Nside, ptx, pty, pt); - d2 = distsq(pt, xyz, 3); - - // delta vector should be outside the healpix - assert((ptx+step*ptdx < 0) || - (ptx+step*ptdx > 1) || - (pty+step*ptdy < 0) || - (pty+step*ptdy > 1)); - - if (d2 > range*range) - continue; - - // compute dx and dy directions that are toward the interior of - // the healpix. - stepdirx = (ptx < step) ? 1 : -1; - stepdiry = (pty < step) ? 1 : -1; - - // take steps in those directions. - healpix_to_xyzarr(hp, Nside, ptx + stepdirx * step, pty, ptstepx); - healpix_to_xyzarr(hp, Nside, ptx, pty + stepdiry * step, ptstepy); - - // convert the steps into dx,dy vectors. - for (j=0; j<3; j++) { - ptstepx[j] = stepdirx * (ptstepx[j] - pt[j]); - ptstepy[j] = stepdiry * (ptstepy[j] - pt[j]); - } - - // take a small step in the specified direction. - for (j=0; j<3; j++) - across[j] = pt[j] + ptdx * ptstepx[j] + ptdy * ptstepy[j]; - - // see which healpix is at the end of the step. - normalize_3(across); - pthp = xyzarrtohealpix(across, Nside); - - healpixes[nhp] = pthp; - nhp++; - } - } + double distsq(const double* d1, const double* d2, int D) { + double dist2; + int i; + dist2 = 0.0; + for (i=0; i 0); + if (Nside <= 0) { + printf("healpix_get_neighbours_within_range: Nside must be > 0.\n"); + return -1; } -#ifdef ENABLE_FUNCTIONS_REQUIRING_QSORT // Avoiding permuted sort code, hiding these functions + hp = xyzarrtohealpixf(xyz, Nside, &fx, &fy); + healpixes[nhp] = hp; + nhp++; - double healpix_distance_to_xyz(int hp, int Nside, const double* xyz, - double* closestxyz) { - int thehp; - // corners - double cdx[4], cdy[4]; - double cdists[4]; - int corder[4]; - int i; - double dxA,dxB,dyA,dyB; - double dxmid, dymid; - double dist2A, dist2B; - double midxyz[3]; - double dist2mid = 0.0; - - double EPS = 1e-16; - - // If the point is actually inside the healpix, dist = 0. - thehp = xyzarrtohealpix(xyz, Nside); - if (thehp == hp) { - if (closestxyz) - std::memcpy(closestxyz, xyz, 3*sizeof(double)); - return 0; - } + { + struct neighbour_dirn dirs[] = { + // edges + { fx, 0, 0, -1 }, + { fx, 1, 0, 1 }, + { 0 , fy,-1, 0 }, + { 1 , fy, 1, 0 }, + // bottom corner + { 0, 0, -1, 1 }, + { 0, 0, -1, 0 }, + { 0, 0, -1, -1 }, + { 0, 0, 0, -1 }, + { 0, 0, 1, -1 }, + // right corner + { 1, 0, 1, 1 }, + { 1, 0, 1, 0 }, + { 1, 0, 1, -1 }, + { 1, 0, 0, -1 }, + { 1, 0, -1, -1 }, + // left corner + { 0, 1, 1, 1 }, + { 0, 1, 0, 1 }, + { 0, 1, -1, 1 }, + { 0, 1, -1, 0 }, + { 0, 1, -1, -1 }, + // top corner + { 1, 1, -1, 1 }, + { 1, 1, 0, 1 }, + { 1, 1, 1, 1 }, + { 1, 1, 1, 0 }, + { 1, 1, 1, -1 }, + }; + int ndirs = sizeof(dirs) / sizeof(struct neighbour_dirn); + + double ptx, pty, ptdx, ptdy; + int pthp; + + for (i=0; ix; + pty = dir->y; + ptdx = dir->dx; + ptdy = dir->dy; + + // pt = point on the edge nearest to the query point. + // FIXME -- check that this is true, esp in the polar regions! + healpix_to_xyzarr(hp, Nside, ptx, pty, pt); + d2 = distsq(pt, xyz, 3); + + // delta vector should be outside the healpix + assert((ptx+step*ptdx < 0) || + (ptx+step*ptdx > 1) || + (pty+step*ptdy < 0) || + (pty+step*ptdy > 1)); + + if (d2 > range*range) + continue; + + // compute dx and dy directions that are toward the interior of + // the healpix. + stepdirx = (ptx < step) ? 1 : -1; + stepdiry = (pty < step) ? 1 : -1; + + // take steps in those directions. + healpix_to_xyzarr(hp, Nside, ptx + stepdirx * step, pty, ptstepx); + healpix_to_xyzarr(hp, Nside, ptx, pty + stepdiry * step, ptstepy); + + // convert the steps into dx,dy vectors. + for (j=0; j<3; j++) { + ptstepx[j] = stepdirx * (ptstepx[j] - pt[j]); + ptstepy[j] = stepdiry * (ptstepy[j] - pt[j]); + } - // Find two nearest corners. - for (i=0; i<4; i++) { - double cxyz[3]; - cdx[i] = i/2; - cdy[i] = i%2; - healpix_to_xyzarr(hp, Nside, cdx[i], cdy[i], cxyz); - cdists[i] = distsq(xyz, cxyz, 3); - } - permutation_init(corder, 4); - permuted_sort(cdists, sizeof(double), compare_doubles_asc, corder, 4); - // now "corder" [0] and [1] are the indices of the two nearest corners. + // take a small step in the specified direction. + for (j=0; j<3; j++) + across[j] = pt[j] + ptdx * ptstepx[j] + ptdy * ptstepy[j]; - // Binary search for closest dx,dy. - dxA = cdx[corder[0]]; - dyA = cdy[corder[0]]; - dist2A = cdists[corder[0]]; - dxB = cdx[corder[1]]; - dyB = cdy[corder[1]]; - dist2B = cdists[corder[1]]; - // the closest two points should share an edge... unless we're in some - // weird configuration like the opposite side of the sphere. - if (!((dxA == dxB) || (dyA == dyB))) { - // weird configuration -- return the closest corner. - if (closestxyz) - healpix_to_xyzarr(hp, Nside, cdx[corder[0]], cdy[corder[0]], closestxyz); - return distsq2deg(cdists[corder[0]]); + // see which healpix is at the end of the step. + normalize_3(across); + pthp = xyzarrtohealpix(across, Nside); + + healpixes[nhp] = pthp; + nhp++; } - assert(dxA == dxB || dyA == dyB); - assert(dist2A <= dist2B); - - while (1) { - dxmid = (dxA + dxB) / 2.0; - dymid = (dyA + dyB) / 2.0; - // converged to EPS? - if ((dxA != dxB && (std::abs(dxmid - dxA) < EPS || std::abs(dxmid - dxB) < EPS)) || - (dyA != dyB && (std::abs(dymid - dyA) < EPS || std::abs(dymid - dyB) < EPS))) - break; - healpix_to_xyzarr(hp, Nside, dxmid, dymid, midxyz); - dist2mid = distsq(xyz, midxyz, 3); + } - if ((dist2mid >= dist2A) && (dist2mid >= dist2B)) + // Remove duplicates... + for (i=0; i= dist2A) && (dist2mid >= dist2B)) + break; + if (dist2A < dist2B) { + dist2B = dist2mid; + dxB = dxmid; + dyB = dymid; + } else { + dist2A = dist2mid; + dxA = dxmid; + dyA = dymid; + } } - int healpix_within_range_of_radec(int hp, int Nside, double ra, double dec, - double radius) { - // the trivial implementation... - return (healpix_distance_to_radec(hp, Nside, ra, dec, NULL) <= radius); - } - int healpix_within_range_of_xyz(int hp, int Nside, const double* xyz, - double radius) { - return (healpix_distance_to_xyz(hp, Nside, xyz, NULL) <= radius); + // Check whether endpoint A is actually closer. + dist2A = cdists[corder[0]]; + if (dist2A < dist2mid) { + dxA = cdx[corder[0]]; + dyA = cdy[corder[0]]; + healpix_to_xyzarr(hp, Nside, dxA, dyA, midxyz); + dist2mid = dist2A; } - void healpix_radec_bounds(int hp, int nside, - double* p_ralo, double* p_rahi, - double* p_declo, double* p_dechi) { - // corners! - double ralo,rahi,declo,dechi; - double ra,dec; - double dx, dy; - ralo = declo = LARGE_VAL; - rahi = dechi = -LARGE_VAL; - for (dy=0; dy<2; dy+=1.0) { - for (dx=0; dx<2; dx+=1.0) { - healpix_to_radecdeg(hp, nside, dx, dy, &ra, &dec); - // FIXME -- wrap-around. - ralo = std::min(ra, ralo); - rahi = std::max(ra, rahi); - declo = std::min(dec, declo); - dechi = std::max(dec, dechi); - } + if (closestxyz) + std::memcpy(closestxyz, midxyz, 3*sizeof(double)); + + return distsq2deg(dist2mid); + } + + double healpix_distance_to_radec(int hp, int Nside, double ra, double dec, + double* closestradec) { + double xyz[3]; + double closestxyz[3]; + double dist; + radecdeg2xyzarr(ra, dec, xyz); + dist = healpix_distance_to_xyz(hp, Nside, xyz, closestxyz); + if (closestradec) + xyzarr2radecdegarr(closestxyz, closestradec); + return dist; + } + + int healpix_within_range_of_radec(int hp, int Nside, double ra, double dec, + double radius) { + // the trivial implementation... + return (healpix_distance_to_radec(hp, Nside, ra, dec, NULL) <= radius); + } + int healpix_within_range_of_xyz(int hp, int Nside, const double* xyz, + double radius) { + return (healpix_distance_to_xyz(hp, Nside, xyz, NULL) <= radius); + } + + void healpix_radec_bounds(int hp, int nside, + double* p_ralo, double* p_rahi, + double* p_declo, double* p_dechi) { + // corners! + double ralo,rahi,declo,dechi; + double ra,dec; + double dx, dy; + ralo = declo = LARGE_VAL; + rahi = dechi = -LARGE_VAL; + for (dy=0; dy<2; dy+=1.0) { + for (dx=0; dx<2; dx+=1.0) { + healpix_to_radecdeg(hp, nside, dx, dy, &ra, &dec); + // FIXME -- wrap-around. + ralo = std::min(ra, ralo); + rahi = std::max(ra, rahi); + declo = std::min(dec, declo); + dechi = std::max(dec, dechi); } - if (p_ralo) *p_ralo = ralo; - if (p_rahi) *p_rahi = rahi; - if (p_declo) *p_declo = declo; - if (p_dechi) *p_dechi = dechi; } + if (p_ralo) *p_ralo = ralo; + if (p_rahi) *p_rahi = rahi; + if (p_declo) *p_declo = declo; + if (p_dechi) *p_dechi = dechi; + } #endif - } // namespace am -} // namespace hp +} // namespace diff --git a/mplot/healpix/healpix_bare.hpp b/mplot/healpix/healpix_bare.hpp index 281dddfb..8043dff2 100644 --- a/mplot/healpix/healpix_bare.hpp +++ b/mplot/healpix/healpix_bare.hpp @@ -31,8 +31,8 @@ #include // The healpix namespace contains code from the HEALPix C library, slightly modified. -namespace hp { - +namespace hp +{ // Lookup tables static const int jrll[] = { 2,2,2,2,3,3,3,3,4,4,4,4 }; static const int jpll[] = { 1,3,5,7,0,2,4,6,1,3,5,7 }; diff --git a/mplot/keys.h b/mplot/keys.h index 7bdd731b..1b244673 100644 --- a/mplot/keys.h +++ b/mplot/keys.h @@ -6,8 +6,8 @@ // numeric keys are slightly different. GLFW_KEY_0 is mplot::key::n0, GLFW_KEY_1 is // mplot::key::n1 etc. (because mplot::key::1 would be illegal C++ code). -namespace mplot { - +namespace mplot +{ struct key { // The unknown key diff --git a/mplot/loadpng.h b/mplot/loadpng.h index fb3c4d4d..6909f070 100644 --- a/mplot/loadpng.h +++ b/mplot/loadpng.h @@ -17,8 +17,8 @@ #include #include -namespace mplot { - +namespace mplot +{ /* * Wrap lodepng::decode to load a PNG from file, placing the data into the * image_data array. Figure out based on the type of T, how to scale the numbers. diff --git a/mplot/qt/keycodes.h b/mplot/qt/keycodes.h index 3501ea09..515becb5 100644 --- a/mplot/qt/keycodes.h +++ b/mplot/qt/keycodes.h @@ -3,334 +3,332 @@ #include #include -namespace mplot { - namespace qt { +namespace mplot::qt +{ + // Pass in a Qt key code and receive back the mplot (i.e. GLFW) key code. + constexpr int qtkey_to_mplotkey (int qt_keycode) + { + int mkc = mplot::key::unknown; + switch (qt_keycode) { - // Pass in a Qt key code and receive back the mplot (i.e. GLFW) key code. - constexpr int qtkey_to_mplotkey (int qt_keycode) - { - int mkc = mplot::key::unknown; - switch (qt_keycode) { + case Qt::Key_Space: + mkc = mplot::key::space; + break; + case Qt::Key_Apostrophe: + mkc = mplot::key::apostrophe; + break; + case Qt::Key_Comma: + mkc = mplot::key::comma; + break; + case Qt::Key_Minus: + mkc = mplot::key::minus; + break; + case Qt::Key_Period: + mkc = mplot::key::period; + break; + case Qt::Key_Slash: + mkc = mplot::key::slash; + break; - case Qt::Key_Space: - mkc = mplot::key::space; - break; - case Qt::Key_Apostrophe: - mkc = mplot::key::apostrophe; - break; - case Qt::Key_Comma: - mkc = mplot::key::comma; - break; - case Qt::Key_Minus: - mkc = mplot::key::minus; - break; - case Qt::Key_Period: - mkc = mplot::key::period; - break; - case Qt::Key_Slash: - mkc = mplot::key::slash; - break; + case Qt::Key_0: + mkc = mplot::key::n0; + break; + case Qt::Key_1: + mkc = mplot::key::n1; + break; + case Qt::Key_2: + mkc = mplot::key::n2; + break; + case Qt::Key_3: + mkc = mplot::key::n3; + break; + case Qt::Key_4: + mkc = mplot::key::n4; + break; + case Qt::Key_5: + mkc = mplot::key::n5; + break; + case Qt::Key_6: + mkc = mplot::key::n6; + break; + case Qt::Key_7: + mkc = mplot::key::n7; + break; + case Qt::Key_8: + mkc = mplot::key::n8; + break; + case Qt::Key_9: + mkc = mplot::key::n9; + break; - case Qt::Key_0: - mkc = mplot::key::n0; - break; - case Qt::Key_1: - mkc = mplot::key::n1; - break; - case Qt::Key_2: - mkc = mplot::key::n2; - break; - case Qt::Key_3: - mkc = mplot::key::n3; - break; - case Qt::Key_4: - mkc = mplot::key::n4; - break; - case Qt::Key_5: - mkc = mplot::key::n5; - break; - case Qt::Key_6: - mkc = mplot::key::n6; - break; - case Qt::Key_7: - mkc = mplot::key::n7; - break; - case Qt::Key_8: - mkc = mplot::key::n8; - break; - case Qt::Key_9: - mkc = mplot::key::n9; - break; + case Qt::Key_Semicolon: + mkc = mplot::key::semicolon; + break; + case Qt::Key_Equal: + mkc = mplot::key::equal; + break; - case Qt::Key_Semicolon: - mkc = mplot::key::semicolon; - break; - case Qt::Key_Equal: - mkc = mplot::key::equal; - break; + case Qt::Key_A: + mkc = mplot::key::a; + break; + case Qt::Key_B: + mkc = mplot::key::b; + break; + case Qt::Key_C: + mkc = mplot::key::c; + break; + case Qt::Key_D: + mkc = mplot::key::d; + break; + case Qt::Key_E: + mkc = mplot::key::e; + break; + case Qt::Key_F: + mkc = mplot::key::f; + break; + case Qt::Key_G: + mkc = mplot::key::g; + break; + case Qt::Key_H: + mkc = mplot::key::h; + break; + case Qt::Key_I: + mkc = mplot::key::i; + break; + case Qt::Key_J: + mkc = mplot::key::j; + break; + case Qt::Key_K: + mkc = mplot::key::k; + break; + case Qt::Key_L: + mkc = mplot::key::l; + break; + case Qt::Key_M: + mkc = mplot::key::m; + break; + case Qt::Key_N: + mkc = mplot::key::n; + break; + case Qt::Key_O: + mkc = mplot::key::o; + break; + case Qt::Key_P: + mkc = mplot::key::p; + break; + case Qt::Key_Q: + mkc = mplot::key::q; + break; + case Qt::Key_R: + mkc = mplot::key::r; + break; + case Qt::Key_S: + mkc = mplot::key::s; + break; + case Qt::Key_T: + mkc = mplot::key::t; + break; + case Qt::Key_U: + mkc = mplot::key::u; + break; + case Qt::Key_V: + mkc = mplot::key::v; + break; + case Qt::Key_W: + mkc = mplot::key::w; + break; + case Qt::Key_X: + mkc = mplot::key::x; + break; + case Qt::Key_Y: + mkc = mplot::key::y; + break; + case Qt::Key_Z: + mkc = mplot::key::z; + break; - case Qt::Key_A: - mkc = mplot::key::a; - break; - case Qt::Key_B: - mkc = mplot::key::b; - break; - case Qt::Key_C: - mkc = mplot::key::c; - break; - case Qt::Key_D: - mkc = mplot::key::d; - break; - case Qt::Key_E: - mkc = mplot::key::e; - break; - case Qt::Key_F: - mkc = mplot::key::f; - break; - case Qt::Key_G: - mkc = mplot::key::g; - break; - case Qt::Key_H: - mkc = mplot::key::h; - break; - case Qt::Key_I: - mkc = mplot::key::i; - break; - case Qt::Key_J: - mkc = mplot::key::j; - break; - case Qt::Key_K: - mkc = mplot::key::k; - break; - case Qt::Key_L: - mkc = mplot::key::l; - break; - case Qt::Key_M: - mkc = mplot::key::m; - break; - case Qt::Key_N: - mkc = mplot::key::n; - break; - case Qt::Key_O: - mkc = mplot::key::o; - break; - case Qt::Key_P: - mkc = mplot::key::p; - break; - case Qt::Key_Q: - mkc = mplot::key::q; - break; - case Qt::Key_R: - mkc = mplot::key::r; - break; - case Qt::Key_S: - mkc = mplot::key::s; - break; - case Qt::Key_T: - mkc = mplot::key::t; - break; - case Qt::Key_U: - mkc = mplot::key::u; - break; - case Qt::Key_V: - mkc = mplot::key::v; - break; - case Qt::Key_W: - mkc = mplot::key::w; - break; - case Qt::Key_X: - mkc = mplot::key::x; - break; - case Qt::Key_Y: - mkc = mplot::key::y; - break; - case Qt::Key_Z: - mkc = mplot::key::z; - break; + case Qt::Key_BracketLeft: + mkc = mplot::key::left_bracket; + break; + case Qt::Key_Backslash: + mkc = mplot::key::backslash; + break; + case Qt::Key_BracketRight: + mkc = mplot::key::right_bracket; + break; + case Qt::Key_QuoteLeft: + mkc = mplot::key::grave_accent; + break; + case Qt::Key_exclamdown: // guess + mkc = mplot::key::world_1; + break; + case Qt::Key_cent: // guess + mkc = mplot::key::world_2; + break; - case Qt::Key_BracketLeft: - mkc = mplot::key::left_bracket; - break; - case Qt::Key_Backslash: - mkc = mplot::key::backslash; - break; - case Qt::Key_BracketRight: - mkc = mplot::key::right_bracket; - break; - case Qt::Key_QuoteLeft: - mkc = mplot::key::grave_accent; - break; - case Qt::Key_exclamdown: // guess - mkc = mplot::key::world_1; - break; - case Qt::Key_cent: // guess - mkc = mplot::key::world_2; - break; + case Qt::Key_Escape: + mkc = mplot::key::escape; + break; + case Qt::Key_Enter: + mkc = mplot::key::enter; + break; + case Qt::Key_Tab: + mkc = mplot::key::tab; + break; + case Qt::Key_Backspace: + mkc = mplot::key::backspace; + break; + case Qt::Key_Insert: + mkc = mplot::key::insert; + break; + case Qt::Key_Delete: + mkc = mplot::key::delete_key; + break; + case Qt::Key_Right: + mkc = mplot::key::right; + break; + case Qt::Key_Left: + mkc = mplot::key::left; + break; + case Qt::Key_Down: + mkc = mplot::key::down; + break; + case Qt::Key_Up: + mkc = mplot::key::up; + break; + case Qt::Key_PageUp: + mkc = mplot::key::page_up; + break; + case Qt::Key_PageDown: + mkc = mplot::key::page_down; + break; + case Qt::Key_Home: + mkc = mplot::key::home; + break; + case Qt::Key_End: + mkc = mplot::key::end; + break; + case Qt::Key_CapsLock: + mkc = mplot::key::caps_lock; + break; + case Qt::Key_ScrollLock: + mkc = mplot::key::scroll_lock; + break; + case Qt::Key_NumLock: + mkc = mplot::key::num_lock; + break; + case Qt::Key_Print: + mkc = mplot::key::print_screen; + break; + case Qt::Key_Pause: + mkc = mplot::key::pause; + break; - case Qt::Key_Escape: - mkc = mplot::key::escape; - break; - case Qt::Key_Enter: - mkc = mplot::key::enter; - break; - case Qt::Key_Tab: - mkc = mplot::key::tab; - break; - case Qt::Key_Backspace: - mkc = mplot::key::backspace; - break; - case Qt::Key_Insert: - mkc = mplot::key::insert; - break; - case Qt::Key_Delete: - mkc = mplot::key::delete_key; - break; - case Qt::Key_Right: - mkc = mplot::key::right; - break; - case Qt::Key_Left: - mkc = mplot::key::left; - break; - case Qt::Key_Down: - mkc = mplot::key::down; - break; - case Qt::Key_Up: - mkc = mplot::key::up; - break; - case Qt::Key_PageUp: - mkc = mplot::key::page_up; - break; - case Qt::Key_PageDown: - mkc = mplot::key::page_down; - break; - case Qt::Key_Home: - mkc = mplot::key::home; - break; - case Qt::Key_End: - mkc = mplot::key::end; - break; - case Qt::Key_CapsLock: - mkc = mplot::key::caps_lock; - break; - case Qt::Key_ScrollLock: - mkc = mplot::key::scroll_lock; - break; - case Qt::Key_NumLock: - mkc = mplot::key::num_lock; - break; - case Qt::Key_Print: - mkc = mplot::key::print_screen; - break; - case Qt::Key_Pause: - mkc = mplot::key::pause; - break; + case Qt::Key_F1: + mkc = mplot::key::f1; + break; + case Qt::Key_F2: + mkc = mplot::key::f2; + break; + case Qt::Key_F3: + mkc = mplot::key::f3; + break; + case Qt::Key_F4: + mkc = mplot::key::f4; + break; + case Qt::Key_F5: + mkc = mplot::key::f5; + break; + case Qt::Key_F6: + mkc = mplot::key::f6; + break; + case Qt::Key_F7: + mkc = mplot::key::f7; + break; + case Qt::Key_F8: + mkc = mplot::key::f8; + break; + case Qt::Key_F9: + mkc = mplot::key::f9; + break; + case Qt::Key_F10: + mkc = mplot::key::f10; + break; + case Qt::Key_F11: + mkc = mplot::key::f11; + break; + case Qt::Key_F12: + mkc = mplot::key::f12; + break; + case Qt::Key_F13: + mkc = mplot::key::f13; + break; + case Qt::Key_F14: + mkc = mplot::key::f14; + break; + case Qt::Key_F15: + mkc = mplot::key::f15; + break; + case Qt::Key_F16: + mkc = mplot::key::f16; + break; + case Qt::Key_F17: + mkc = mplot::key::f17; + break; + case Qt::Key_F18: + mkc = mplot::key::f18; + break; + case Qt::Key_F19: + mkc = mplot::key::f19; + break; + case Qt::Key_F20: + mkc = mplot::key::f20; + break; + case Qt::Key_F21: + mkc = mplot::key::f21; + break; + case Qt::Key_F22: + mkc = mplot::key::f22; + break; + case Qt::Key_F23: + mkc = mplot::key::f23; + break; + case Qt::Key_F24: + mkc = mplot::key::f24; + break; + case Qt::Key_F25: + mkc = mplot::key::f25; + break; - case Qt::Key_F1: - mkc = mplot::key::f1; - break; - case Qt::Key_F2: - mkc = mplot::key::f2; - break; - case Qt::Key_F3: - mkc = mplot::key::f3; - break; - case Qt::Key_F4: - mkc = mplot::key::f4; - break; - case Qt::Key_F5: - mkc = mplot::key::f5; - break; - case Qt::Key_F6: - mkc = mplot::key::f6; - break; - case Qt::Key_F7: - mkc = mplot::key::f7; - break; - case Qt::Key_F8: - mkc = mplot::key::f8; - break; - case Qt::Key_F9: - mkc = mplot::key::f9; - break; - case Qt::Key_F10: - mkc = mplot::key::f10; - break; - case Qt::Key_F11: - mkc = mplot::key::f11; - break; - case Qt::Key_F12: - mkc = mplot::key::f12; - break; - case Qt::Key_F13: - mkc = mplot::key::f13; - break; - case Qt::Key_F14: - mkc = mplot::key::f14; - break; - case Qt::Key_F15: - mkc = mplot::key::f15; - break; - case Qt::Key_F16: - mkc = mplot::key::f16; - break; - case Qt::Key_F17: - mkc = mplot::key::f17; - break; - case Qt::Key_F18: - mkc = mplot::key::f18; - break; - case Qt::Key_F19: - mkc = mplot::key::f19; - break; - case Qt::Key_F20: - mkc = mplot::key::f20; - break; - case Qt::Key_F21: - mkc = mplot::key::f21; - break; - case Qt::Key_F22: - mkc = mplot::key::f22; - break; - case Qt::Key_F23: - mkc = mplot::key::f23; - break; - case Qt::Key_F24: - mkc = mplot::key::f24; - break; - case Qt::Key_F25: - mkc = mplot::key::f25; - break; + case Qt::Key_division: + mkc = mplot::key::kp_divide; + break; + case Qt::Key_multiply: + mkc = mplot::key::kp_multiply; + break; - case Qt::Key_division: - mkc = mplot::key::kp_divide; - break; - case Qt::Key_multiply: - mkc = mplot::key::kp_multiply; - break; + case Qt::Key_Shift: + mkc = mplot::key::left_shift; + break; + case Qt::Key_Control: + mkc = mplot::key::left_control; + break; + case Qt::Key_Alt: + mkc = mplot::key::left_alt; + break; + case Qt::Key_AltGr: + mkc = mplot::key::right_alt; + break; + case Qt::Key_Super_L: + mkc = mplot::key::left_super; + break; + case Qt::Key_Super_R: + mkc = mplot::key::right_super; + break; - case Qt::Key_Shift: - mkc = mplot::key::left_shift; - break; - case Qt::Key_Control: - mkc = mplot::key::left_control; - break; - case Qt::Key_Alt: - mkc = mplot::key::left_alt; - break; - case Qt::Key_AltGr: - mkc = mplot::key::right_alt; - break; - case Qt::Key_Super_L: - mkc = mplot::key::left_super; - break; - case Qt::Key_Super_R: - mkc = mplot::key::right_super; - break; - - default: - break; - } - return mkc; + default: + break; } + return mkc; } } diff --git a/mplot/qt/viswidget.h b/mplot/qt/viswidget.h index 2d33911b..6625a3f2 100644 --- a/mplot/qt/viswidget.h +++ b/mplot/qt/viswidget.h @@ -19,146 +19,144 @@ namespace mplot { using win_t = QOpenGLWidget; } // We need to be able to convert from Qt keycodes to mplot keycodes #include -namespace mplot { - namespace qt { - - // This must match the QOpenGLFunctions_4_1_Core class you derive from - constexpr int gl_version = mplot::gl::version_4_1; - - struct OpenGLProcAddressHelper { - inline static QOpenGLContext *ctx; - - static QFunctionPointer getProcAddress(const char *name) { - return ctx->getProcAddress(name); - } - }; - - // A mplot::VisualOwnable-based widget - struct viswidget : public QOpenGLWidget +namespace mplot::qt +{ + // This must match the QOpenGLFunctions_4_1_Core class you derive from + constexpr int gl_version = mplot::gl::version_4_1; + + struct OpenGLProcAddressHelper { + inline static QOpenGLContext *ctx; + + static QFunctionPointer getProcAddress(const char *name) { + return ctx->getProcAddress(name); + } + }; + + // A mplot::VisualOwnable-based widget + struct viswidget : public QOpenGLWidget + { + // Unlike the GLFW or mplot-in-a-QWindow schemes, we hold the mplot::VisualOwnable + // inside the widget. + mplot::VisualOwnableNoMX v; + + // In your Qt code, build VisualModels that should be added to the scene and add them to this. + std::vector>> newvisualmodels; + std::vector*> model_ptrs; + + // if >-1, then that model needs a reinit. + int needs_reinit = -1; + void set_model_needs_reinit (int model_idx, bool reinit_required = true) { - // Unlike the GLFW or mplot-in-a-QWindow schemes, we hold the mplot::VisualOwnable - // inside the widget. - mplot::VisualOwnableNoMX v; - - // In your Qt code, build VisualModels that should be added to the scene and add them to this. - std::vector>> newvisualmodels; - std::vector*> model_ptrs; - - // if >-1, then that model needs a reinit. - int needs_reinit = -1; - void set_model_needs_reinit (int model_idx, bool reinit_required = true) - { - this->needs_reinit = reinit_required ? model_idx : -1; - } - - viswidget (QWidget* parent = 0) : QOpenGLWidget(parent) - { - // You have to set the format in the constructor - QSurfaceFormat format; - format.setDepthBufferSize (4); - format.setSamples (4); - format.setStencilBufferSize (8); - format.setVersion (4, 1); - format.setProfile (QSurfaceFormat::CoreProfile); - this->setFormat (format); - this->setUpdateBehavior (QOpenGLWidget::NoPartialUpdate); - this->setFocusPolicy (Qt::StrongFocus); // ensure keyPressEvents reach us - } - - protected: - - void initializeGL() override - { - // Make sure we can call gl functions - OpenGLProcAddressHelper::ctx = context(); - v.init_glad(OpenGLProcAddressHelper::getProcAddress); - // Switch on multisampling anti-aliasing (with the num samples set in constructor) - glEnable (GL_MULTISAMPLE); - // Initialise mplot::VisualOwnable - v.init (this); - } - - void resizeGL (int w, int h) override - { - double dpr = this->devicePixelRatio(); - v.set_winsize (static_cast(std::round(w * dpr)), - static_cast(std::round(h * dpr))); - this->update(); - } - - void paintGL() override - { - if (!this->newvisualmodels.empty()) { - // Now we iterate through newvisualmodels, finalize them and add them to mplot::Visual - for (unsigned int i = 0; i < newvisualmodels.size(); ++i) { - this->newvisualmodels[i]->finalize(); - this->model_ptrs.push_back (this->v.addVisualModel (this->newvisualmodels[i])); - } - this->newvisualmodels.clear(); - } - if (this->needs_reinit > -1) { - this->model_ptrs[this->needs_reinit]->reinit(); - this->needs_reinit = -1; - } - v.render(); - } + this->needs_reinit = reinit_required ? model_idx : -1; + } - void mousePressEvent (QMouseEvent* event) override - { - v.set_cursorpos (event->x(), event->y()); - int bflg = event->button(); - int b = mplot::mousebutton::unhandled; - b = bflg & Qt::LeftButton ? mplot::mousebutton::left : b; - b = bflg & Qt::RightButton ? mplot::mousebutton::right : b; - int mflg = event->modifiers(); - int mods = 0; - if (mflg & Qt::ControlModifier) { mods |= mplot::keymod::control; } - if (mflg & Qt::ShiftModifier) { mods |= mplot::keymod::shift; } - v.mouse_button_callback (b, mplot::keyaction::press, mods); - event->accept(); - } + viswidget (QWidget* parent = 0) : QOpenGLWidget(parent) + { + // You have to set the format in the constructor + QSurfaceFormat format; + format.setDepthBufferSize (4); + format.setSamples (4); + format.setStencilBufferSize (8); + format.setVersion (4, 1); + format.setProfile (QSurfaceFormat::CoreProfile); + this->setFormat (format); + this->setUpdateBehavior (QOpenGLWidget::NoPartialUpdate); + this->setFocusPolicy (Qt::StrongFocus); // ensure keyPressEvents reach us + } + + protected: + + void initializeGL() override + { + // Make sure we can call gl functions + OpenGLProcAddressHelper::ctx = context(); + v.init_glad(OpenGLProcAddressHelper::getProcAddress); + // Switch on multisampling anti-aliasing (with the num samples set in constructor) + glEnable (GL_MULTISAMPLE); + // Initialise mplot::VisualOwnable + v.init (this); + } + + void resizeGL (int w, int h) override + { + double dpr = this->devicePixelRatio(); + v.set_winsize (static_cast(std::round(w * dpr)), + static_cast(std::round(h * dpr))); + this->update(); + } - void mouseMoveEvent (QMouseEvent* event) override - { - if (v.cursor_position_callback (event->x(), event->y())) { - this->update(); + void paintGL() override + { + if (!this->newvisualmodels.empty()) { + // Now we iterate through newvisualmodels, finalize them and add them to mplot::Visual + for (unsigned int i = 0; i < newvisualmodels.size(); ++i) { + this->newvisualmodels[i]->finalize(); + this->model_ptrs.push_back (this->v.addVisualModel (this->newvisualmodels[i])); } - event->accept(); + this->newvisualmodels.clear(); } - - void mouseReleaseEvent (QMouseEvent* event) override - { - v.set_cursorpos (event->x(), event->y()); - int bflg = event->button(); - int b = mplot::mousebutton::unhandled; - b = bflg & Qt::LeftButton ? mplot::mousebutton::left : b; - b = bflg & Qt::RightButton ? mplot::mousebutton::right : b; - v.mouse_button_callback (b, mplot::keyaction::release); - event->accept(); + if (this->needs_reinit > -1) { + this->model_ptrs[this->needs_reinit]->reinit(); + this->needs_reinit = -1; } + v.render(); + } - void wheelEvent (QWheelEvent* event) override - { - QPoint numSteps = event->angleDelta() / 120; - v.scroll_callback (numSteps.x(), numSteps.y()); + void mousePressEvent (QMouseEvent* event) override + { + v.set_cursorpos (event->x(), event->y()); + int bflg = event->button(); + int b = mplot::mousebutton::unhandled; + b = bflg & Qt::LeftButton ? mplot::mousebutton::left : b; + b = bflg & Qt::RightButton ? mplot::mousebutton::right : b; + int mflg = event->modifiers(); + int mods = 0; + if (mflg & Qt::ControlModifier) { mods |= mplot::keymod::control; } + if (mflg & Qt::ShiftModifier) { mods |= mplot::keymod::shift; } + v.mouse_button_callback (b, mplot::keyaction::press, mods); + event->accept(); + } + + void mouseMoveEvent (QMouseEvent* event) override + { + if (v.cursor_position_callback (event->x(), event->y())) { this->update(); - event->accept(); } + event->accept(); + } - // Keyboard events... - void keyPressEvent (QKeyEvent* event) override - { - int mflg = event->modifiers(); - int mods = 0; - if (mflg & Qt::ControlModifier) { mods |= mplot::keymod::control; } - if (mflg & Qt::ShiftModifier) { mods |= mplot::keymod::shift; } - int mplot_keycode = mplot::qt::qtkey_to_mplotkey (event->key()); - // Could be keyaction::REPEAT in GLFW - if (v.key_callback (mplot_keycode, 0, mplot::keyaction::press, mods)) { - this->update(); - } - event->accept(); + void mouseReleaseEvent (QMouseEvent* event) override + { + v.set_cursorpos (event->x(), event->y()); + int bflg = event->button(); + int b = mplot::mousebutton::unhandled; + b = bflg & Qt::LeftButton ? mplot::mousebutton::left : b; + b = bflg & Qt::RightButton ? mplot::mousebutton::right : b; + v.mouse_button_callback (b, mplot::keyaction::release); + event->accept(); + } + + void wheelEvent (QWheelEvent* event) override + { + QPoint numSteps = event->angleDelta() / 120; + v.scroll_callback (numSteps.x(), numSteps.y()); + this->update(); + event->accept(); + } + + // Keyboard events... + void keyPressEvent (QKeyEvent* event) override + { + int mflg = event->modifiers(); + int mods = 0; + if (mflg & Qt::ControlModifier) { mods |= mplot::keymod::control; } + if (mflg & Qt::ShiftModifier) { mods |= mplot::keymod::shift; } + int mplot_keycode = mplot::qt::qtkey_to_mplotkey (event->key()); + // Could be keyaction::REPEAT in GLFW + if (v.key_callback (mplot_keycode, 0, mplot::keyaction::press, mods)) { + this->update(); } - }; - } // qt -} // mplot + event->accept(); + } + }; +} // namespace diff --git a/mplot/qt/viswidget_mx.h b/mplot/qt/viswidget_mx.h index 0b316720..7f344c56 100644 --- a/mplot/qt/viswidget_mx.h +++ b/mplot/qt/viswidget_mx.h @@ -20,174 +20,172 @@ namespace mplot { using win_t = QOpenGLWidget; } #include -namespace mplot { - namespace qt { +namespace mplot::qt +{ + constexpr int gl_version = mplot::gl::version_4_1; - constexpr int gl_version = mplot::gl::version_4_1; + // How many separate OpenGL contexts (i.e. how many viswidget_mxs) to support in one Qt program? + constexpr int max_contexts = 32; // with 32 we use 32 * 8 bytes of memory = 256 bytes. - // How many separate OpenGL contexts (i.e. how many viswidget_mxs) to support in one Qt program? - constexpr int max_contexts = 32; // with 32 we use 32 * 8 bytes of memory = 256 bytes. - - // A container class to manage a getProcAddress function from each viswidget_mx/QOpenGLWidget context - struct gl_contexts + // A container class to manage a getProcAddress function from each viswidget_mx/QOpenGLWidget context + struct gl_contexts + { + static auto& i() // The instance public function. { - static auto& i() // The instance public function. - { - static gl_contexts instance; - return instance; - } + static gl_contexts instance; + return instance; + } - // Set the context. Store the QOpenGLContext pointer into ctx_ptrs[widget_index]. - template - void set_context (QOpenGLContext* _ctx) - { - static_assert (widget_index < mplot::qt::max_contexts); - ctx_ptrs[widget_index] = _ctx; - } - - // The static getProcAddress function for the index widget_index. - template - static QFunctionPointer getProcAddress (const char* name) - { - static_assert (widget_index < mplot::qt::max_contexts); - if (mplot::qt::gl_contexts::i().ctx_ptrs[widget_index] == nullptr) { return nullptr; } - return mplot::qt::gl_contexts::i().ctx_ptrs[widget_index]->getProcAddress (name); - } - - private: - gl_contexts() { ctx_ptrs = { nullptr }; } - ~gl_contexts() {} - std::array ctx_ptrs; - }; - - // A mplot::Visual widget. You have to choose and provide a widget_index in the range [0, - // mplot::gl::max_contexts) + // Set the context. Store the QOpenGLContext pointer into ctx_ptrs[widget_index]. template - struct viswidget_mx : public QOpenGLWidget //, protected QOpenGLFunctions_4_1_Core + void set_context (QOpenGLContext* _ctx) { - // Unlike the GLFW or mplot-in-a-QWindow schemes, we hold the mplot::VisualOwnableMX - // inside the widget. - mplot::VisualOwnableMX v; - - // In your Qt code, build VisualModels that should be added to the scene and add them to this. - std::vector>> newvisualmodels; - std::vector*> model_ptrs; - - // if >-1, then that model needs a reinit. - int needs_reinit = -1; - void set_model_needs_reinit (int model_idx, bool reinit_required = true) - { - this->needs_reinit = reinit_required ? model_idx : -1; - } + static_assert (widget_index < mplot::qt::max_contexts); + ctx_ptrs[widget_index] = _ctx; + } - viswidget_mx (QWidget* parent = 0) : QOpenGLWidget(parent) - { - static_assert (widget_index < mplot::qt::max_contexts); - // You have to set the format in the constructor - QSurfaceFormat format; - format.setDepthBufferSize (4); - format.setSamples (4); - format.setStencilBufferSize (8); - format.setVersion (4, 1); - format.setProfile (QSurfaceFormat::CoreProfile); - this->setFormat (format); - this->setUpdateBehavior (QOpenGLWidget::NoPartialUpdate); - this->setFocusPolicy (Qt::StrongFocus); // ensure keyPressEvents reach us - } - - protected: - - void initializeGL() override - { - // Initialise mplot::Visual, which must set up GLAD's access to the OpenGL context - mplot::qt::gl_contexts::i().set_context (this->context()); - v.init_glad (mplot::qt::gl_contexts::getProcAddress); - v.init (this); - - // Switch on multisampling anti-aliasing (with the num samples set in constructor) - v.glfn->Enable (GL_MULTISAMPLE); - } + // The static getProcAddress function for the index widget_index. + template + static QFunctionPointer getProcAddress (const char* name) + { + static_assert (widget_index < mplot::qt::max_contexts); + if (mplot::qt::gl_contexts::i().ctx_ptrs[widget_index] == nullptr) { return nullptr; } + return mplot::qt::gl_contexts::i().ctx_ptrs[widget_index]->getProcAddress (name); + } + + private: + gl_contexts() { ctx_ptrs = { nullptr }; } + ~gl_contexts() {} + std::array ctx_ptrs; + }; + + // A mplot::Visual widget. You have to choose and provide a widget_index in the range [0, + // mplot::gl::max_contexts) + template + struct viswidget_mx : public QOpenGLWidget //, protected QOpenGLFunctions_4_1_Core + { + // Unlike the GLFW or mplot-in-a-QWindow schemes, we hold the mplot::VisualOwnableMX + // inside the widget. + mplot::VisualOwnableMX v; + + // In your Qt code, build VisualModels that should be added to the scene and add them to this. + std::vector>> newvisualmodels; + std::vector*> model_ptrs; + + // if >-1, then that model needs a reinit. + int needs_reinit = -1; + void set_model_needs_reinit (int model_idx, bool reinit_required = true) + { + this->needs_reinit = reinit_required ? model_idx : -1; + } - void resizeGL (int w, int h) override - { - double dpr = this->devicePixelRatio(); - v.set_winsize (static_cast(std::round(w * dpr)), static_cast(std::round(h * dpr))); - this->update(); - } + viswidget_mx (QWidget* parent = 0) : QOpenGLWidget(parent) + { + static_assert (widget_index < mplot::qt::max_contexts); + // You have to set the format in the constructor + QSurfaceFormat format; + format.setDepthBufferSize (4); + format.setSamples (4); + format.setStencilBufferSize (8); + format.setVersion (4, 1); + format.setProfile (QSurfaceFormat::CoreProfile); + this->setFormat (format); + this->setUpdateBehavior (QOpenGLWidget::NoPartialUpdate); + this->setFocusPolicy (Qt::StrongFocus); // ensure keyPressEvents reach us + } + + protected: + + void initializeGL() override + { + // Initialise mplot::Visual, which must set up GLAD's access to the OpenGL context + mplot::qt::gl_contexts::i().set_context (this->context()); + v.init_glad (mplot::qt::gl_contexts::getProcAddress); + v.init (this); - void paintGL() override - { - if (!this->newvisualmodels.empty()) { - // Now we iterate through newvisualmodels, finalize them and add them to mplot::Visual - for (unsigned int i = 0; i < newvisualmodels.size(); ++i) { - this->newvisualmodels[i]->finalize(); - this->model_ptrs.push_back (this->v.addVisualModel (this->newvisualmodels[i])); - } - this->newvisualmodels.clear(); - } - if (this->needs_reinit > -1) { - this->model_ptrs[this->needs_reinit]->reinit(); - this->needs_reinit = -1; - } - v.render(); - } + // Switch on multisampling anti-aliasing (with the num samples set in constructor) + v.glfn->Enable (GL_MULTISAMPLE); + } - void mousePressEvent (QMouseEvent* event) override - { - v.set_cursorpos (event->x(), event->y()); - int bflg = event->button(); - int b = mplot::mousebutton::unhandled; - b = bflg & Qt::LeftButton ? mplot::mousebutton::left : b; - b = bflg & Qt::RightButton ? mplot::mousebutton::right : b; - int mflg = event->modifiers(); - int mods = 0; - if (mflg & Qt::ControlModifier) { mods |= mplot::keymod::control; } - if (mflg & Qt::ShiftModifier) { mods |= mplot::keymod::shift; } - v.mouse_button_callback (b, mplot::keyaction::press, mods); - event->accept(); - } + void resizeGL (int w, int h) override + { + double dpr = this->devicePixelRatio(); + v.set_winsize (static_cast(std::round(w * dpr)), static_cast(std::round(h * dpr))); + this->update(); + } - void mouseMoveEvent (QMouseEvent* event) override - { - if (v.cursor_position_callback (event->x(), event->y())) { - this->update(); + void paintGL() override + { + if (!this->newvisualmodels.empty()) { + // Now we iterate through newvisualmodels, finalize them and add them to mplot::Visual + for (unsigned int i = 0; i < newvisualmodels.size(); ++i) { + this->newvisualmodels[i]->finalize(); + this->model_ptrs.push_back (this->v.addVisualModel (this->newvisualmodels[i])); } - event->accept(); + this->newvisualmodels.clear(); } - - void mouseReleaseEvent (QMouseEvent* event) override - { - v.set_cursorpos (event->x(), event->y()); - int bflg = event->button(); - int b = mplot::mousebutton::unhandled; - b = bflg & Qt::LeftButton ? mplot::mousebutton::left : b; - b = bflg & Qt::RightButton ? mplot::mousebutton::right : b; - v.mouse_button_callback (b, mplot::keyaction::release); - event->accept(); + if (this->needs_reinit > -1) { + this->model_ptrs[this->needs_reinit]->reinit(); + this->needs_reinit = -1; } + v.render(); + } - void wheelEvent (QWheelEvent* event) override - { - QPoint numSteps = event->angleDelta() / 120; - v.scroll_callback (numSteps.x(), numSteps.y()); + void mousePressEvent (QMouseEvent* event) override + { + v.set_cursorpos (event->x(), event->y()); + int bflg = event->button(); + int b = mplot::mousebutton::unhandled; + b = bflg & Qt::LeftButton ? mplot::mousebutton::left : b; + b = bflg & Qt::RightButton ? mplot::mousebutton::right : b; + int mflg = event->modifiers(); + int mods = 0; + if (mflg & Qt::ControlModifier) { mods |= mplot::keymod::control; } + if (mflg & Qt::ShiftModifier) { mods |= mplot::keymod::shift; } + v.mouse_button_callback (b, mplot::keyaction::press, mods); + event->accept(); + } + + void mouseMoveEvent (QMouseEvent* event) override + { + if (v.cursor_position_callback (event->x(), event->y())) { this->update(); - event->accept(); } + event->accept(); + } - // Keyboard events... - void keyPressEvent (QKeyEvent* event) override - { - int mflg = event->modifiers(); - int mods = 0; - if (mflg & Qt::ControlModifier) { mods |= mplot::keymod::control; } - if (mflg & Qt::ShiftModifier) { mods |= mplot::keymod::shift; } - int mplot_keycode = mplot::qt::qtkey_to_mplotkey (event->key()); - // Could be keyaction::REPEAT in GLFW - if (v.key_callback (mplot_keycode, 0, mplot::keyaction::press, mods)) { - this->update(); - } - event->accept(); + void mouseReleaseEvent (QMouseEvent* event) override + { + v.set_cursorpos (event->x(), event->y()); + int bflg = event->button(); + int b = mplot::mousebutton::unhandled; + b = bflg & Qt::LeftButton ? mplot::mousebutton::left : b; + b = bflg & Qt::RightButton ? mplot::mousebutton::right : b; + v.mouse_button_callback (b, mplot::keyaction::release); + event->accept(); + } + + void wheelEvent (QWheelEvent* event) override + { + QPoint numSteps = event->angleDelta() / 120; + v.scroll_callback (numSteps.x(), numSteps.y()); + this->update(); + event->accept(); + } + + // Keyboard events... + void keyPressEvent (QKeyEvent* event) override + { + int mflg = event->modifiers(); + int mods = 0; + if (mflg & Qt::ControlModifier) { mods |= mplot::keymod::control; } + if (mflg & Qt::ShiftModifier) { mods |= mplot::keymod::shift; } + int mplot_keycode = mplot::qt::qtkey_to_mplotkey (event->key()); + // Could be keyaction::REPEAT in GLFW + if (v.key_callback (mplot_keycode, 0, mplot::keyaction::press, mods)) { + this->update(); } - }; - } // qt -} // mplot + event->accept(); + } + }; +} // namespace diff --git a/mplot/unicode.h b/mplot/unicode.h index 8e009770..8d88d0c1 100644 --- a/mplot/unicode.h +++ b/mplot/unicode.h @@ -11,8 +11,8 @@ #include -namespace mplot::unicode { - +namespace mplot::unicode +{ /* * These constants are defined to make program code that uses unicode::toUtf8() * and unicode::append easier to read. You can also pass the raw codes. diff --git a/mplot/version.h b/mplot/version.h index 37890ddb..54550018 100644 --- a/mplot/version.h +++ b/mplot/version.h @@ -9,8 +9,8 @@ #include -namespace mplot { - +namespace mplot +{ //! A version definition for the whole of mathplot static constexpr unsigned int version_major = 1; static constexpr unsigned int version_minor = 0; diff --git a/mplot/wx/keycodes.h b/mplot/wx/keycodes.h index d45bb622..0b294b72 100644 --- a/mplot/wx/keycodes.h +++ b/mplot/wx/keycodes.h @@ -5,256 +5,254 @@ // WXK_ENTER WXK_APOSTROPHE and WXK_META have been omitted -namespace mplot { - namespace wx { +namespace mplot::wx +{ + // Pass in a wxWidgets key code and receive back the mplot (i.e. GLFW) key code. + constexpr int wxkey_to_mplotkey(int wx_keycode) + { + int mkc = mplot::key::unknown; + switch (wx_keycode) { - // Pass in a wxWidgets key code and receive back the mplot (i.e. GLFW) key code. - constexpr int wxkey_to_mplotkey(int wx_keycode) - { - int mkc = mplot::key::unknown; - switch (wx_keycode) { + case WXK_SPACE: + mkc = mplot::key::space; + break; + case ',': + mkc = mplot::key::comma; + break; + case '-': + mkc = mplot::key::minus; + break; + case '.': + mkc = mplot::key::period; + break; + case '/': + mkc = mplot::key::slash; + break; - case WXK_SPACE: - mkc = mplot::key::space; - break; - case ',': - mkc = mplot::key::comma; - break; - case '-': - mkc = mplot::key::minus; - break; - case '.': - mkc = mplot::key::period; - break; - case '/': - mkc = mplot::key::slash; - break; + case '0': + mkc = mplot::key::n0; + break; + case '1': + mkc = mplot::key::n1; + break; + case '2': + mkc = mplot::key::n2; + break; + case '3': + mkc = mplot::key::n3; + break; + case '4': + mkc = mplot::key::n4; + break; + case '5': + mkc = mplot::key::n5; + break; + case '6': + mkc = mplot::key::n6; + break; + case '7': + mkc = mplot::key::n7; + break; + case '8': + mkc = mplot::key::n8; + break; + case '9': + mkc = mplot::key::n9; + break; - case '0': - mkc = mplot::key::n0; - break; - case '1': - mkc = mplot::key::n1; - break; - case '2': - mkc = mplot::key::n2; - break; - case '3': - mkc = mplot::key::n3; - break; - case '4': - mkc = mplot::key::n4; - break; - case '5': - mkc = mplot::key::n5; - break; - case '6': - mkc = mplot::key::n6; - break; - case '7': - mkc = mplot::key::n7; - break; - case '8': - mkc = mplot::key::n8; - break; - case '9': - mkc = mplot::key::n9; - break; + case ';': + mkc = mplot::key::semicolon; + break; + case '=': + mkc = mplot::key::equal; + break; - case ';': - mkc = mplot::key::semicolon; - break; - case '=': - mkc = mplot::key::equal; - break; + case 'A': + mkc = mplot::key::a; + break; + case 'B': + mkc = mplot::key::b; + break; + case 'C': + mkc = mplot::key::c; + break; + case 'D': + mkc = mplot::key::d; + break; + case 'E': + mkc = mplot::key::e; + break; + case 'F': + mkc = mplot::key::f; + break; + case 'G': + mkc = mplot::key::g; + break; + case 'H': + mkc = mplot::key::h; + break; + case 'I': + mkc = mplot::key::i; + break; + case 'J': + mkc = mplot::key::j; + break; + case 'K': + mkc = mplot::key::k; + break; + case 'L': + mkc = mplot::key::l; + break; + case 'M': + mkc = mplot::key::m; + break; + case 'N': + mkc = mplot::key::n; + break; + case 'O': + mkc = mplot::key::o; + break; + case 'P': + mkc = mplot::key::p; + break; + case 'Q': + mkc = mplot::key::q; + break; + case 'R': + mkc = mplot::key::r; + break; + case 'S': + mkc = mplot::key::s; + break; + case 'T': + mkc = mplot::key::t; + break; + case 'U': + mkc = mplot::key::u; + break; + case 'V': + mkc = mplot::key::v; + break; + case 'W': + mkc = mplot::key::w; + break; + case 'X': + mkc = mplot::key::x; + break; + case 'Y': + mkc = mplot::key::y; + break; + case 'Z': + mkc = mplot::key::z; + break; - case 'A': - mkc = mplot::key::a; - break; - case 'B': - mkc = mplot::key::b; - break; - case 'C': - mkc = mplot::key::c; - break; - case 'D': - mkc = mplot::key::d; - break; - case 'E': - mkc = mplot::key::e; - break; - case 'F': - mkc = mplot::key::f; - break; - case 'G': - mkc = mplot::key::g; - break; - case 'H': - mkc = mplot::key::h; - break; - case 'I': - mkc = mplot::key::i; - break; - case 'J': - mkc = mplot::key::j; - break; - case 'K': - mkc = mplot::key::k; - break; - case 'L': - mkc = mplot::key::l; - break; - case 'M': - mkc = mplot::key::m; - break; - case 'N': - mkc = mplot::key::n; - break; - case 'O': - mkc = mplot::key::o; - break; - case 'P': - mkc = mplot::key::p; - break; - case 'Q': - mkc = mplot::key::q; - break; - case 'R': - mkc = mplot::key::r; - break; - case 'S': - mkc = mplot::key::s; - break; - case 'T': - mkc = mplot::key::t; - break; - case 'U': - mkc = mplot::key::u; - break; - case 'V': - mkc = mplot::key::v; - break; - case 'W': - mkc = mplot::key::w; - break; - case 'X': - mkc = mplot::key::x; - break; - case 'Y': - mkc = mplot::key::y; - break; - case 'Z': - mkc = mplot::key::z; - break; + case '[': + mkc = mplot::key::left_bracket; + break; + case '\\': + mkc = mplot::key::backslash; + break; + case ']': + mkc = mplot::key::right_bracket; + break; + case '`': + mkc = mplot::key::grave_accent; + break; - case '[': - mkc = mplot::key::left_bracket; - break; - case '\\': - mkc = mplot::key::backslash; - break; - case ']': - mkc = mplot::key::right_bracket; - break; - case '`': - mkc = mplot::key::grave_accent; - break; + case WXK_ESCAPE: + mkc = mplot::key::escape; + break; + case WXK_TAB: + mkc = mplot::key::tab; + break; + case WXK_BACK: + mkc = mplot::key::backspace; + break; + case WXK_INSERT: + mkc = mplot::key::insert; + break; + case WXK_DELETE: + mkc = mplot::key::delete_key; + break; - case WXK_ESCAPE: - mkc = mplot::key::escape; - break; - case WXK_TAB: - mkc = mplot::key::tab; - break; - case WXK_BACK: - mkc = mplot::key::backspace; - break; - case WXK_INSERT: - mkc = mplot::key::insert; - break; - case WXK_DELETE: - mkc = mplot::key::delete_key; - break; + case WXK_RIGHT: + mkc = mplot::key::right; + break; + case WXK_LEFT: + mkc = mplot::key::left; + break; + case WXK_DOWN: + mkc = mplot::key::down; + break; + case WXK_UP: + mkc = mplot::key::up; + break; - case WXK_RIGHT: - mkc = mplot::key::right; - break; - case WXK_LEFT: - mkc = mplot::key::left; - break; - case WXK_DOWN: - mkc = mplot::key::down; - break; - case WXK_UP: - mkc = mplot::key::up; - break; + case WXK_PAGEUP: + mkc = mplot::key::page_up; + break; + case WXK_PAGEDOWN: + mkc = mplot::key::page_down; + break; + case WXK_HOME: + mkc = mplot::key::home; + break; + case WXK_END: + mkc = mplot::key::end; + break; - case WXK_PAGEUP: - mkc = mplot::key::page_up; - break; - case WXK_PAGEDOWN: - mkc = mplot::key::page_down; - break; - case WXK_HOME: - mkc = mplot::key::home; - break; - case WXK_END: - mkc = mplot::key::end; - break; + case WXK_F1: + mkc = mplot::key::f1; + break; + case WXK_F2: + mkc = mplot::key::f2; + break; + case WXK_F3: + mkc = mplot::key::f3; + break; + case WXK_F4: + mkc = mplot::key::f4; + break; + case WXK_F5: + mkc = mplot::key::f5; + break; + case WXK_F6: + mkc = mplot::key::f6; + break; + case WXK_F7: + mkc = mplot::key::f7; + break; + case WXK_F8: + mkc = mplot::key::f8; + break; + case WXK_F9: + mkc = mplot::key::f9; + break; + case WXK_F10: + mkc = mplot::key::f10; + break; + case WXK_F11: + mkc = mplot::key::f11; + break; + case WXK_F12: + mkc = mplot::key::f12; + break; - case WXK_F1: - mkc = mplot::key::f1; - break; - case WXK_F2: - mkc = mplot::key::f2; - break; - case WXK_F3: - mkc = mplot::key::f3; - break; - case WXK_F4: - mkc = mplot::key::f4; - break; - case WXK_F5: - mkc = mplot::key::f5; - break; - case WXK_F6: - mkc = mplot::key::f6; - break; - case WXK_F7: - mkc = mplot::key::f7; - break; - case WXK_F8: - mkc = mplot::key::f8; - break; - case WXK_F9: - mkc = mplot::key::f9; - break; - case WXK_F10: - mkc = mplot::key::f10; - break; - case WXK_F11: - mkc = mplot::key::f11; - break; - case WXK_F12: - mkc = mplot::key::f12; - break; + case WXK_SHIFT: + mkc = mplot::key::left_shift; + break; + case WXK_ALT: + mkc = mplot::key::left_alt; + break; + case WXK_CONTROL: + mkc = mplot::key::left_control; + break; - case WXK_SHIFT: - mkc = mplot::key::left_shift; - break; - case WXK_ALT: - mkc = mplot::key::left_alt; - break; - case WXK_CONTROL: - mkc = mplot::key::left_control; - break; - - default: - mkc = mplot::key::unknown; - break; - } - return mkc; + default: + mkc = mplot::key::unknown; + break; } + return mkc; + } - } // namespace wx -} // namespace mplot +} // namespace diff --git a/mplot/wx/viswx.h b/mplot/wx/viswx.h index ddb6ade7..0f821665 100644 --- a/mplot/wx/viswx.h +++ b/mplot/wx/viswx.h @@ -23,222 +23,220 @@ namespace mplot { using win_t = wxGLCanvas; } #include -namespace mplot { - namespace wx { - - // This is the OpenGL version you will attempt to create a context for. Example version: - // mplot::gl::version_4_1 - template - class Canvas : public wxGLCanvas +namespace mplot::wx +{ + // This is the OpenGL version you will attempt to create a context for. Example version: + // mplot::gl::version_4_1 + template + class Canvas : public wxGLCanvas + { + public: + Canvas (wxFrame* parent, const wxGLAttributes& canvasAttrs) + : wxGLCanvas(parent, canvasAttrs) { - public: - Canvas (wxFrame* parent, const wxGLAttributes& canvasAttrs) - : wxGLCanvas(parent, canvasAttrs) - { - wxGLContextAttrs ctxAttrs; - ctxAttrs.PlatformDefaults().CoreProfile().OGLVersion(mplot::gl::version::major(glver), - mplot::gl::version::minor(glver)).EndList(); - this->glContext = std::make_unique(this, nullptr, &ctxAttrs); - - if (!this->glContext->IsOK()) { - std::stringstream ee; - ee << "This sample needs an OpenGL " << mplot::gl::version::vstring(glver) << " capable driver."; - wxMessageBox (ee.str(), "OpenGL version error", wxOK | wxICON_INFORMATION, this); - } - - // Bind events to functions in the Canvas constructor - Bind (wxEVT_PAINT, &mplot::wx::Canvas::OnPaint, this); - Bind (wxEVT_SIZE, &mplot::wx::Canvas::OnSize, this); - Bind (wxEVT_MOTION, &mplot::wx::Canvas::OnMouseMove, this); - Bind (wxEVT_LEFT_DOWN, &mplot::wx::Canvas::OnMousePress, this); - Bind (wxEVT_RIGHT_DOWN, &mplot::wx::Canvas::OnMousePress, this); - Bind (wxEVT_LEFT_UP, &mplot::wx::Canvas::OnMouseRelease, this); - Bind (wxEVT_RIGHT_UP, &mplot::wx::Canvas::OnMouseRelease, this); - Bind (wxEVT_MOUSEWHEEL, &mplot::wx::Canvas::OnMouseWheel, this); - Bind (wxEVT_KEY_DOWN, &mplot::wx::Canvas::OnKeyPress, this); + wxGLContextAttrs ctxAttrs; + ctxAttrs.PlatformDefaults().CoreProfile().OGLVersion(mplot::gl::version::major(glver), + mplot::gl::version::minor(glver)).EndList(); + this->glContext = std::make_unique(this, nullptr, &ctxAttrs); + + if (!this->glContext->IsOK()) { + std::stringstream ee; + ee << "This sample needs an OpenGL " << mplot::gl::version::vstring(glver) << " capable driver."; + wxMessageBox (ee.str(), "OpenGL version error", wxOK | wxICON_INFORMATION, this); } - bool InitializeOpenGLFunctions() - { + // Bind events to functions in the Canvas constructor + Bind (wxEVT_PAINT, &mplot::wx::Canvas::OnPaint, this); + Bind (wxEVT_SIZE, &mplot::wx::Canvas::OnSize, this); + Bind (wxEVT_MOTION, &mplot::wx::Canvas::OnMouseMove, this); + Bind (wxEVT_LEFT_DOWN, &mplot::wx::Canvas::OnMousePress, this); + Bind (wxEVT_RIGHT_DOWN, &mplot::wx::Canvas::OnMousePress, this); + Bind (wxEVT_LEFT_UP, &mplot::wx::Canvas::OnMouseRelease, this); + Bind (wxEVT_RIGHT_UP, &mplot::wx::Canvas::OnMouseRelease, this); + Bind (wxEVT_MOUSEWHEEL, &mplot::wx::Canvas::OnMouseWheel, this); + Bind (wxEVT_KEY_DOWN, &mplot::wx::Canvas::OnKeyPress, this); + } + + bool InitializeOpenGLFunctions() + { #ifdef GLAD_OPTION_GL_MX - []() { static_assert(flag, "multi-context glad header is not supported in viswx"); }(); + []() { static_assert(flag, "multi-context glad header is not supported in viswx"); }(); #else - // Can we get GLADloadfunc from wx? Maybe need the internal loader version of glad? - int version = gladLoadGL (mygetprocaddress); - if (version == 0) { - wxLogError("OpenGL gladLoadGL initialization failed"); - return false; - } -#endif - return true; + // Can we get GLADloadfunc from wx? Maybe need the internal loader version of glad? + int version = gladLoadGL (mygetprocaddress); + if (version == 0) { + wxLogError("OpenGL gladLoadGL initialization failed"); + return false; } +#endif + return true; + } - bool InitializeOpenGL() - { - if (!this->glContext) { return false; } - SetCurrent (*this->glContext.get()); - if (!InitializeOpenGLFunctions()) { - wxMessageBox("Error: Could not initialize OpenGL function pointers.", - "OpenGL initialization error", wxOK | wxICON_INFORMATION, this); - return false; - } - // Switch on multisampling anti-aliasing (with the num samples set in constructor) - glEnable (GL_MULTISAMPLE); - // Initialise mplot::Visual - v.init (this); - this->glInitialized = true; - return this->glInitialized; + bool InitializeOpenGL() + { + if (!this->glContext) { return false; } + SetCurrent (*this->glContext.get()); + if (!InitializeOpenGLFunctions()) { + wxMessageBox("Error: Could not initialize OpenGL function pointers.", + "OpenGL initialization error", wxOK | wxICON_INFORMATION, this); + return false; } - - // Check if any of the VisualModels in the Visual need a reinit and then call Visual::render - void OnPaint ([[maybe_unused]] wxPaintEvent &event) - { - wxPaintDC dc(this); - if (!this->glInitialized) { return; } - SetCurrent(*this->glContext.get()); - if (!this->newvisualmodels.empty()) { - // Now we iterate through newvisualmodels, finalize them and add them to mplot::Visual - for (unsigned int i = 0; i < newvisualmodels.size(); ++i) { - this->newvisualmodels[i]->finalize(); - this->model_ptrs.push_back (this->v.addVisualModel (this->newvisualmodels[i])); - } - this->newvisualmodels.clear(); - } - if (this->needs_reinit > -1) { - this->model_ptrs[this->needs_reinit]->reinit(); - this->needs_reinit = -1; + // Switch on multisampling anti-aliasing (with the num samples set in constructor) + glEnable (GL_MULTISAMPLE); + // Initialise mplot::Visual + v.init (this); + this->glInitialized = true; + return this->glInitialized; + } + + // Check if any of the VisualModels in the Visual need a reinit and then call Visual::render + void OnPaint ([[maybe_unused]] wxPaintEvent &event) + { + wxPaintDC dc(this); + if (!this->glInitialized) { return; } + SetCurrent(*this->glContext.get()); + if (!this->newvisualmodels.empty()) { + // Now we iterate through newvisualmodels, finalize them and add them to mplot::Visual + for (unsigned int i = 0; i < newvisualmodels.size(); ++i) { + this->newvisualmodels[i]->finalize(); + this->model_ptrs.push_back (this->v.addVisualModel (this->newvisualmodels[i])); } - v.render(); - SwapBuffers(); + this->newvisualmodels.clear(); } - - void OnSize (wxSizeEvent &event) - { - bool firstApperance = IsShownOnScreen() && !this->glInitialized; - if (firstApperance) { InitializeOpenGL(); } - if (this->glInitialized) { - const wxSize size = event.GetSize() * GetContentScaleFactor(); - v.set_winsize (static_cast(size.x), static_cast(size.y)); - } - // Refresh(false); // maybe - event.Skip(); + if (this->needs_reinit > -1) { + this->model_ptrs[this->needs_reinit]->reinit(); + this->needs_reinit = -1; } + v.render(); + SwapBuffers(); + } - void OnMousePress (wxMouseEvent& event) - { - event.Skip(); - wxPoint pos = event.GetPosition(); - int x = pos.x; - int y = pos.y; - v.set_cursorpos (x, y); - int bflg = event.GetButton(); - int b = mplot::mousebutton::unhandled; - b = bflg == wxMOUSE_BTN_LEFT ? mplot::mousebutton::left : b; - b = bflg == wxMOUSE_BTN_RIGHT ? mplot::mousebutton::right : b; - int mflg = event.GetModifiers(); - int mods = 0; - if (mflg & wxMOD_CONTROL) { mods |= mplot::keymod::control; } - if (mflg & wxMOD_SHIFT) { mods |= mplot::keymod::shift; } - v.mouse_button_callback (b, mplot::keyaction::press, mods); - event.Skip(); + void OnSize (wxSizeEvent &event) + { + bool firstApperance = IsShownOnScreen() && !this->glInitialized; + if (firstApperance) { InitializeOpenGL(); } + if (this->glInitialized) { + const wxSize size = event.GetSize() * GetContentScaleFactor(); + v.set_winsize (static_cast(size.x), static_cast(size.y)); } + // Refresh(false); // maybe + event.Skip(); + } - void OnMouseMove (wxMouseEvent& event) - { - wxPoint pos = event.GetPosition(); - int x = pos.x; - int y = pos.y; - if (v.cursor_position_callback (x,y)) { Refresh (false); } - event.Skip(); + void OnMousePress (wxMouseEvent& event) + { + event.Skip(); + wxPoint pos = event.GetPosition(); + int x = pos.x; + int y = pos.y; + v.set_cursorpos (x, y); + int bflg = event.GetButton(); + int b = mplot::mousebutton::unhandled; + b = bflg == wxMOUSE_BTN_LEFT ? mplot::mousebutton::left : b; + b = bflg == wxMOUSE_BTN_RIGHT ? mplot::mousebutton::right : b; + int mflg = event.GetModifiers(); + int mods = 0; + if (mflg & wxMOD_CONTROL) { mods |= mplot::keymod::control; } + if (mflg & wxMOD_SHIFT) { mods |= mplot::keymod::shift; } + v.mouse_button_callback (b, mplot::keyaction::press, mods); + event.Skip(); + } + + void OnMouseMove (wxMouseEvent& event) + { + wxPoint pos = event.GetPosition(); + int x = pos.x; + int y = pos.y; + if (v.cursor_position_callback (x,y)) { Refresh (false); } + event.Skip(); + } + + void OnMouseRelease (wxMouseEvent& event) + { + event.Skip(); + wxPoint pos = event.GetPosition(); + int x = pos.x; + int y = pos.y; + v.set_cursorpos(x, y); + int bflg = event.GetButton(); + int b = mplot::mousebutton::unhandled; + b = bflg & wxMOUSE_BTN_LEFT ? mplot::mousebutton::left : b; + b = bflg & wxMOUSE_BTN_RIGHT ? mplot::mousebutton::right : b; + v.mouse_button_callback(b, mplot::keyaction::release); + } + + void OnMouseWheel (wxMouseEvent& event) + { + int direction = event.GetWheelRotation()/120; // 1 or -1 + wxPoint numSteps; + numSteps.x = 0; + numSteps.y = direction; + v.scroll_callback (numSteps.x, numSteps.y); + Refresh (false); + event.Skip(); + } + + void OnKeyPress (wxKeyEvent & event) + { + int mflg = event.GetModifiers(); + int mods = 0; + if (mflg & wxMOD_CONTROL) { + mods |= mplot::keymod::control; } - - void OnMouseRelease (wxMouseEvent& event) - { - event.Skip(); - wxPoint pos = event.GetPosition(); - int x = pos.x; - int y = pos.y; - v.set_cursorpos(x, y); - int bflg = event.GetButton(); - int b = mplot::mousebutton::unhandled; - b = bflg & wxMOUSE_BTN_LEFT ? mplot::mousebutton::left : b; - b = bflg & wxMOUSE_BTN_RIGHT ? mplot::mousebutton::right : b; - v.mouse_button_callback(b, mplot::keyaction::release); + if (mflg & wxMOD_SHIFT) { + mods |= mplot::keymod::shift; } - - void OnMouseWheel (wxMouseEvent& event) - { - int direction = event.GetWheelRotation()/120; // 1 or -1 - wxPoint numSteps; - numSteps.x = 0; - numSteps.y = direction; - v.scroll_callback (numSteps.x, numSteps.y); + int mplot_keycode = mplot::wx::wxkey_to_mplotkey(event.GetKeyCode()); + // Could be keyaction::REPEAT in GLFW + if (v.key_callback (mplot_keycode, 0, mplot::keyaction::press, mods)) { Refresh (false); - event.Skip(); - } - - void OnKeyPress (wxKeyEvent & event) - { - int mflg = event.GetModifiers(); - int mods = 0; - if (mflg & wxMOD_CONTROL) { - mods |= mplot::keymod::control; - } - if (mflg & wxMOD_SHIFT) { - mods |= mplot::keymod::shift; - } - int mplot_keycode = mplot::wx::wxkey_to_mplotkey(event.GetKeyCode()); - // Could be keyaction::REPEAT in GLFW - if (v.key_callback (mplot_keycode, 0, mplot::keyaction::press, mods)) { - Refresh (false); - } - event.Skip(); } + event.Skip(); + } - // API for user to say that model 4 (say) need to be reinitialized. - void set_model_needs_reinit (int model_idx, bool reinit_required = true) - { - this->needs_reinit = reinit_required ? model_idx : -1; - } - - // In your wx code, build VisualModels that should be added to the scene and add them to this. - std::vector>> newvisualmodels; - std::vector*> model_ptrs; - // if >-1, then that model needs a reinit. - int needs_reinit = -1; - - bool ready() { return this->glInitialized; } - - mplot::VisualOwnableNoMX v; - - private: - std::unique_ptr glContext; - bool glInitialized = false; - }; - - // mplot::wx::Frame is to be extended. Note that a default GL version of 4.1 is given here. - template - class Frame : public wxFrame + // API for user to say that model 4 (say) need to be reinitialized. + void set_model_needs_reinit (int model_idx, bool reinit_required = true) { - public: - Frame(const wxString &title) - : wxFrame(nullptr, wxID_ANY, title, wxDefaultPosition, wxDefaultSize) - { - wxGLAttributes vAttrs; - vAttrs.PlatformDefaults().Defaults().EndList(); - if (wxGLCanvas::IsDisplaySupported(vAttrs)) { - // canvas becomes a child of this wxFrame which is responsible for deallocation - this->canvas = new mplot::wx::Canvas(this, vAttrs); - this->canvas->SetMinSize (FromDIP (wxSize(640, 480))); - } else { - throw std::runtime_error ("wxGLCanvas::IsDisplaySupported(vAttrs) returned false"); - } + this->needs_reinit = reinit_required ? model_idx : -1; + } + + // In your wx code, build VisualModels that should be added to the scene and add them to this. + std::vector>> newvisualmodels; + std::vector*> model_ptrs; + // if >-1, then that model needs a reinit. + int needs_reinit = -1; + + bool ready() { return this->glInitialized; } + + mplot::VisualOwnableNoMX v; + + private: + std::unique_ptr glContext; + bool glInitialized = false; + }; + + // mplot::wx::Frame is to be extended. Note that a default GL version of 4.1 is given here. + template + class Frame : public wxFrame + { + public: + Frame(const wxString &title) + : wxFrame(nullptr, wxID_ANY, title, wxDefaultPosition, wxDefaultSize) + { + wxGLAttributes vAttrs; + vAttrs.PlatformDefaults().Defaults().EndList(); + if (wxGLCanvas::IsDisplaySupported(vAttrs)) { + // canvas becomes a child of this wxFrame which is responsible for deallocation + this->canvas = new mplot::wx::Canvas(this, vAttrs); + this->canvas->SetMinSize (FromDIP (wxSize(640, 480))); + } else { + throw std::runtime_error ("wxGLCanvas::IsDisplaySupported(vAttrs) returned false"); } + } - protected: - // A mplot::wx::Frame contains a mplot::wx::Canvas - mplot::wx::Canvas* canvas; - }; + protected: + // A mplot::wx::Frame contains a mplot::wx::Canvas + mplot::wx::Canvas* canvas; + }; - } // wx -} // mplot +} // mplot::wx