diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 00000000..8e5b93b4 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,13 @@ +cmake_minimum_required(VERSION 3.16) +project(psemek) + +set(CMAKE_CXX_STANDARD 17) +list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules") + +string(TOUPPER ${CMAKE_BUILD_TYPE} PSEMEK_BUILD_TYPE) + +if(PSEMEK_BUILD_TYPE STREQUAL "DEBUG") + add_definitions("-DPSEMEK_DEBUG=1") +endif() + +add_subdirectory(libs) diff --git a/cmake/modules/FindGMP.cmake b/cmake/modules/FindGMP.cmake new file mode 100644 index 00000000..6a0e05dc --- /dev/null +++ b/cmake/modules/FindGMP.cmake @@ -0,0 +1,19 @@ +if(GMP_FOUND) + set(GMP_FIND_QUIETLY TRUE) +endif() + +find_path(GMP_INCLUDE_DIRS NAMES "gmp.h" PATHS "${GMP_ROOT}/include") +find_library(GMP_LIBRARIES NAMES "gmp" PATHS "${GMP_ROOT}/lib") + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(GMP DEFAULT_MSG GMP_INCLUDE_DIRS GMP_LIBRARIES) + +if(GMP_FOUND AND NOT TARGET GMP) + add_library(GMP SHARED IMPORTED) + set_target_properties(GMP PROPERTIES + IMPORTED_LOCATION "${GMP_LIBRARIES}" + INTERFACE_INCLUDE_DIRECTORIES "${GMP_INCLUDE_DIRS}" + ) +endif() + +mark_as_advanced(GMP_INCLUDE_DIRS GMP_LIBRARIES) diff --git a/cmake/modules/FindSDL2.cmake b/cmake/modules/FindSDL2.cmake new file mode 100644 index 00000000..b486eb43 --- /dev/null +++ b/cmake/modules/FindSDL2.cmake @@ -0,0 +1,19 @@ +if(SDL2_FOUND) + set(SDL2_FIND_QUIETLY TRUE) +endif() + +find_path(SDL2_INCLUDE_DIRS NAMES "SDL2/SDL.h" PATHS "${SDL2_ROOT}/include") +find_library(SDL2_LIBRARIES NAMES "SDL2" PATHS "${SDL2_ROOT}/lib") + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(SDL2 DEFAULT_MSG SDL2_INCLUDE_DIRS SDL2_LIBRARIES) + +if(SDL2_FOUND AND NOT TARGET sdl2) + add_library(sdl2 SHARED IMPORTED) + set_target_properties(sdl2 PROPERTIES + IMPORTED_LOCATION "${SDL2_LIBRARIES}" + INTERFACE_INCLUDE_DIRECTORIES "${SDL2_INCLUDE_DIRS}" + ) +endif() + +mark_as_advanced(SDL2_INCLUDE_DIRS SDL2_LIBRARIES) diff --git a/libs/CMakeLists.txt b/libs/CMakeLists.txt new file mode 100644 index 00000000..f7040cc0 --- /dev/null +++ b/libs/CMakeLists.txt @@ -0,0 +1,5 @@ +add_subdirectory(util) +add_subdirectory(geom) +add_subdirectory(cg) +add_subdirectory(pcg) +add_subdirectory(gfx) diff --git a/libs/cg/CMakeLists.txt b/libs/cg/CMakeLists.txt new file mode 100644 index 00000000..b6ebf0e4 --- /dev/null +++ b/libs/cg/CMakeLists.txt @@ -0,0 +1,6 @@ +file(GLOB_RECURSE PSEMEK_CG_HEADERS "include/*.hpp") + +add_library(cg STATIC ${PSEMEK_CG_HEADERS}) +target_include_directories(cg PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include") +target_link_libraries(cg PUBLIC geom) +set_target_properties(cg PROPERTIES LINKER_LANGUAGE CXX) diff --git a/libs/cg/include/psemek/cg/bbox.hpp b/libs/cg/include/psemek/cg/bbox.hpp new file mode 100644 index 00000000..93bdf7e6 --- /dev/null +++ b/libs/cg/include/psemek/cg/bbox.hpp @@ -0,0 +1,19 @@ +#pragma once + +#include + +namespace cg +{ + + template + auto bbox (Iterator begin, Iterator end) + { + using point_type = std::decay_t; + + box result; + for (; begin != end; ++begin) + result |= *begin; + return result; + } + +} diff --git a/libs/cg/include/psemek/cg/clip.hpp b/libs/cg/include/psemek/cg/clip.hpp new file mode 100644 index 00000000..c8b2f504 --- /dev/null +++ b/libs/cg/include/psemek/cg/clip.hpp @@ -0,0 +1,174 @@ +#pragma once + +#include +#include +#include + +namespace cg +{ + + // TODO: this was written for Voronoi and is known to fail in some cases + template + void clip (dcel, Edge, Face, Index> & dcel, cg::vector const & eq) + { + auto outer_face = dcel.face(0); + + auto inside = [eq](auto const & p){ + return p[0] * eq[0] + p[1] * eq[1] + eq[2] >= 0.f; + }; + + auto cross = [&inside](auto edge){ + return !inside(edge.origin().data()) && inside(edge.next().origin().data()); + }; + + auto split_edge = [&dcel, eq](auto edge) + { + auto q0 = edge.origin().data(); + auto q1 = edge.next().origin().data(); + + float t = - (eq[0] * q0[0] + eq[1] * q0[1] + eq[2]) / (eq[0] * (q1[0] - q0[0]) + eq[1] * (q1[1] - q0[1])); + auto q = q0 + t * (q1 - q0); + + auto e = dcel.push_edge(); + auto twin = dcel.push_edge(); + auto p = dcel.push_point(q); + + auto ctwin = edge.twin(); + + p.edge(e); + + e.origin(p); + e.next(edge.next()); + e.twin(ctwin); + e.face(edge.face()); + + twin.origin(p); + twin.next(ctwin.next()); + twin.twin(edge); + twin.face(ctwin.face()); + + edge.next(e); + edge.twin(twin); + + ctwin.next(twin); + ctwin.twin(e); + }; + + auto prev_edge = [](auto edge) + { + auto e = edge; + while (true) + { + e = e.twin(); + if (e.next() == edge) return e; + e = e.next(); + } + }; + + auto merge_edge = [&](auto edge) + { + auto dcel_copy = dcel; + + auto next = edge.next(); + auto twin = edge.twin(); + auto ntwin = next.twin(); + + assert(ntwin.next() == twin); + assert(next.origin() == twin.origin()); + + edge.next(next.next()); + edge.twin(ntwin); + + ntwin.next(twin.next()); + ntwin.twin(edge); + + edge.face().edge(edge); + ntwin.face().edge(ntwin); + + auto face = edge.face(); + auto p = next.origin(); + if (next > twin) + { + dcel.remove_edge(next); + dcel.remove_edge(twin); + } + else + { + dcel.remove_edge(twin); + dcel.remove_edge(next); + } + dcel.remove_point(p); + + return face.edge(); + }; + + auto current_edge = outer_face.edge(); + + bool no_intersection = true; + + while (true) + { + if (cross(current_edge)) { + no_intersection = false; + break; + } + + current_edge = current_edge.next(); + if (current_edge == outer_face.edge()) + break; + } + + if (no_intersection) + return; + + split_edge(current_edge); + + while (true) + { + bool end = false; + while (true) + { + auto prev = current_edge.twin().next().twin(); + + if (prev.face() != outer_face) break; + + if (cross(prev.twin())) + { + end = true; + split_edge(prev.twin()); + current_edge = merge_edge(prev.next()); + + break; + } + + current_edge = merge_edge(prev); + } + + if (end) break; + + for (bool finished = false; !finished;) + { + auto n = current_edge.twin().next(); + + if (cross(n)) + { + finished = true; + split_edge(n); + } + + auto prev = prev_edge(current_edge); + + prev.next(n); + n.face().edge(n.next()); + n.face(outer_face); + current_edge.origin(n.next().origin()); + current_edge.twin().next(n.next()); + n.next(current_edge); + n.origin().edge(n); + } + + current_edge = prev_edge(current_edge); + } + } + +} diff --git a/libs/cg/include/psemek/cg/convex_hull_2d/andrew.hpp b/libs/cg/include/psemek/cg/convex_hull_2d/andrew.hpp new file mode 100644 index 00000000..4e9a62a2 --- /dev/null +++ b/libs/cg/include/psemek/cg/convex_hull_2d/andrew.hpp @@ -0,0 +1,53 @@ +#pragma once + +#include + +#include +#include +#include + +namespace cg +{ + + template + OutIterator andrew_convex_hull (InIterator begin, InIterator end, OutIterator out) + { + // need to store iterators to sort them + std::vector its(end - begin); + std::iota(its.begin(), its.end(), begin); + + // sort lexicographically + std::sort(its.begin(), its.end(), [](auto i1, auto i2){ return *i1 < *i2; }); + + std::vector hull; + hull.push_back(its.front()); + + // find lower half of the hull + for (auto it = its.begin() + 1; it != its.end(); ++it) + { + while (hull.size() >= 2 && orientation(**(hull.end() - 2), **(hull.end() - 1), **it) != sign_t::positive) + hull.pop_back(); + + hull.push_back(*it); + } + + // find upper half of the hull + for (auto it = its.rbegin() + 1; it != its.rend(); ++it) + { + if (*it == *(hull.end() - 2)) + continue; + + while (hull.size() >= 2 && orientation(**(hull.end() - 2), **(hull.end() - 1), **it) != sign_t::positive) + hull.pop_back(); + + hull.push_back(*it); + } + + // the last upper part point is the first lower part point - remove it + hull.pop_back(); + + // copy result to output + return std::copy(hull.begin(), hull.end(), out); + } + +} diff --git a/libs/cg/include/psemek/cg/convex_hull_2d/graham.hpp b/libs/cg/include/psemek/cg/convex_hull_2d/graham.hpp new file mode 100644 index 00000000..9eb7f0c9 --- /dev/null +++ b/libs/cg/include/psemek/cg/convex_hull_2d/graham.hpp @@ -0,0 +1,54 @@ +#pragma once + +#include + +#include +#include +#include + +namespace cg +{ + + template + OutIterator graham_convex_hull (InIterator begin, InIterator end, OutIterator out) + { + // need to store iterators to sort them + std::vector its(end - begin); + std::iota(its.begin(), its.end(), begin); + + // find leftmost point & move its iterator to beginning + { + auto leftmost = std::min_element(its.begin(), its.end(), [](auto i1, auto i2){ return *i1 < *i2; }); + std::iter_swap(leftmost, its.begin()); + } + + // sort with respect to angle to leftmost point + std::sort(its.begin() + 1, its.end(), [&](auto i1, auto i2){ + auto o = orientation(*its.front(), *i1, *i2); + + // carefully deal with parallel points + if (o == sign_t::positive) + return true; + else if (o == sign_t::negative) + return false; + + return *i1 < *i2; + }); + + // perform gift wrapping + + auto hull_end = its.begin() + 1; + + for (auto it = its.begin() + 1; it != its.end(); ++it) + { + while (hull_end - its.begin() >= 2 && orientation(**(hull_end - 2), **(hull_end - 1), **it) != sign_t::positive) + --hull_end; + + *hull_end++ = *it; + } + + // copy result to output + return std::copy(its.begin(), hull_end, out); + } + +} diff --git a/libs/cg/include/psemek/cg/convex_hull_2d/jarvis.hpp b/libs/cg/include/psemek/cg/convex_hull_2d/jarvis.hpp new file mode 100644 index 00000000..f2217b61 --- /dev/null +++ b/libs/cg/include/psemek/cg/convex_hull_2d/jarvis.hpp @@ -0,0 +1,51 @@ +#pragma once + +#include + +namespace cg +{ + + template + OutIterator jarvis_convex_hull (InIterator begin, InIterator end, OutIterator out) + { + auto first_hull_point = std::min_element(begin, end); + auto last_hull_point = first_hull_point; + + *out++ = last_hull_point; + + while (true) + { + auto it = begin; + for (; it != end; ++it) + { + if (it == last_hull_point) continue; + + bool is_hull_edge = true; + for (auto jt = begin; jt != end; ++jt) + { + if (jt == it) continue; + if (jt == last_hull_point) continue; + + if (orientation(*last_hull_point, *it, *jt) != cg::sign_t::positive) + { + is_hull_edge = false; + break; + } + } + + if (is_hull_edge) + { + break; + } + } + + if (it == first_hull_point) break; + + *out++ = it; + last_hull_point = it; + } + + return out; + } + +} diff --git a/libs/cg/include/psemek/cg/convex_hull_2d/quickhull.hpp b/libs/cg/include/psemek/cg/convex_hull_2d/quickhull.hpp new file mode 100644 index 00000000..b7c01340 --- /dev/null +++ b/libs/cg/include/psemek/cg/convex_hull_2d/quickhull.hpp @@ -0,0 +1,67 @@ +#pragma once + +#include + +#include +#include +#include + +namespace cg +{ + + namespace detail + { + + template + OutIterator quick_hull_recursive_helper (InIterator p1, InIterator p2, ItIterator begin, ItIterator end, OutIterator out) + { + if (begin == end) + return *out++ = p1; + + // find point in [begin, end) furthest from segment (p1,p2) + auto mid = *std::max_element(begin, end, [&](auto it1, auto it2){ + // TODO: design a robust predicate + return orientation(*it2, (*it2) + ((*p2) - (*p1)), *it1) == sign_t::positive; + }); + + auto end1 = std::partition(begin, end, [&](auto it){ return orientation(*p1, *it, *mid) == sign_t::positive; }); + auto end2 = std::partition(end1, end, [&](auto it){ return orientation(*mid, *it, *p2) == sign_t::positive; }); + + out = quick_hull_recursive_helper(p1, mid, begin, end1, out); + out = quick_hull_recursive_helper(mid, p2, end1, end2, out); + + return out; + } + + } + + template + OutIterator quick_hull (InIterator begin, InIterator end, OutIterator out) + { + // need to store iterators to move sets of points around + std::vector its(end - begin); + std::iota(its.begin(), its.end(), begin); + + // find leftmost point and move it to the beginning + { + auto p = std::min_element(its.begin(), its.end(), [](auto it1, auto it2){ return *it1 < *it2; }); + std::iter_swap(its.begin(), p); + } + + // find the next hull point in clockwise order and move it to second place + { + auto p = std::find_if(its.begin() + 1, its.end(), [&](auto it){ + return std::all_of(its.begin() + 1, its.end(), [&](auto jt){ + return it == jt || orientation(*its.front(), *it, *jt) == sign_t::negative; + }); + }); + std::iter_swap(its.begin() + 1, p); + } + + // everything is set up, do the recursion + out = detail::quick_hull_recursive_helper(its[0], its[1], its.begin() + 2, its.end(), out); + + return *out++ = *(its.begin() + 1); + } + +} diff --git a/libs/cg/include/psemek/cg/dcel.hpp b/libs/cg/include/psemek/cg/dcel.hpp new file mode 100644 index 00000000..d1958b06 --- /dev/null +++ b/libs/cg/include/psemek/cg/dcel.hpp @@ -0,0 +1,477 @@ +#pragma once + +#include + +#include +#include +#include + +namespace cg +{ + + namespace detail + { + + template + struct point_rec : util::ebo_helper + { + Index edge; + }; + + template + struct edge_rec : util::ebo_helper + { + Index origin; + Index next; + Index twin; + Index face; + }; + + template + struct face_rec : util::ebo_helper + { + Index edge; + }; + + template + struct handle_base + { + handle_base ( ) + : owner_(nullptr) + , i_(static_cast(-1)) + { } + + handle_base (DCEL * owner, Index i) + : owner_(owner) + , i_(i) + { } + + DCEL & owner ( ) const { return *owner_; } + + Index index ( ) const { return i_; } + + explicit operator bool ( ) const { return i_ != static_cast(-1); } + + friend bool operator == (handle_base const & h1, handle_base const & h2) + { + return h1.i_ == h2.i_; + } + + friend bool operator != (handle_base const & h1, handle_base const & h2) + { + return !(h1 == h2); + } + + friend bool operator < (handle_base const & h1, handle_base const & h2) + { + return h1.i_ < h2.i_; + } + + friend bool operator > (handle_base const & h1, handle_base const & h2) + { + return h2 < h1; + } + + friend bool operator <= (handle_base const & h1, handle_base const & h2) + { + return !(h2 < h1); + } + + friend bool operator >= (handle_base const & h1, handle_base const & h2) + { + return !(h1 < h2); + } + + protected: + DCEL * owner_; + Index i_; + }; + + struct point_tag { }; + struct edge_tag { }; + struct face_tag { }; + + } + + template + struct dcel + { + static constexpr Index null = static_cast(-1); + + using point_rec = detail::point_rec; + using edge_rec = detail::edge_rec; + using face_rec = detail::face_rec; + + std::vector points; + std::vector edges; + std::vector faces; + + // TODO: const handles + + // TODO: iteration over handles + + struct point_handle; + struct edge_handle; + struct face_handle; + + struct point_handle : detail::handle_base + { + using detail::handle_base::handle_base; + + Point & data ( ) const; + + edge_handle edge ( ) const; + + void edge (edge_handle h); + + protected: + point_rec & get ( ) const + { + assert(this->owner_ != nullptr); + assert(this->i_ < this->owner_->points.size()); + return this->owner_->points[this->i_]; + } + }; + + struct edge_handle : detail::handle_base + { + using detail::handle_base::handle_base; + + Edge & data ( ) const; + + point_handle origin ( ) const; + edge_handle next ( ) const; + edge_handle twin ( ) const; + face_handle face ( ) const; + + void origin (point_handle h); + void next (edge_handle h); + void twin (edge_handle h); + void face (face_handle h); + + protected: + edge_rec & get ( ) const + { + assert(this->owner_ != nullptr); + assert(this->i_ < this->owner_->edges.size()); + return this->owner_->edges[this->i_]; + } + }; + + struct face_handle : detail::handle_base + { + using detail::handle_base::handle_base; + + Face & data ( ) const; + + edge_handle edge ( ) const; + + void edge (edge_handle h); + + protected: + face_rec & get ( ) const + { + assert(this->owner_ != nullptr); + assert(this->i_ < this->owner_->faces.size()); + return this->owner_->faces[this->i_]; + } + }; + + point_handle point (Index i) + { + return {this, i}; + } + + edge_handle edge (Index i) + { + return {this, i}; + } + + face_handle face (Index i) + { + return {this, i}; + } + + point_handle push_point (Point data = {}) + { + auto i = static_cast(points.size()); + points.push_back({{std::move(data)}, null}); + return point(i); + } + + edge_handle push_edge (Edge data = {}) + { + auto i = static_cast(edges.size()); + edges.push_back({{std::move(data)}, null, null, null, null}); + return edge(i); + } + + face_handle push_face (Face data = {}) + { + auto i = static_cast(faces.size()); + faces.push_back({{std::move(data)}, null}); + return face(i); + } + + point_handle insert_point (Index i, Point data = {}) + { + points.insert(points.begin() + i, {{std::move(data)}, null}); + for (auto & e : edges) + { + if (e.origin >= i) + ++e.origin; + } + return point(i); + } + + edge_handle insert_edge (Index i, Edge data = {}) + { + edges.insert(edges.begin() + i, {{std::move(data)}, null, null, null, null}); + for (auto & p : points) + { + if (p.edge >= i) + ++p.edge; + } + for (auto & e : edges) + { + if (e.next >= i) + ++e.next; + if (e.twin >= i) + ++e.twin; + } + for (auto & f : faces) + { + if (f.edge >= i) + ++f.edge; + } + return edge(i); + } + + face_handle insert_face (Index i, Face data = {}) + { + faces.insert(faces.begin() + i, {{std::move(data)}, null}); + for (auto & e : edges) + { + if (e.face >= i) + ++e.face; + } + return face(i); + } + + void remove_point (point_handle h) + { + points.erase(points.begin() + h.index()); + for (auto & e : edges) + { + if (e.origin > h.index()) + --e.origin; + } + } + + void remove_edge (edge_handle h) + { + edges.erase(edges.begin() + h.index()); + for (auto & p : points) + { + if (p.edge > h.index()) + --p.edge; + } + for (auto & e : edges) + { + if (e.next > h.index()) + --e.next; + if (e.twin > h.index()) + --e.twin; + } + for (auto & f : faces) + { + if (f.edge > h.index()) + --f.edge; + } + } + + void remove_face (face_handle h) + { + faces.erase(faces.begin() + h.index()); + for (auto & e : edges) + { + if (e.face > h.index()) + --e.face; + } + } + }; + + template + Point & dcel::point_handle::data() const + { + return get().data(); + } + + template + typename dcel::edge_handle dcel::point_handle::edge() const + { + return edge_handle{this->owner_, get().edge}; + } + + template + void dcel::point_handle::edge(edge_handle h) + { + get().edge = h.index(); + } + + template + Edge & dcel::edge_handle::data() const + { + return get().data(); + } + + template + typename dcel::point_handle dcel::edge_handle::origin() const + { + return point_handle{this->owner_, get().origin}; + } + + template + typename dcel::edge_handle dcel::edge_handle::next() const + { + return edge_handle{this->owner_, get().next}; + } + + template + typename dcel::edge_handle dcel::edge_handle::twin() const + { + return edge_handle{this->owner_, get().twin}; + } + + template + typename dcel::face_handle dcel::edge_handle::face() const + { + return face_handle{this->owner_, get().face}; + } + + template + void dcel::edge_handle::origin(point_handle h) + { + get().origin = h.index(); + } + + template + void dcel::edge_handle::next(edge_handle h) + { + get().next = h.index(); + } + + template + void dcel::edge_handle::twin(edge_handle h) + { + get().twin = h.index(); + } + + template + void dcel::edge_handle::face(face_handle h) + { + get().face = h.index(); + } + + template + Face & dcel::face_handle::data() const + { + return get().data(); + } + + template + typename dcel::edge_handle dcel::face_handle::edge() const + { + return edge_handle{this->owner_, get().edge}; + } + + template + void dcel::face_handle::edge(edge_handle h) + { + get().edge = h.index(); + } + + template < + typename Point2, typename Edge2 = util::empty, typename Face2 = util::empty, typename Index2 = std::size_t, + typename Point, typename Edge, typename Face, typename Index, + typename PointFn, typename EdgeFn, typename FaceFn> + dcel map(dcel const & d, PointFn && point_fn, EdgeFn && edge_fn, FaceFn && face_fn) + { + using result_type = dcel; + result_type result; + + result.points.reserve(d.points.size()); + result.edges.reserve(d.edges.size()); + result.faces.reserve(d.faces.size()); + + for (auto const & p : d.points) + { + typename result_type::point_rec rec; + rec.edge = static_cast(p.edge); + rec.data() = point_fn(p.data()); + result.points.push_back(std::move(rec)); + } + + for (auto const & e : d.edges) + { + typename result_type::edge_rec rec; + rec.origin = static_cast(e.origin); + rec.next = static_cast(e.next); + rec.twin = static_cast(e.twin); + rec.face = static_cast(e.face); + rec.data() = edge_fn(e.data()); + result.edges.push_back(std::move(rec)); + } + + for (auto const & f : d.faces) + { + typename result_type::face_rec rec; + rec.edge = static_cast(f.edge); + rec.data() = face_fn(f.data()); + result.faces.push_back(std::move(rec)); + } + + return result; + } + + template + auto polygon_dcel (Iterator begin, Iterator end) + { + using point_type = std::decay_t; + + dcel result; + + auto outer_face = result.push_face(); + auto inner_face = result.push_face(); + + outer_face.edge(result.edge(0)); + inner_face.edge(result.edge(1)); + + for (; begin != end; ++begin) + { + result.push_point(*begin); + result.push_edge(); + result.push_edge(); + } + + std::size_t const N = result.points.size(); + + for (std::size_t i = 0; i < N; ++i) + { + result.points[i].edge = 2 * i; + + result.edges[2 * i].face = 0; + result.edges[2 * i].next = (2 * i + 2) % (2 * N); + result.edges[2 * i].twin = 2 * i + 1; + result.edges[2 * i].origin = i; + + result.edges[2 * i + 1].face = 1; + result.edges[2 * i + 1].next = (2 * i + 2 * N - 1) % (2 * N); + result.edges[2 * i + 1].twin = 2 * i; + result.edges[2 * i + 1].origin = (i + 1) % N; + } + + return result; + } + +} diff --git a/libs/cg/include/psemek/cg/dual.hpp b/libs/cg/include/psemek/cg/dual.hpp new file mode 100644 index 00000000..c371534b --- /dev/null +++ b/libs/cg/include/psemek/cg/dual.hpp @@ -0,0 +1,50 @@ +#pragma once + +#include + +namespace cg +{ + + template + dcel dual (dcel const & d) + { + dcel result; + + result.edges.reserve(d.edges.size()); + for (auto const & e : d.edges) + { + result.push_edge(e.data()); + auto & n = result.edges.back(); + n.twin = e.twin; + n.face = e.origin; + n.origin = d.edges[e.twin].face; + } + + for (Index e = 0; e < result.edges.size(); ++e) + { + auto next = [&](auto i){ return d.edges[d.edges[i].twin].next; }; + + Index i = e, n = next(i); + for (; n != e; i = n, n = next(n)); + + result.edges[e].next = i; + } + + result.points.reserve(d.faces.size()); + for (auto const & f : d.faces) + { + result.push_point(f.data()); + result.points.back().edge = d.edges[f.edge].twin; + } + + result.faces.reserve(d.points.size()); + for (auto const & p : d.points) + { + result.push_face(p.data()); + result.faces.back().edge = p.edge; + } + + return result; + } + +} diff --git a/libs/cg/include/psemek/cg/segment_intersection.hpp b/libs/cg/include/psemek/cg/segment_intersection.hpp new file mode 100644 index 00000000..0103ba9e --- /dev/null +++ b/libs/cg/include/psemek/cg/segment_intersection.hpp @@ -0,0 +1,147 @@ +#pragma once + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace cg +{ + + template + OutIterator segment_intersection (InIterator begin, InIterator end, OutIterator out) + { + using segment = std::decay_t; + using point = typename segment::point_type; + using scalar = typename point::scalar_type; + + enum event_type + { + BEGIN, + END, + CROSS, + }; + + // TODO: robust event comparison predicate + + struct event + { + InIterator it1, it2; + point p; + event_type type; + }; + + struct event_comparator + { + bool operator() (event const & e1, event const & e2) const + { + return e1.p > e2.p; + } + }; + + std::priority_queue, event_comparator> queue; + + for (auto it = begin; it != end; ++it) + { + event e_begin{it, end, (*it)[0], BEGIN}; + event e_end {it, end, (*it)[1], END }; + + if (e_begin.p > e_end.p) std::swap(e_begin.p, e_end.p); + queue.push(e_begin); + queue.push(e_end); + } + + auto push_cross_event = [&queue](InIterator it, InIterator jt){ + auto ion = intersection(*it, *jt); + if (auto p = std::get_if(&ion)) + { + queue.push({it, jt, *p, CROSS}); + } + }; + + scalar sweep_line = -std::numeric_limits::infinity(); + + struct status_comparator + { + scalar & sweep_line; + + bool operator() (InIterator it1, InIterator it2) const + { + scalar const eps = 1e-4; + scalar const y1 = (*it1)[0][1] + ((*it1)[1][1] -(*it1)[0][1]) * (sweep_line + eps - (*it1)[0][0]) / ((*it1)[1][0] - (*it1)[0][0]); + scalar const y2 = (*it2)[0][1] + ((*it2)[1][1] -(*it2)[0][1]) * (sweep_line + eps - (*it2)[0][0]) / ((*it2)[1][0] - (*it2)[0][0]); + + return y1 < y2; + } + }; + + std::set status{status_comparator{sweep_line}}; + + while (!queue.empty()) + { + event e = queue.top(); + queue.pop(); + + switch (e.type) + { + case BEGIN: { + auto it = status.insert(e.it1).first; + if (it != status.begin()) push_cross_event(*std::prev(it), *it); + if (std::next(it) != status.end()) push_cross_event(*it, *std::next(it)); + sweep_line = e.p[0]; + break; + } + case END: { + auto it = status.find(e.it1); + if (it == status.end()) + { + int fuck = 42; + } + else + { + if (it != status.begin() && std::next(it) != status.end()) push_cross_event(*std::prev(it), *std::next(it)); + status.erase(it); + } + sweep_line = e.p[0]; + break; + } + case CROSS: { + *out++ = {e.it1, e.it2}; + + status.erase(e.it1); + status.erase(e.it2); + sweep_line = e.p[0]; + auto it1 = status.insert(e.it1).first; + auto it2 = status.insert(e.it2).first; + if (it1 == status.end()) + { + int fuck_really = 42; + } + if (it2 == status.end()) + { + int fuck_really = 42; + } + + if (std::next(it2) != it1) + { + bool check = std::next(it1) == it2; + + int fuck = 42; + } + if (it2 != status.begin()) push_cross_event(*std::prev(it2), *it2); + if (std::next(it1) != status.end()) push_cross_event(*it1, *std::next(it1)); + break; + } + } + } + + return out; + } + +} diff --git a/libs/cg/include/psemek/cg/triangulation/delaunay.hpp b/libs/cg/include/psemek/cg/triangulation/delaunay.hpp new file mode 100644 index 00000000..4f6c2e00 --- /dev/null +++ b/libs/cg/include/psemek/cg/triangulation/delaunay.hpp @@ -0,0 +1,103 @@ +#pragma once + +#include +#include + +#include + +namespace cg +{ + + template + auto delaunay (InputIterator begin, InputIterator end) + { + std::vector edge_queue; + + auto callback = [&](auto & dcel, auto p) + { + auto outer_face = dcel.face(0); + + // grab interior edges outgoing from p + for (auto e = p.edge();;) + { + auto t = e.twin(); + + if (e.face() != outer_face) + { + if (t.face() != outer_face) + { + edge_queue.push_back(e.index()); + } + + auto n = e.next(); + if (n.twin().face() != outer_face) + { + edge_queue.push_back(n.index()); + } + } + + e = t.next(); + + if (e == p.edge()) break; + } + + while (!edge_queue.empty()) + { + auto e = dcel.edge(edge_queue.back()); + edge_queue.pop_back(); + + auto next = e.next(); + auto prev = next.next(); + auto twin = e.twin(); + auto tnext = twin.next(); + auto tprev = tnext.next(); + + auto p0 = prev.origin(); + auto p1 = e.origin(); + auto p2 = next.origin(); + auto p3 = e.twin().next().next().origin(); + + // decide if a flip is needed + if (in_circle(*p0.data(), *p1.data(), *p2.data(), *p3.data()) != sign_t::positive) continue; + + auto f0 = e.face(); + auto f1 = twin.face(); + + e.origin(p0); + e.next(tprev); + + next.next(e); + + prev.face(f1); + prev.next(tnext); + + twin.origin(p3); + twin.next(prev); + + tnext.next(twin); + + tprev.face(f0); + tprev.next(next); + + p1.edge(tnext); + p2.edge(next); + + f0.edge(e); + f1.edge(twin); + + auto push = [&](auto e) + { + if (e.twin().face() != outer_face) + edge_queue.push_back(e.index()); + }; + + push(next); + push(prev); + push(tnext); + push(tprev); + } + }; + return detail::triangulate(begin, end, callback); + } + +} diff --git a/libs/cg/include/psemek/cg/triangulation/triangulation.hpp b/libs/cg/include/psemek/cg/triangulation/triangulation.hpp new file mode 100644 index 00000000..0a37b5d6 --- /dev/null +++ b/libs/cg/include/psemek/cg/triangulation/triangulation.hpp @@ -0,0 +1,262 @@ +#pragma once + +#include +#include +#include + +#include +#include + +namespace cg +{ + + namespace detail + { + + template + auto triangulate (Iterator begin, Iterator end, Callback && callback) + { + using point_type = std::decay_t; + static_assert(point_type::dimension == 2); + + using dcel_type = dcel; + + dcel_type result; + + std::vector sweepline_events; + sweepline_events.resize(std::distance(begin, end)); + std::iota(sweepline_events.begin(), sweepline_events.end(), begin); + std::sort(sweepline_events.begin(), sweepline_events.end(), [](auto it, auto jt){ return *it < *jt; }); + + auto it = sweepline_events.begin(); + + auto outer_face = result.push_face(); + + // handle degenerate cases + if (sweepline_events.empty()) return result; + + if (sweepline_events.size() == 1) + { + result.push_point(*it++); + return result; + } + + { + auto const N = sweepline_events.size(); + result.points.reserve(N); + result.edges.reserve(3*(N-1)); + result.faces.reserve(2*(N-1)); + } + + typename dcel_type::edge_handle hull_start; + + { + auto p0 = result.push_point(*it++); + auto p1 = result.push_point(*it++); + + auto e01 = result.push_edge(); + auto e10 = result.push_edge(); + + p0.edge(e01); + p1.edge(e10); + + e01.origin(p0); + e01.next(e10); + e01.face(outer_face); + e01.twin(e10); + e10.origin(p1); + e10.next(e01); + e10.face(outer_face); + e10.twin(e01); + outer_face.edge(e01); + + hull_start = e01; + } + + for (; it != sweepline_events.end(); ++it) + { + // walk along the hull clockwise + + auto cur_hull_edge = hull_start; + auto next_hull_edge = cur_hull_edge.next(); + + auto hp0 = cur_hull_edge.origin(); + auto hp1 = next_hull_edge.origin(); + + auto move_hull_edge = [&]{ + cur_hull_edge = next_hull_edge; + next_hull_edge = next_hull_edge.next(); + hp0 = hp1; + hp1 = next_hull_edge.origin(); + }; + + bool degenerate = false; + + // find first hull edge visible from new point + while (orientation(**it, *hp0.data(), *hp1.data()) != sign_t::positive) + { + move_hull_edge(); + if (cur_hull_edge == hull_start) + { + degenerate = true; + break; + } + } + + if (degenerate) + { + // the whole hull is just a sequence of points on a line + // find the closest & connect via a single edge + + auto q = result.point(0); + + bool vertical = false; + + // find rightmost point + for (Index i = 1; i < result.points.size(); ++i) + { + auto const x = (*result.points[i].data())[0]; + auto const qx = (*q.data())[0]; + + if (x == qx) + { + vertical = true; + break; + } + + if (x > qx) + { + q = result.point(i); + } + } + + // all points lie on a vertical line - find topmost + if (vertical) + { + q = result.point(0); + + for (Index i = 1; i < result.points.size(); ++i) + { + auto const y = (*result.points[i].data())[1]; + auto const qy = (*q.data())[1]; + + if (y > qy) + { + q = result.point(i); + } + } + } + + auto p = result.push_point(*it); + + auto qnext = q.edge(); + auto qprev = qnext.twin(); + + auto pnext = result.push_edge(); + auto pprev = result.push_edge(); + + qprev.next(pprev); + + pprev.next(pnext); + pprev.origin(q); + pprev.twin(pnext); + pprev.face(outer_face); + + pnext.next(qnext); + pnext.origin(p); + pnext.twin(pprev); + pnext.face(outer_face); + + p.edge(pnext); + + continue; + } + + auto p = result.push_point(*it); + + auto mid_edge = result.push_edge(); + mid_edge.origin(hp0); + mid_edge.face(outer_face); + + auto first_mid_edge = mid_edge; + + { + // fix prev_hull_edge.next + auto prev_hull_edge = cur_hull_edge.twin(); + + while (prev_hull_edge.face() != outer_face) + { + prev_hull_edge = prev_hull_edge.next().twin(); + } + prev_hull_edge.next(first_mid_edge); + } + + // until current edge is visible + while (orientation(**it, *hp0.data(), *hp1.data()) == sign_t::positive) + { + // fill new triangle + + auto ep0 = result.push_edge(); + auto e1p = result.push_edge(); + + auto f = result.push_face(); + + if (!p.edge()) + { + p.edge(ep0); + } + + mid_edge.twin(ep0); + + ep0.origin(p); + ep0.next(cur_hull_edge); + ep0.twin(mid_edge); + ep0.face(f); + + e1p.origin(hp1); + e1p.next(ep0); + e1p.face(f); + + cur_hull_edge.next(e1p); + cur_hull_edge.face(f); + + f.edge(ep0); + + mid_edge = e1p; + + move_hull_edge(); + } + + auto last_mid_edge = result.push_edge(); + last_mid_edge.origin(p); + last_mid_edge.face(outer_face); + last_mid_edge.twin(mid_edge); + last_mid_edge.next(cur_hull_edge); + + mid_edge.twin(last_mid_edge); + + first_mid_edge.next(last_mid_edge); + + // update first hull edge + + if (hull_start.face() != outer_face) + { + hull_start = hull_start.next().next().twin(); + outer_face.edge(hull_start); + } + + callback(result, p); + } + + return result; + } + + } + + template + auto triangulate (InputIterator begin, InputIterator end) + { + return detail::triangulate(begin, end, util::nop); + } + +} diff --git a/libs/cg/include/psemek/cg/utility.hpp b/libs/cg/include/psemek/cg/utility.hpp new file mode 100644 index 00000000..ab4e1754 --- /dev/null +++ b/libs/cg/include/psemek/cg/utility.hpp @@ -0,0 +1,68 @@ +#pragma once + +#include +#include + +namespace cg::util +{ + + struct empty{}; + + template + struct overload_impl + : Fs ... + { + using Fs::operator() ...; + }; + + template + auto overload (Fs && ... fs) + { + return overload_impl{ std::forward(fs) ... }; + } + + template + decltype(auto) match (Variant && v, Fs && ... fs) + { + return std::visit(overload(std::forward(fs)...), std::forward(v)); + } + + constexpr auto id = [](auto const & x){ return x; }; + + constexpr auto nop = [](auto const & ...){}; + + namespace detail + { + + template + struct ebo_helper_impl : T + { + T & data() { return *this; } + T const & data() const { return *this; } + + template + ebo_helper_impl (Args && ... args) + : T(std::forward(args)...) + { } + }; + + template + struct ebo_helper_impl + { + T value; + + T & data() { return value; } + T const & data() const { return value; } + + template + ebo_helper_impl (Args && ... args) + : value(std::forward(args)...) + { } + }; + + } + + template + using ebo_helper = detail::ebo_helper_impl && !(std::is_final_v)>; + +} diff --git a/libs/cg/include/psemek/cg/voronoi.hpp b/libs/cg/include/psemek/cg/voronoi.hpp new file mode 100644 index 00000000..0f1abd1a --- /dev/null +++ b/libs/cg/include/psemek/cg/voronoi.hpp @@ -0,0 +1,194 @@ +#pragma once + +#include +#include +#include +#include + +namespace cg +{ + + // Point #0 of the resulting dcel corresponds to the outer face, + // i.e. the point at infinity, and has unspecified coordinates. + template + auto voronoi (Iterator begin, Iterator end) + { + using point_type = std::decay_t; + + auto del = dual(delaunay(begin, end)); + + dcel result; + + result.points.reserve(del.points.size()); + for (std::size_t i = 0; i < del.points.size(); ++i) + { + auto p = del.point(i); + + point_type q[3]; + + auto e = p.edge(); + q[0] = *e.face().data(); + e = e.twin().next(); + q[1] = *e.face().data(); + e = e.twin().next(); + q[2] = *e.face().data(); + + using T = typename point_type::scalar_type; + + matrix m; + vector b; + + for (std::size_t i = 0; i < 3; ++i) + { + m[i][0] = q[i][0]; + m[i][1] = q[i][1]; + m[i][2] = T{1}; + + b[i] = q[i][0] * q[i][0] + q[i][1] * q[i][1]; + } + + gauss(m, b); + + auto newp = result.push_point(point_type{b[0] / 2, b[1] / 2}); + newp.edge(result.edge(p.edge().index())); + } + + result.edges = std::move(del.edges); + result.faces = std::move(del.faces); + + return result; + } + + // Replaces the #0 infinite point of a dcel with a proper outer face + template + void remove_infinite_point (dcel & dcel) + { + // insert outer face at position #0 + auto outer_face = dcel.insert_face(0); + + std::vector delete_edges; + std::vector delete_faces; + + auto infinite_point = dcel.point(0); + + // iterate edges of infinite vertex #0 and fix hull + for (auto e = infinite_point.edge();;) + { + for (auto n = e.next(); n.twin().origin() != infinite_point; n = n.next()) + { + n.face(outer_face); + n.origin().edge(n); + if (!outer_face.edge()) + outer_face.edge(n); + } + + auto n = e; + for (; n.next() != e.twin(); n = n.next().twin()); + + if (n.origin() != infinite_point) + { + auto t = e.next(); + for (; t.twin().origin() == infinite_point; t = t.twin().next()); + + n.next(t); + } + + delete_faces.push_back(e.face().index()); + delete_edges.push_back(e.index()); + e = e.twin(); + delete_edges.push_back(e.index()); + e = e.next(); + + if (e == infinite_point.edge()) break; + } + + // remove edges incident to infinite vertex #0 + std::sort(delete_edges.begin(), delete_edges.end(), std::greater<>{}); + for (auto e : delete_edges) + dcel.remove_edge(dcel.edge(e)); + + // remove vertex #0 + dcel.remove_point(infinite_point); + + std::sort(delete_faces.begin(), delete_faces.end(), std::greater<>{}); + for (auto f : delete_faces) + dcel.remove_face(dcel.face(f)); + } + + // iteratively removes degenerate edges + template + void remove_degenerate_edges (dcel & dcel) + { + std::vector delete_points; + std::vector delete_edges; + + for (std::size_t i = 0; i < dcel.points.size(); ++i) + { + auto p = dcel.point(i); + while (p.edge().twin().next() == p.edge()) + { + delete_points.push_back(p.index()); + delete_edges.push_back(p.edge().index()); + delete_edges.push_back(p.edge().twin().index()); + + p.edge().next().origin().edge(p.edge().next()); + p.edge().face().edge(p.edge().next()); + + auto n = p.edge(); + while (true) + { + auto m = n.next().twin(); + if (m == p.edge()) break; + n = m; + } + + n.next(p.edge().next()); + + p = p.edge().next().origin(); + } + } + + std::sort(delete_points.begin(), delete_points.end(), std::greater<>{}); + for (auto p : delete_points) + dcel.remove_point(dcel.point(p)); + + std::sort(delete_edges.begin(), delete_edges.end(), std::greater<>{}); + for (auto e : delete_edges) + dcel.remove_edge(dcel.edge(e)); + } + + // Outputs 4 points such that the finite faces of the voronoi diagram of (anything + // inside the convex hull of input + the output points) covers the convex hull of input + template + OutputIterator bounded_voronoi_extra_points (InputIterator begin, InputIterator end, OutputIterator out) + { + using point_type = std::decay_t; + + static_assert(point_type::dimension == 2); + + auto box = bbox(begin, end); + + point_type const center {(box[0].min + box[0].max) / 2, (box[1].min + box[1].max) / 2}; + + auto const R = std::sqrt(box[0].length() * box[0].length() + box[1].length() * box[1].length()); + + *out++ = point_type{center[0] + R, center[1]}; + *out++ = point_type{center[0], center[1] + R}; + *out++ = point_type{center[0] - R, center[1]}; + *out++ = point_type{center[0], center[1] - R}; + + return out; + } + + // Compute a clipped voronoi tessellation of (begin, end - 4) + // Last 4 points will be used for temporary data + template + auto bounded_voronoi (InputIterator begin, InputIterator end) + { + bounded_voronoi_extra_points(begin, end - 4, end - 4); + auto dcel = cg::voronoi(begin, end); + cg::remove_infinite_point(dcel); + return dcel; + } + +} diff --git a/libs/geom/CMakeLists.txt b/libs/geom/CMakeLists.txt new file mode 100644 index 00000000..6a09ff48 --- /dev/null +++ b/libs/geom/CMakeLists.txt @@ -0,0 +1,9 @@ +find_package(Boost REQUIRED) +find_package(GMP REQUIRED) + +file(GLOB_RECURSE PSEMEK_GEOM_HEADERS "include/*.hpp") +file(GLOB_RECURSE PSEMEK_GEOM_SOURCES "source/*.cpp") + +add_library(geom STATIC ${PSEMEK_GEOM_HEADERS} ${PSEMEK_GEOM_SOURCES}) +target_include_directories(geom PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include") +target_link_libraries(geom PUBLIC Boost::boost GMP) diff --git a/libs/geom/include/psemek/geom/bezier.hpp b/libs/geom/include/psemek/geom/bezier.hpp new file mode 100644 index 00000000..c50a24d0 --- /dev/null +++ b/libs/geom/include/psemek/geom/bezier.hpp @@ -0,0 +1,41 @@ +#pragma once + +#include + +#include +#include + +namespace psemek::geom +{ + + template + struct bezier + { + bezier (std::vector points) + : points_(std::move(points)) + { + if (points_.empty()) + throw std::runtime_error("Points array should be non-empty"); + temp_.resize(points_.size()); + } + + template + auto operator() (T const & t) const + { + // In-place de Casteljau's algorithm + temp_ = points_; + + for (std::size_t k = 0; k + 1 < points_.size(); ++k) + { + for (std::size_t i = 0; i + k + 1 < points_.size(); ++i) + temp_[i] = lerp(temp_[i], temp_[i + 1], t); + } + return temp_.front(); + } + + private: + std::vector const points_; + std::vector mutable temp_; + }; + +} diff --git a/libs/geom/include/psemek/geom/box.hpp b/libs/geom/include/psemek/geom/box.hpp new file mode 100644 index 00000000..4f668ece --- /dev/null +++ b/libs/geom/include/psemek/geom/box.hpp @@ -0,0 +1,208 @@ +#pragma once + +#include +#include + +namespace psemek::geom +{ + + template + struct box + { + interval axes[N]; + + using point_type = point; + using vector_type = vector; + + interval & operator [] (std::size_t i) + { + return axes[i]; + } + + interval const & operator [] (std::size_t i) const + { + return axes[i]; + } + + // singleton box + static box singleton (point_type const & p) + { + box b; + for (std::size_t i = 0; i < N; ++i) + b.axes[i] = interval::singleton(p[i]); + return b; + } + + bool empty ( ) const + { + for (auto const & i : axes) + if (i.empty()) + return true; + return false; + } + + T size ( ) const + { + T result = T{1}; + for (auto const & i : axes) + result *= i.size(); + return result; + } + + box & operator += (vector_type const & delta); + box & operator -= (vector_type const & delta); + + box & operator &= (point_type const & p); + box & operator |= (point_type const & p); + + box & operator &= (box const & b); + box & operator |= (box const & b); + }; + + template + box operator + (box const & b, vector const & delta) + { + box result; + for (std::size_t i = 0; i < N; ++i) + { + result[i] = b[i] + delta[i]; + } + return result; + } + + template + box operator + (vector const & delta, box const & b) + { + box result; + for (std::size_t i = 0; i < N; ++i) + { + result[i] = delta[i] + b[i]; + } + return result; + } + + template + box operator - (box const & b, vector const & delta) + { + box result; + for (std::size_t i = 0; i < N; ++i) + { + result[i] = b[i] - delta[i]; + } + return result; + } + + template + box operator & (box const & b, point const & p) + { + box result; + for (std::size_t i = 0; i < N; ++i) + { + result[i] = b[i] & p[i]; + } + return result; + } + + template + box operator & (point const & p, box const & b) + { + box result; + for (std::size_t i = 0; i < N; ++i) + { + result[i] = p[i] & b[i]; + } + return result; + } + + template + box operator | (box const & b, point const & p) + { + box result; + for (std::size_t i = 0; i < N; ++i) + { + result[i] = b[i] | p[i]; + } + return result; + } + + template + box operator | (point const & p, box const & b) + { + box result; + for (std::size_t i = 0; i < N; ++i) + { + result[i] = p[i] | b[i]; + } + return result; + } + + template + box operator & (box const & b1, box const & b2) + { + box result; + for (std::size_t i = 0; i < N; ++i) + { + result[i] = b1[i] & b2[i]; + } + return result; + } + + template + box operator | (box const & b1, box const & b2) + { + box result; + for (std::size_t i = 0; i < N; ++i) + { + result[i] = b1[i] | b2[i]; + } + return result; + } + + template + box & box::operator += (vector const & delta) + { + return *this = *this + delta; + } + + template + box & box::operator -= (vector const & delta) + { + return *this = *this - delta; + } + + template + box & box::operator &= (point const & p) + { + return *this = *this & p; + } + + template + box & box::operator |= (point const & p) + { + return *this = *this | p; + } + + template + box & box::operator &= (box const & b) + { + return *this = *this & b; + } + + template + box & box::operator |= (box const & b) + { + return *this = *this | b; + } + + template + Stream & operator << (Stream & os, box const & b) + { + for (std::size_t i = 0; i < N; ++i) + { + if (i != 0) os << 'x'; + os << b[i]; + } + return os; + } + +} diff --git a/libs/geom/include/psemek/geom/camera.hpp b/libs/geom/include/psemek/geom/camera.hpp new file mode 100644 index 00000000..0283d738 --- /dev/null +++ b/libs/geom/include/psemek/geom/camera.hpp @@ -0,0 +1,59 @@ +#pragma once + +#include +#include +#include + +namespace psemek::geom +{ + + struct camera + { + virtual matrix projection() const = 0; + virtual matrix view() const = 0; + + virtual matrix transform() const; + virtual point position() const; + + // View direction is -axis_z(), or equivalently direction(0,0) + // NB: these vectors are not necessarily normalized + virtual vector axis_x() const; + virtual vector axis_y() const; + virtual vector axis_z() const; + + // x, y are in clip-space [-1, 1] + // NB: this vector is not necessarily normalized + virtual vector direction(float x, float y) const; + + // view frustum is the intersection of half-spaces defined by dot(clip_plane, x) >= 0 + virtual std::array, 6> clip_planes() const; + + virtual ~camera() = default; + }; + + struct perspective_camera + : camera + { + float fov_x; + float fov_y; + + float near_clip; + float far_clip; + + matrix projection() const override; + }; + + struct spherical_camera + : perspective_camera + { + // assumes up is +Y + // + float azimuthal_angle; + float elevation_angle; + float distance; + point target; + + matrix view() const override; + }; + +} diff --git a/libs/geom/include/psemek/geom/contains.hpp b/libs/geom/include/psemek/geom/contains.hpp new file mode 100644 index 00000000..aa482a53 --- /dev/null +++ b/libs/geom/include/psemek/geom/contains.hpp @@ -0,0 +1,37 @@ +#pragma once + +#include +#include +#include +#include +#include + +namespace psemek::geom +{ + + template + bool contains (interval const & i, T const & x) + { + return (i.min <= x) && (x <= i.max); + } + + template + bool contains (box const & b, point const & p) + { + for (std::size_t i = 0; i < N; ++i) + if (!contains(b[i], p[i])) + return false; + return true; + } + + template + bool contains (triangle> const & t, point const & p) + { + return true + && orientation(t[0], t[1], p) != sign_t::negative + && orientation(t[1], t[2], p) != sign_t::negative + && orientation(t[2], t[0], p) != sign_t::negative + ; + } + +} diff --git a/libs/geom/include/psemek/geom/gauss.hpp b/libs/geom/include/psemek/geom/gauss.hpp new file mode 100644 index 00000000..2d1f28b3 --- /dev/null +++ b/libs/geom/include/psemek/geom/gauss.hpp @@ -0,0 +1,238 @@ +#pragma once + +#include + +#include + +namespace psemek::geom +{ + + namespace detail + { + + // A helper to treat vectors & matrices uniformly + + template + struct gauss_helper; + + template + gauss_helper (X &) -> gauss_helper; + + template + struct gauss_helper> + { + vector & v; + + static constexpr std::size_t columns ( ) { return 1; } + T & at (std::size_t row, std::size_t) { return v[row]; } + }; + + template + struct gauss_helper> + { + matrix & m; + + static constexpr std::size_t columns ( ) { return M; } + T & at (std::size_t row, std::size_t col) { return m[row][col]; } + }; + + template + void for_each (F && f, Args & ... args) + { + (f(args), ...); + } + + } + + template + T det (matrix m) + { + using std::abs; + + std::size_t sign = 0; + + for (std::size_t i = 0; i < N; ++i) + { + // find maximal modulus along i-th column + auto M = abs(m[i][i]); + std::size_t k = i; + for (std::size_t j = i + 1; j < N; ++j) + { + auto const n = abs(m[j][i]); + if (n > M) + { + M = n; + k = j; + } + } + + // avoid dividing by zero + if (M == T{}) + return T{}; + + // swap rows i & k + if (i != k) + { + sign += 1; + + for (std::size_t j = i; j < N; ++j) + std::swap(m[i][j], m[k][j]); + } + + // zero out the column under i,i + for (std::size_t k = i + 1; k < N; ++k) + { + auto r = m[k][i] / m[i][i]; + for (std::size_t j = i; j < N; ++j) + { + m[k][j] -= m[i][j] * r; + } + } + } + + // determinant is product of diagonal entries + sign + T res = ((sign % 2) == 0) ? T{1} : -T{1}; + for (std::size_t i = 0; i < N; ++i) + res *= m[i][i]; + return res; + } + + // each element of the rhs can be a vector or a matrix + // the set of equations (m * x = rhs)... is solved simultaneously column-wise + // returns false is the matrix is degenerate + template + bool gauss (matrix m, RHS & ... rhs) + { + using std::abs; + + // forward elimination + for (std::size_t i = 0; i < N; ++i) + { + // find maximal modulus along i-th column + auto M = abs(m[i][i]); + std::size_t k = i; + for (std::size_t j = i + 1; j < N; ++j) + { + auto const n = abs(m[j][i]); + if (n > M) + { + M = n; + k = j; + } + } + + // avoid dividing by zero + if (M == T{}) + return false; + + // swap rows i & k + if (i != k) + { + for (std::size_t j = i; j < N; ++j) + std::swap(m[i][j], m[k][j]); + + detail::for_each([i, k](auto & rhs){ + detail::gauss_helper h{rhs}; + for (std::size_t c = 0; c < h.columns(); ++c) + { + std::swap(h.at(i, c), h.at(k, c)); + } + }, rhs...); + } + + // make i,i equal 1 + { + auto r = m[i][i]; + for (std::size_t j = i; j < N; ++j) + { + m[i][j] /= r; + } + + detail::for_each([i, r](auto & rhs){ + detail::gauss_helper h{rhs}; + for (std::size_t c = 0; c < h.columns(); ++c) + { + h.at(i, c) /= r; + } + }, rhs...); + } + + // zero out the column under i,i + for (std::size_t k = i + 1; k < N; ++k) + { + auto r = m[k][i]; + for (std::size_t j = i; j < N; ++j) + { + m[k][j] -= m[i][j] * r; + } + + detail::for_each([i, k, r](auto & rhs){ + detail::gauss_helper h{rhs}; + for (std::size_t c = 0; c < h.columns(); ++c) + { + h.at(k, c) -= h.at(i, c) * r; + } + }, rhs...); + } + } + + // backward elimination + for (std::size_t i = N; i --> 0;) + { + for (std::size_t j = 0; j < i; ++j) + { + auto r = m[j][i]; + m[j][i] = T{}; + + detail::for_each([i, j, r](auto & rhs){ + detail::gauss_helper h{rhs}; + for (std::size_t c = 0; c < h.columns(); ++c) + { + h.at(j, c) -= r * h.at(i, c); + } + }, rhs...); + } + } + + return true; + } + + template + std::optional> inverse (matrix m) + { + matrix r = matrix::identity(); + if (!gauss(m, r)) + return std::nullopt; + return r; + } + + // Least-squares solution of m*x=b with full-rank m + template + std::optional> least_squares (matrix const & m, vector const & b) + { + if constexpr (N == M) + { + auto rhs = b; + if (gauss(m, rhs)) + return rhs; + return {}; + } + else if constexpr (N < M) + { + auto const mt = transpose(m); + auto rhs = b; + if (gauss(m * mt, rhs)) + return mt * rhs; + return {}; + } + else // if constexpr (N > M) + { + auto const mt = transpose(m); + auto rhs = mt * b; + if (gauss(mt * m, rhs)) + return rhs; + return {}; + } + } + +} diff --git a/libs/geom/include/psemek/geom/gram_schmidt.hpp b/libs/geom/include/psemek/geom/gram_schmidt.hpp new file mode 100644 index 00000000..a0b94126 --- /dev/null +++ b/libs/geom/include/psemek/geom/gram_schmidt.hpp @@ -0,0 +1,21 @@ +#pragma once + +#include + +namespace psemek::geom +{ + + void gram_schmidt() + {} + + template + void gram_schmidt(V1 & v1, Vs & ... vs) + { + v1 = normalized(v1); + + ((vs -= dot(v1, vs) * v1), ...); + + gram_schmidt(vs...); + } + +} diff --git a/libs/geom/include/psemek/geom/homogeneous.hpp b/libs/geom/include/psemek/geom/homogeneous.hpp new file mode 100644 index 00000000..137576f3 --- /dev/null +++ b/libs/geom/include/psemek/geom/homogeneous.hpp @@ -0,0 +1,45 @@ +#pragma once + +#include +#include +#include + +namespace psemek::geom +{ + + template + vector homogeneous(vector const & v) + { + vector result; + for (std::size_t i = 0; i < D; ++i) + result[i] = v[i]; + result[D] = T(0); + return result; + } + + template + vector homogeneous(point const & v) + { + vector result; + for (std::size_t i = 0; i < D; ++i) + result[i] = v[i]; + result[D] = T(1); + return result; + } + + template + matrix homogeneous(matrix const & m) + { + matrix result = matrix::zero(); + for (std::size_t i = 0; i < D; ++i) + { + for (std::size_t j = 0; j < D; ++j) + { + result[i][j] = m[i][j]; + } + } + result[D][D] = T(1); + return result; + } + +} diff --git a/libs/geom/include/psemek/geom/incircle.hpp b/libs/geom/include/psemek/geom/incircle.hpp new file mode 100644 index 00000000..c401fc6e --- /dev/null +++ b/libs/geom/include/psemek/geom/incircle.hpp @@ -0,0 +1,70 @@ +#pragma once + +#include +#include +#include + +#include + +#include + +namespace psemek::geom +{ + + template + std::enable_if_t, sign_t> + in_circle (point const & p0, point const & p1, point const & p2, point const & p3) + { + auto proj = [](point const & p){ + auto const x = p[0]; + auto const y = p[1]; + return point{ x, y, x*x + y*y }; + }; + + return orientation(proj(p0), proj(p1), proj(p2), proj(p3)); + } + + template + std::enable_if_t, sign_t> + in_circle (point const & p0, point const & p1, point const & p2, point const & p3) + { + constexpr T error = std::numeric_limits::epsilon() * T(29) / T(2); + + T const m01 = (p0[0] - p3[0]) * (p1[1] - p3[1]); + T const m02 = (p0[0] - p3[0]) * (p2[1] - p3[1]); + T const m10 = (p1[0] - p3[0]) * (p0[1] - p3[1]); + T const m12 = (p1[0] - p3[0]) * (p2[1] - p3[1]); + T const m20 = (p2[0] - p3[0]) * (p0[1] - p3[1]); + T const m21 = (p2[0] - p3[0]) * (p1[1] - p3[1]); + + T const d = T(0) + + m01 * p2[0] * p2[0] + m01 * p2[1] * p2[1] - m01 * p3[0] * p3[0] - m01 * p3[1] * p3[1] + - m02 * p1[0] * p1[0] - m02 * p1[1] * p1[1] + m02 * p3[0] * p3[0] + m02 * p3[1] * p3[1] + - m10 * p2[0] * p2[0] - m10 * p2[1] * p2[1] + m10 * p3[0] * p3[0] + m10 * p3[1] * p3[1] + + m12 * p0[0] * p0[0] + m12 * p0[1] * p0[1] - m12 * p3[0] * p3[0] - m12 * p3[1] * p3[1] + + m20 * p1[0] * p1[0] + m20 * p1[1] * p1[1] - m20 * p3[0] * p3[0] - m20 * p3[1] * p3[1] + - m21 * p0[0] * p0[0] - m21 * p0[1] * p0[1] + m21 * p3[0] * p3[0] + m21 * p3[1] * p3[1] + ; + + T const t = T(0) + + std::abs(m01 * p2[0] * p2[0]) + std::abs(m01 * p2[1] * p2[1]) + std::abs(m01 * p3[0] * p3[0]) + std::abs(m01 * p3[1] * p3[1]) + + std::abs(m02 * p1[0] * p1[0]) + std::abs(m02 * p1[1] * p1[1]) + std::abs(m02 * p3[0] * p3[0]) + std::abs(m02 * p3[1] * p3[1]) + + std::abs(m10 * p2[0] * p2[0]) + std::abs(m10 * p2[1] * p2[1]) + std::abs(m10 * p3[0] * p3[0]) + std::abs(m10 * p3[1] * p3[1]) + + std::abs(m12 * p0[0] * p0[0]) + std::abs(m12 * p0[1] * p0[1]) + std::abs(m12 * p3[0] * p3[0]) + std::abs(m12 * p3[1] * p3[1]) + + std::abs(m20 * p1[0] * p1[0]) + std::abs(m20 * p1[1] * p1[1]) + std::abs(m20 * p3[0] * p3[0]) + std::abs(m20 * p3[1] * p3[1]) + + std::abs(m21 * p0[0] * p0[0]) + std::abs(m21 * p0[1] * p0[1]) + std::abs(m21 * p3[0] * p3[0]) + std::abs(m21 * p3[1] * p3[1]) + ; + + if (d > t * error) + return sign_t::positive; + else if (d < - t * error) + return sign_t::negative; + else + { + using exact_type = boost::multiprecision::mpq_rational; + + return in_circle(cast(p0), cast(p1), cast(p2), cast(p3)); + } + } + +} diff --git a/libs/geom/include/psemek/geom/intersection.hpp b/libs/geom/include/psemek/geom/intersection.hpp new file mode 100644 index 00000000..3d4790cc --- /dev/null +++ b/libs/geom/include/psemek/geom/intersection.hpp @@ -0,0 +1,112 @@ +#pragma once + +#include +#include +#include + +#include +#include + +namespace psemek::geom +{ + + // denotes empty intersection + struct empty { }; + + template + Stream & operator << (Stream & os, empty) + { + return os << "empty"; + } + + template > + bool intersect (segment const & s0, segment const & s1) + { + auto const o00 = orientation(s0[0], s0[1], s1[0]); + auto const o01 = orientation(s0[0], s0[1], s1[1]); + auto const o10 = orientation(s1[0], s1[1], s0[0]); + auto const o11 = orientation(s1[0], s1[1], s0[1]); + + return ((o00 != o01) || (o00 == sign_t::zero)) && ((o10 != o11) || (o10 == sign_t::zero)); + } + + // TODO: robust implementation + template > + std::variant> intersection (segment s0, segment s1) + { + auto const a0 = -det(s1[0] - s0[0], s1[1] - s1[0]); + auto const a1 = det(s0[1] - s0[0], s1[0] - s0[0]); + auto const b = -det(s0[1] - s0[0], s1[1] - s1[0]); + + if (b != 0) + { + // general case + + auto const t0 = a0 / b; + auto const t1 = a1 / b; + + if (t0 < 0 || t0 > 1 || t1 < 0 || t1 > 1) + return empty{}; + + return s0[0] + t0 * (s0[1] - s0[0]); + } + else + { + // collinear segments + + if (a0 != 0) + { + // segments do not lie on the same line: no intersection + return empty{}; + } + + // if segments are not Y-axis aligned, safe to use X-coordinates to sort them (k = 0) + // otherwise use Y-coordinates (k = 1) + std::size_t const k = (s0[0][0] != s0[1][0]) ? 0 : 1; + + if (s0[0][k] > s0[1][k]) + std::swap(s0[0], s0[1]); + + if (s1[0][k] > s1[1][k]) + std::swap(s1[0], s1[1]); + + auto const r0 = std::max(s0[0][k], s1[0][k]); + auto const r1 = std::min(s0[1][k], s1[1][k]); + + if (r0 > r1) + return empty{}; + + bool const s0_is_first = s0[0][k] < s1[0][k]; + + if (r0 == r1) + { + Point p; + p[k] = r0; + p[1 - k] = s0_is_first ? s0[1][1 - k] : s1[1][1 - k]; + return p; + } + else if (s0_is_first) + return segment{ s1[0], s0[1] }; + else + return segment{ s0[0], s1[1] }; + } + } + + template + bool intersect(triangle> const & t0, triangle> const & t1) + { + if (contains(t0, t1[0]) || contains(t0, t1[1]) || contains(t0, t1[2])) return true; + + if (contains(t1, t0[0]) || contains(t1, t0[1]) || contains(t1, t0[2])) return true; + + if (intersect(segment{t0[0], t0[1]}, segment{t1[0], t1[1]})) return true; + if (intersect(segment{t0[0], t0[1]}, segment{t1[1], t1[2]})) return true; + if (intersect(segment{t0[1], t0[2]}, segment{t1[0], t1[1]})) return true; + if (intersect(segment{t0[1], t0[2]}, segment{t1[1], t1[2]})) return true; + if (intersect(segment{t0[2], t0[0]}, segment{t1[0], t1[1]})) return true; + if (intersect(segment{t0[2], t0[0]}, segment{t1[1], t1[2]})) return true; + + return false; + } + +} diff --git a/libs/geom/include/psemek/geom/interval.hpp b/libs/geom/include/psemek/geom/interval.hpp new file mode 100644 index 00000000..51f2569e --- /dev/null +++ b/libs/geom/include/psemek/geom/interval.hpp @@ -0,0 +1,222 @@ +#pragma once + +#include +#include +#include + +namespace psemek::geom +{ + + // Can be specialized in client code + template + struct limits + { + static constexpr T min ( ) + { + if constexpr (std::is_floating_point_v) + { + return -std::numeric_limits::infinity(); + } + else + { + return std::numeric_limits::min(); + } + } + + static constexpr T max ( ) + { + if constexpr (std::is_floating_point_v) + { + return std::numeric_limits::infinity(); + } + else + { + return std::numeric_limits::max(); + } + } + }; + + + template + struct interval_iterator + { + T value; + + T operator* () const { return value; } + + interval_iterator & operator++ () + { + ++value; + return *this; + } + + interval_iterator operator++ (int) + { + auto copy = *this; + ++value; + return copy; + } + + friend bool operator == (interval_iterator const & i1, interval_iterator const & i2) + { + return i1.value == i2.value; + } + + friend bool operator != (interval_iterator const & i1, interval_iterator const & i2) + { + return !(i1 == i2); + } + }; + + template + struct interval + { + T min = limits::max(); + T max = limits::min(); + + static interval singleton (T const & value) + { + return {value, value}; + } + + bool empty ( ) const + { + return min > max; + } + + T length ( ) const + { + return empty() ? T{} : max - min; + } + + using iterator = interval_iterator; + using const_iterator = iterator; + + iterator begin() const { return {min}; } + iterator end() const { return {max}; } + + interval & operator += (T const & delta); + interval & operator -= (T const & delta); + + interval & operator &= (T const & a); + interval & operator |= (T const & a); + + interval & operator &= (interval const & i); + interval & operator |= (interval const & i); + }; + + template + interval operator + (interval const & i, T const & delta) + { + return {i.min + delta, i.max + delta}; + } + + template + interval operator + (T const & delta, interval const & i) + { + return {delta + i.min, delta + i.max}; + } + + template + interval operator - (interval const & i, T const & delta) + { + return {i.min - delta, i.max - delta}; + } + + template + interval operator & (interval const & i, T const & a) + { + using std::min; + using std::max; + return {max(i.min, a), min(i.max, a)}; + } + + template + interval operator & (T const & a, interval const & i) + { + using std::min; + using std::max; + return {max(a, i.min), min(a, i.max)}; + } + + template + interval operator | (interval const & i, T const & a) + { + using std::min; + using std::max; + return {min(i.min, a), max(i.max, a)}; + } + + template + interval operator | (T const & a, interval const & i) + { + using std::min; + using std::max; + return {min(a, i.min), max(a, i.max)}; + } + + template + interval operator & (interval const & i1, interval const & i2) + { + using std::min; + using std::max; + return {max(i1.min, i2.min), min(i1.max, i2.max)}; + } + + template + interval operator | (interval const & i1, interval const & i2) + { + using std::min; + using std::max; + return {min(i1.min, i2.min), max(i1.max, i2.max)}; + } + + template + interval & interval::operator += (T const & delta) + { + return *this = *this + delta; + } + + template + interval & interval::operator -= (T const & delta) + { + return *this = *this - delta; + } + + template + interval & interval::operator &= (T const & a) + { + return *this = *this & a; + } + + template + interval & interval::operator |= (T const & a) + { + return *this = *this | a; + } + + template + interval & interval::operator &= (interval const & i) + { + return *this = *this & i; + } + + template + interval & interval::operator |= (interval const & i) + { + return *this = *this | i; + } + + template + T clamp (T x, interval const & i) + { + return std::max(i.min, std::min(i.max, x)); + } + + template + Stream & operator << (Stream & os, interval const & i) + { + return os << '[' << i.min << " .. " << i.max << ']'; + } + +} diff --git a/libs/geom/include/psemek/geom/matrix.hpp b/libs/geom/include/psemek/geom/matrix.hpp new file mode 100644 index 00000000..2f7f236b --- /dev/null +++ b/libs/geom/include/psemek/geom/matrix.hpp @@ -0,0 +1,238 @@ +#pragma once + +#include + +#include + +namespace psemek::geom +{ + + template + struct matrix + { + static constexpr std::size_t rows = R; + static constexpr std::size_t columns = C; + + using scalar_type = T; + + T coords[R * C]; + + T * operator [] (std::size_t i) + { + return coords + C * i; + } + + T const * operator [] (std::size_t i) const + { + return coords + C * i; + } + + matrix & operator *= (T const & s); + matrix & operator /= (T const & s); + + matrix & operator += (matrix const & v); + matrix & operator -= (matrix const & v); + + static matrix zero ( ); + static matrix identity ( ); + static matrix scalar (T const & s); + }; + + + template + matrix matrix::zero ( ) + { + matrix m; + for (std::size_t i = 0; i < R * C; ++i) + m.coords[i] = 0; + return m; + } + + template + matrix matrix::identity ( ) + { + return scalar(T{1}); + } + + template + matrix matrix::scalar (T const & s) + { + matrix m = zero(); + for (std::size_t i = 0; i < std::min(R, C); ++i) + for (std::size_t j = 0; j < C; ++j) + m[i][i] = s; + return m; + } + + template + bool operator == (matrix const & m1, matrix const & m2) + { + return std::equal(m1.coords, m1.coords + R * C, m2.coords); + } + + template + bool operator != (matrix const & m1, matrix const & m2) + { + return !(m1 == m2); + } + + template + bool operator < (matrix const & m1, matrix const & m2) + { + return std::lexicographical_compare(m1.coords, m1.coords + R * C, m2.coords, m2.coords + R * C); + } + + template + bool operator > (matrix const & m1, matrix const & m2) + { + return m2 < m1; + } + + template + bool operator <= (matrix const & m1, matrix const & m2) + { + return !(m2 < m1); + } + + template + bool operator >= (matrix const & m1, matrix const & m2) + { + return !(m1 < m2); + } + + template + matrix cast (matrix const & m) + { + matrix r; + for (std::size_t i = 0; i < R * C; ++i) + r.coords[i] = static_cast(m.coords[i]); + return r; + } + + template + matrix operator * (matrix const & m, T const & s) + { + matrix r; + for (std::size_t i = 0; i < R * C; ++i) + r.coords[i] = m.coords[i] * s; + return r; + } + + template + matrix operator * (T const & s, matrix const & m) + { + matrix r; + for (std::size_t i = 0; i < R * C; ++i) + r.coords[i] = s * m.coords[i]; + return r; + } + + template + matrix operator / (matrix const & m, T const & s) + { + matrix r; + for (std::size_t i = 0; i < R * C; ++i) + r.coords[i] = m.coords[i] / s; + return r; + } + + template + matrix & matrix::operator *= (T const & s) + { + *this = *this * s; + return *this; + } + + template + matrix & matrix::operator /= (T const & s) + { + *this = *this / s; + return *this; + } + + template + matrix operator + (matrix const & m1, matrix const & m2) + { + matrix r; + for (std::size_t i = 0; i < R * C; ++i) + r.coords[i] = m1.coords[i] + m2.coords[i]; + return r; + } + + template + matrix operator - (matrix const & m1, matrix const & m2) + { + matrix r; + for (std::size_t i = 0; i < R * C; ++i) + r.coords[i] = m1.coords[i] - m2.coords[i]; + return r; + } + + template + matrix & matrix::operator += (matrix const & m) + { + *this = *this + m; + return *this; + } + + template + matrix & matrix::operator -= (matrix const & m) + { + *this = *this - m; + return *this; + } + + template + vector operator * (matrix const & m, vector const & v) + { + vector r; + for (std::size_t i = 0; i < R; ++i) + { + r[i] = T{}; + for (std::size_t j = 0; j < C; ++j) + r[i] += m[i][j] * v[j]; + } + return r; + } + + template + vector operator * (vector const & v, matrix const & m) + { + vector r; + for (std::size_t j = 0; j < C; ++j) + { + r[j] = T{}; + for (std::size_t i = 0; i < R; ++i) + r[i] += v[j] * m[i][j]; + } + return r; + } + + template + matrix operator * (matrix const & m1, matrix const & m2) + { + matrix r; + for (std::size_t i = 0; i < R; ++i) + { + for (std::size_t j = 0; j < C; ++j) + { + r[i][j] = T{}; + + for (std::size_t k = 0; k < K; ++k) + r[i][j] += m1[i][k] * m2[k][j]; + } + } + return r; + } + + template + matrix transpose (matrix const & m) + { + matrix r; + for (std::size_t i = 0; i < R; ++i) + for (std::size_t j = 0; j < C; ++j) + r[j][i] = m[i][j]; + return r; + } + +} diff --git a/libs/geom/include/psemek/geom/orientation.hpp b/libs/geom/include/psemek/geom/orientation.hpp new file mode 100644 index 00000000..158a05e4 --- /dev/null +++ b/libs/geom/include/psemek/geom/orientation.hpp @@ -0,0 +1,67 @@ +#pragma once + +#include +#include +#include + +#include + +#include +#include + +namespace psemek::geom +{ + + // TODO: generic implementation + template + std::enable_if_t, sign_t> + orientation (point const & p0, point const & p1, point const & p2) + { + T const d = det(p1 - p0, p2 - p0); + + if (d > T{}) + return sign_t::positive; + else if (d < T{}) + return sign_t::negative; + else + return sign_t::zero; + } + + template + std::enable_if_t, sign_t> + orientation (point const & p0, point const & p1, point const & p2) + { + constexpr T error = std::numeric_limits::epsilon() * T(5) / T(2); + + T const d = (p1[0] - p0[0]) * (p2[1] - p0[1]) + - (p1[1] - p0[1]) * (p2[0] - p0[0]); + + T const t = std::abs((p1[0] - p0[0]) * (p2[1] - p0[1])) + + std::abs((p1[1] - p0[1]) * (p2[0] - p0[0])); + + if (d > t * error) + return sign_t::positive; + else if (d < - t * error) + return sign_t::negative; + else + { + using exact_type = boost::multiprecision::mpq_rational; + + return orientation(cast(p0), cast(p1), cast(p2)); + } + } + + template + sign_t orientation (point const & p0, point const & p1, point const & p2, point const & p3) + { + T const d = det(p0 - p3, p1 - p3, p2 - p3); + + if (d > T{}) + return sign_t::positive; + else if (d < T{}) + return sign_t::negative; + else + return sign_t::zero; + } + +} diff --git a/libs/geom/include/psemek/geom/orthographic.hpp b/libs/geom/include/psemek/geom/orthographic.hpp new file mode 100644 index 00000000..ed87fd65 --- /dev/null +++ b/libs/geom/include/psemek/geom/orthographic.hpp @@ -0,0 +1,92 @@ +#pragma once + +#include +#include +#include +#include +#include + +namespace psemek::geom +{ + + template + struct orthographic + { + using vector_type = vector; + using point_type = point; + using homogeneous_matrix_type = matrix; + using box_type = box; + + orthographic(); + orthographic(box_type r); + + box_type box() const; + box_type box(box_type r); + + vector_type operator() (vector_type v) const; + point_type operator() (point_type p) const; + + homogeneous_matrix_type homogeneous_matrix() const; + + orthographic inverse() const; + + private: + box_type r_; + }; + + template + orthographic::orthographic() + { + for (std::size_t i = 0; i < D; ++i) + { + r_[i] = {T(-1), T(1)}; + } + } + + template + orthographic::orthographic(box_type r) + : r_(r) + { } + + template + box orthographic::box() const + { + return r_; + } + + template + box orthographic::box(box_type r) + { + std::swap(r, r_); + return r; + } + + template + vector orthographic::operator() (vector v) const + { + return homogeneous_matrix() * homogeneous(v); + } + + template + point orthographic::operator() (point p) const + { + return homogeneous_matrix() * homogeneous(p); + } + + template + matrix orthographic::homogeneous_matrix() const + { + auto m = matrix::zero(); + + for (std::size_t d = 0; d < D; ++d) + m[d][d] = T(2) / (r_[d].max - r_[d].min); + + for (std::size_t d = 0; d < D; ++d) + m[d][D] = - (r_[d].max + r_[d].min) / (r_[d].max - r_[d].min); + + m[D][D] = T(1); + + return m; + } + +} diff --git a/libs/geom/include/psemek/geom/permutation.hpp b/libs/geom/include/psemek/geom/permutation.hpp new file mode 100644 index 00000000..8752f6dd --- /dev/null +++ b/libs/geom/include/psemek/geom/permutation.hpp @@ -0,0 +1,59 @@ +#pragma once + +#include +#include +#include + +namespace psemek::geom +{ + + template + struct swap + { + using vector_type = vector; + using point_type = point; + using matrix_type = matrix; + + swap(std::size_t i, std::size_t j); + + vector_type operator() (vector_type v) const; + + matrix_type matrix() const; + + swap inverse() const; + + private: + std::size_t i_, j_; + }; + + template + swap::swap (std::size_t i, std::size_t j) + : i_(i) + , j_(j) + { } + + template + vector swap::operator() (vector_type v) const + { + std::swap(v[i_], v[j_]); + return v; + } + + template + matrix swap::matrix() const + { + matrix_type m = matrix_type::identity(); + m[i_][i_] = 0; + m[j_][j_] = 0; + m[i_][j_] = 1; + m[j_][i_] = 1; + return m; + } + + template + swap swap::inverse() const + { + return *this; + } + +} diff --git a/libs/geom/include/psemek/geom/perspective.hpp b/libs/geom/include/psemek/geom/perspective.hpp new file mode 100644 index 00000000..a2c77c24 --- /dev/null +++ b/libs/geom/include/psemek/geom/perspective.hpp @@ -0,0 +1,61 @@ +#pragma once + +#include +#include + +namespace psemek::geom +{ + + template + struct perspective; + + template + struct perspective + { + using scalar_type = T; + using homogeneous_matrix_type = matrix; + + // fov are in radians + perspective (scalar_type fov_x, scalar_type fov_y, scalar_type near, scalar_type far); + + perspective (scalar_type left, scalar_type right, scalar_type bottom, scalar_type top, scalar_type near, scalar_type far); + + homogeneous_matrix_type homogeneous_matrix() const; + + private: + homogeneous_matrix_type homogeneous_matrix_; + }; + + template + perspective::perspective(scalar_type fov_x, scalar_type fov_y, scalar_type near, scalar_type far) + : homogeneous_matrix_(homogeneous_matrix_type::zero()) + { + scalar_type dx = 1 / std::tan(fov_x / 2); + scalar_type dy = 1 / std::tan(fov_y / 2); + homogeneous_matrix_[0][0] = dx; + homogeneous_matrix_[1][1] = dy; + homogeneous_matrix_[2][2] = (near + far) / (near - far); + homogeneous_matrix_[2][3] = 2 * near * far / (near - far); + homogeneous_matrix_[3][2] = -1; + } + + template + perspective::perspective(scalar_type left, scalar_type right, scalar_type bottom, scalar_type top, scalar_type near, scalar_type far) + : homogeneous_matrix_(homogeneous_matrix_type::zero()) + { + homogeneous_matrix_[0][0] = 2 * near / (right - left); + homogeneous_matrix_[1][1] = 2 * near / (top - bottom); + homogeneous_matrix_[0][2] = (right + left) / (right - left); + homogeneous_matrix_[1][2] = (top + bottom) / (top - bottom); + homogeneous_matrix_[2][2] = - (far + near) / (far - near); + homogeneous_matrix_[2][3] = - 2 * far * near / (far - near); + homogeneous_matrix_[3][2] = -1; + } + + template + matrix perspective::homogeneous_matrix() const + { + return homogeneous_matrix_; + } + +} diff --git a/libs/geom/include/psemek/geom/point.hpp b/libs/geom/include/psemek/geom/point.hpp new file mode 100644 index 00000000..1ba89db0 --- /dev/null +++ b/libs/geom/include/psemek/geom/point.hpp @@ -0,0 +1,173 @@ +#pragma once + +#include + +namespace psemek::geom +{ + + template + struct point + { + static constexpr std::size_t dimension = N; + + using scalar_type = T; + + T coords[N]; + + point ( ) = default; + point (point const &) = default; + point (point &) = default; + point (point &&) = default; + point & operator = (point const &) = default; + point & operator = (point &) = default; + point & operator = (point &&) = default; + + template + point (Args && ... args) + : coords{ std::forward(args)... } + { + static_assert(sizeof...(Args) == N); + } + + T & operator[] (std::size_t i) + { + return coords[i]; + } + + T const & operator[] (std::size_t i) const + { + return coords[i]; + } + + point & operator += (vector const & v); + point & operator -= (vector const & v); + }; + + template + point (Args && ...) -> point, sizeof...(Args)>; + + template + bool operator == (point const & p1, point const & p2) + { + for (std::size_t i = 0; i < N; ++i) + if (p1[i] != p2[i]) + return false; + return true; + } + + template + bool operator != (point const & p1, point const & p2) + { + return !(p1 == p2); + } + + template + bool operator < (point const & p1, point const & p2) + { + return std::lexicographical_compare(p1.coords, p1.coords + N, p2.coords, p2.coords + N); + } + + template + bool operator > (point const & p1, point const & p2) + { + return p2 < p1; + } + + template + bool operator <= (point const & p1, point const & p2) + { + return !(p2 < p1); + } + + template + bool operator >= (point const & p1, point const & p2) + { + return !(p1 < p2); + } + + template + point cast (point const & p) + { + point r; + for (std::size_t i = 0; i < N; ++i) + r[i] = T1(p[i]); + return r; + } + + template + point operator + (point const & p, vector const & v) + { + point r; + for (std::size_t i = 0; i < N; ++i) + r[i] = p[i] + v[i]; + return r; + } + + template + point operator + (vector const & v, point const & p) + { + point r; + for (std::size_t i = 0; i < N; ++i) + r[i] = v[i] + p[i]; + return r; + } + + template + point operator - (point const & p, vector const & v) + { + point r; + for (std::size_t i = 0; i < N; ++i) + r[i] = p[i] - v[i]; + return r; + } + + template + vector operator - (point const & p1, point const & p2) + { + vector r; + for (std::size_t i = 0; i < N; ++i) + r[i] = p1[i] - p2[i]; + return r; + } + + template + point & point::operator += (vector const & v) + { + return (*this) = (*this) + v; + } + + template + point & point::operator -= (vector const & v) + { + return (*this) = (*this) - v; + } + + template + point lerp (point const & p0, point const & p1, T const & t) + { + return p0 + t * (p1 - p0); + } + + template + T distance_sqr (point const & p1, point const & p2) + { + return length_sqr(p2 - p1); + } + + template + T distance (point const & p1, point const & p2) + { + return length(p2 - p1); + } + + template + Stream & operator << (Stream & os, point const & p) + { + os << '(' << p[0]; + for (std::size_t i = 1; i < N; ++i) + os << ", " << p[i]; + os << ')'; + return os; + } + +} diff --git a/libs/geom/include/psemek/geom/rotation.hpp b/libs/geom/include/psemek/geom/rotation.hpp new file mode 100644 index 00000000..54f2f50d --- /dev/null +++ b/libs/geom/include/psemek/geom/rotation.hpp @@ -0,0 +1,184 @@ +#pragma once + +#include +#include +#include +#include + +namespace psemek::geom +{ + + // Rotation in oriented plane (i,j) + template + struct plane_rotation + { + using scalar_type = T; + using vector_type = geom::vector; + using point_type = geom::point; + using matrix_type = geom::matrix; + + plane_rotation(std::size_t i, std::size_t j, T angle = T(0)); + + scalar_type angle() const; + scalar_type angle(scalar_type a); + + vector_type operator() (vector_type v) const; + + matrix_type matrix() const; + + plane_rotation inverse() const; + + private: + std::size_t const i_; + std::size_t const j_; + T angle_; + }; + + // 3D-rotation around an axis + template + struct axis_rotation + { + using scalar_type = T; + using vector_type = geom::vector; + using point_type = geom::point; + using matrix_type = geom::matrix; + + axis_rotation(); + axis_rotation(vector_type axis, scalar_type angle); + + vector_type axis() const; + vector_type axis(vector_type a); + + scalar_type angle() const; + scalar_type angle(scalar_type a); + + vector_type operator() (vector_type v) const; + + matrix_type matrix() const; + + axis_rotation inverse() const; + + private: + vector_type axis_; + scalar_type angle_; + }; + + template + plane_rotation::plane_rotation(std::size_t i, std::size_t j, T angle) + : i_(i), j_(j), angle_(angle) + { } + + template + T plane_rotation::angle() const + { + return angle_; + } + + template + T plane_rotation::angle(T a) + { + T t = angle_; + angle_ = a; + return t; + } + + template + vector plane_rotation::operator() (vector_type v) const + { + T vi = v[i_] * std::cos(angle_) - v[j_] * std::sin(angle_); + T vj = v[i_] * std::sin(angle_) + v[j_] * std::cos(angle_); + v[i_] = vi; + v[j_] = vj; + return v; + } + + template + matrix plane_rotation::matrix() const + { + matrix_type m = matrix_type::identity(); + m[i_][i_] = std::cos(angle_); + m[i_][j_] = -std::sin(angle_); + m[j_][i_] = std::sin(angle_); + m[j_][j_] = std::cos(angle_); + return m; + } + + template + plane_rotation plane_rotation::inverse() const + { + return {i_, j_, -angle_}; + } + + template + axis_rotation::axis_rotation() + : axis_rotation(vector_type{T(0), T(0), T(1)}, T(0)) + { } + + template + axis_rotation::axis_rotation(vector_type axis, scalar_type angle) + : axis_(axis) + , angle_(angle) + { } + + template + vector axis_rotation::axis() const + { + return axis_; + } + + template + vector axis_rotation::axis(vector_type a) + { + auto t = axis_; + axis_ = a; + return t; + } + + template + T axis_rotation::angle ( ) const + { + return angle_; + } + + template + T axis_rotation::angle(scalar_type a) + { + auto t = angle_; + angle_ = a; + return t; + } + + template + vector axis_rotation::operator() (vector_type v) const + { + return matrix() * v; + } + + template + matrix axis_rotation::matrix() const + { + matrix_type m = matrix_type::identity(); + T c = std::cos(angle_); + T s = std::sin(angle_); + T x = axis_[0]; + T y = axis_[1]; + T z = axis_[2]; + m[0][0] = c + x * x * (1 - c); + m[0][1] = x * y * (1 - c) - z * s; + m[0][2] = x * z * (1 - c) + y * s; + m[1][0] = y * x * (1 - c) + z * s; + m[1][1] = c + y * y * (1 - c); + m[1][2] = y * z * (1 - c) - x * s; + m[2][0] = z * x * (1 - c) - y * s; + m[2][1] = z * y * (1 - c) + x * s; + m[2][2] = c + z * z * (1 - c); + return m; + } + + template + axis_rotation axis_rotation::inverse() const + { + return {axis_, -angle_}; + } + +} diff --git a/libs/geom/include/psemek/geom/scale.hpp b/libs/geom/include/psemek/geom/scale.hpp new file mode 100644 index 00000000..0181b82c --- /dev/null +++ b/libs/geom/include/psemek/geom/scale.hpp @@ -0,0 +1,93 @@ +#pragma once + +#include +#include +#include + +namespace psemek::geom +{ + + template + struct scale + { + using vector_type = vector; + using point_type = point; + using matrix_type = matrix; + + scale(); + scale(T v); + scale(vector_type v); + + vector_type vector() const; + vector_type vector(vector_type v); + + vector_type operator() (vector_type v) const; + + matrix_type matrix() const; + + scale inverse() const; + + private: + vector_type v_; + }; + + template + scale::scale() + { + for (std::size_t i = 0; i < D; ++i) + v_[i] = T(1); + } + + template + scale::scale(T v) + { + for (std::size_t i = 0; i < D; ++i) + v_[i] = v; + } + + template + scale::scale(vector_type v) + : v_(v) + { } + + template + vector scale::vector() const + { + return v_; + } + + template + vector scale::vector(vector_type v) + { + auto t = v_; + v_ = v; + return t; + } + + template + vector scale::operator() (vector_type v) const + { + for (std::size_t i = 0; i < D; ++i) + v[i] *= v_[i]; + return v; + } + + template + matrix scale::matrix() const + { + matrix_type m = matrix_type::identity(); + for (std::size_t i = 0; i < D; ++i) + m[i][i] = v_[i]; + return m; + } + + template + scale scale::inverse() const + { + vector_type v; + for (std::size_t i = 0; i < D; ++i) + v[i] = T(1) / v_[i]; + return {v}; + } + +} diff --git a/libs/geom/include/psemek/geom/sign.hpp b/libs/geom/include/psemek/geom/sign.hpp new file mode 100644 index 00000000..3ba9fc4f --- /dev/null +++ b/libs/geom/include/psemek/geom/sign.hpp @@ -0,0 +1,26 @@ +#pragma once + +namespace psemek::geom +{ + + enum class sign_t : int + { + positive = 1, + zero = 0, + negative = -1, + }; + + template + OStream & operator << (OStream & o, sign_t s) + { + switch (s) + { + case sign_t::positive: return o << "positive"; + case sign_t::zero: return o << "zero"; + case sign_t::negative: return o << "negative"; + } + + return o; + } + +} diff --git a/libs/geom/include/psemek/geom/simplex.hpp b/libs/geom/include/psemek/geom/simplex.hpp new file mode 100644 index 00000000..a9f10522 --- /dev/null +++ b/libs/geom/include/psemek/geom/simplex.hpp @@ -0,0 +1,56 @@ +#pragma once + +#include + +#include + +namespace psemek::geom +{ + + template + struct simplex + { + using point_type = Point; + + point_type points[K + 1]; + + point_type & operator[] (std::size_t i) + { + return points[i]; + } + + point_type const & operator[] (std::size_t i) const + { + return points[i]; + } + }; + + template + simplex (Args ...) -> simplex, sizeof...(Args) - 1>; + + template + struct segment + : simplex + { }; + + template + segment (Point, Point) -> segment; + + template + struct triangle + : simplex + { }; + + template + triangle (Point, Point, Point) -> triangle; + + template + Stream & operator << (Stream & os, simplex const & s) + { + os << '(' << s[0]; + for (std::size_t i = 1; i <= K; ++i) + os << ", " << s[i]; + return os << ')'; + } + +} diff --git a/libs/geom/include/psemek/geom/translation.hpp b/libs/geom/include/psemek/geom/translation.hpp new file mode 100644 index 00000000..562d7d3e --- /dev/null +++ b/libs/geom/include/psemek/geom/translation.hpp @@ -0,0 +1,85 @@ +#pragma once + +#include +#include +#include + +namespace psemek::geom +{ + + template + struct translation + { + using vector_type = geom::vector; + using point_type = geom::point; + using homogeneous_matrix_type = geom::matrix; + + translation(); + translation(vector_type v); + + vector_type vector() const; + vector_type vector(vector_type v); + + vector_type operator() (vector_type v) const; + point_type operator() (point_type p) const; + + homogeneous_matrix_type homogeneous_matrix() const; + + translation inverse() const; + + private: + vector_type v_; + }; + + template + translation::translation() + : translation(vector_type::zero()) + { } + + template + translation::translation(vector_type v) + : v_(v) + { } + + template + vector translation::vector() const + { + return v_; + } + + template + vector translation::vector(vector_type v) + { + auto t = v_; + v_ = v; + return t; + } + + template + vector translation::operator() (vector_type v) const + { + return v; + } + + template + point translation::operator() (point_type p) const + { + return p + v_; + } + + template + matrix translation::homogeneous_matrix() const + { + homogeneous_matrix_type m = homogeneous_matrix_type::identity(); + for (std::size_t i = 0; i < D; ++i) + m[i][D] = v_[i]; + return m; + } + + template + translation translation::inverse() const + { + return {-v_}; + } + +} diff --git a/libs/geom/include/psemek/geom/vector.hpp b/libs/geom/include/psemek/geom/vector.hpp new file mode 100644 index 00000000..3229920b --- /dev/null +++ b/libs/geom/include/psemek/geom/vector.hpp @@ -0,0 +1,268 @@ +#pragma once + +#include +#include +#include +#include + +namespace psemek::geom +{ + + template + struct vector + { + static constexpr std::size_t dimension = N; + + using scalar_type = T; + + T coords[N]; + + vector ( ) = default; + vector (vector const &) = default; + vector (vector &) = default; + vector (vector &&) = default; + vector & operator = (vector const &) = default; + vector & operator = (vector &) = default; + vector & operator = (vector &&) = default; + + template + vector (Args && ... args) + : coords{ std::forward(args)... } + { + static_assert(sizeof...(Args) == N); + } + + T & operator[] (std::size_t i) + { + return coords[i]; + } + + T const & operator[] (std::size_t i) const + { + return coords[i]; + } + + vector & operator *= (T const & s); + vector & operator /= (T const & s); + + vector & operator += (vector const & v); + vector & operator -= (vector const & v); + + static vector zero(); + }; + + template + vector (Args && ...) -> vector, sizeof...(Args)>; + + template + bool operator == (vector const & v1, vector const & v2) + { + return std::equal(v1.coords, v1.coords + N, v2.coords); + } + + template + bool operator != (vector const & v1, vector const & v2) + { + return !(v1 == v2); + } + + template + bool operator < (vector const & v1, vector const & v2) + { + return std::lexicographical_compare(v1.coords, v1.coords + N, v2.coords, v2.coords + N); + } + + template + bool operator > (vector const & v1, vector const & v2) + { + return v2 < v1; + } + + template + bool operator <= (vector const & v1, vector const & v2) + { + return !(v2 < v1); + } + + template + bool operator >= (vector const & v1, vector const & v2) + { + return !(v1 < v2); + } + + template + vector cast (vector const & v) + { + vector r; + for (std::size_t i = 0; i < N; ++i) + r[i] = static_cast(v[i]); + return r; + } + + template + vector operator * (vector const & v, T const & s) + { + vector r; + for (std::size_t i = 0; i < N; ++i) + r[i] = v[i] * s; + return r; + } + + template + vector operator * (T const & s, vector const & v) + { + vector r; + for (std::size_t i = 0; i < N; ++i) + r[i] = s * v[i]; + return r; + } + + template + vector operator / (vector const & v, T const & s) + { + vector r; + for (std::size_t i = 0; i < N; ++i) + r[i] = v[i] / s; + return r; + } + + template + vector operator - (vector const & v) + { + vector r; + for (std::size_t i = 0; i < N; ++i) + r[i] = -v[i]; + return r; + } + + template + vector operator + (vector const & v1, vector const & v2) + { + vector r; + for (std::size_t i = 0; i < N; ++i) + r[i] = v1[i] + v2[i]; + return r; + } + + template + vector operator - (vector const & v1, vector const & v2) + { + vector r; + for (std::size_t i = 0; i < N; ++i) + r[i] = v1[i] - v2[i]; + return r; + } + + template + vector & vector::operator *= (T const & s) + { + return (*this) = (*this) * s; + } + + template + vector & vector::operator /= (T const & s) + { + return (*this) = (*this) / s; + } + + template + vector & vector::operator += (vector const & v) + { + return (*this) = (*this) + v; + } + + template + vector & vector::operator -= (vector const & v) + { + return (*this) = (*this) - v; + } + + template + vector vector::zero() + { + vector r; + for (std::size_t i = 0; i < N; ++i) + r[i] = T(0); + return r; + } + + template + T dot (vector const & v1, vector const & v2) + { + T r{}; + for (std::size_t i = 0; i < N; ++i) + r += v1[i] * v2[i]; + return r; + } + + template + T length_sqr (vector const & v) + { + return dot(v, v); + } + + template + T length (vector const & v) + { + return std::sqrt(length_sqr(v)); + } + + template + vector normalized (vector const & v) + { + return v / length(v); + } + + // TODO: generic implementation + template + T det (vector const & v0, vector const & v1) + { + return v0[0] * v1[1] - v0[1] * v1[0]; + } + + template + T det (vector const & v0, vector const & v1, vector const & v2) + { + return + + v0[0] * v1[1] * v2[2] + - v0[0] * v1[2] * v2[1] + - v0[1] * v1[0] * v2[2] + + v0[1] * v1[2] * v2[0] + + v0[2] * v1[0] * v2[1] + - v0[2] * v1[1] * v2[0] + ; + } + + template + vector cross (vector const & v0, vector const & v1) + { + return vector{ + v0[1] * v1[2] - v0[2] * v1[1], + v0[2] * v1[0] - v0[0] * v1[2], + v0[0] * v1[1] - v0[1] * v1[0], + }; + } + + template + T lerp (T const & x0, T const & x1, T const & t) + { + return x0 * (T(1) - t) + x1 * t; + } + + template + vector lerp (vector const & v0, vector const & v1, T const & t) + { + return v0 * (T(1) - t) + v1 * t; + } + + template + Stream & operator << (Stream & os, vector const & v) + { + os << '(' << v[0]; + for (std::size_t i = 1; i < N; ++i) + os << ", " << v[i]; + os << ')'; + return os; + } + +} diff --git a/libs/geom/source/camera.cpp b/libs/geom/source/camera.cpp new file mode 100644 index 00000000..83c591fe --- /dev/null +++ b/libs/geom/source/camera.cpp @@ -0,0 +1,86 @@ +#include +#include +#include +#include +#include +#include + +#include + +namespace psemek::geom +{ + + matrix camera::transform() const + { + return projection() * view(); + } + + point camera::position() const + { + vector b{ 0.f, 0.f, 0.f, 1.f }; + gauss(view(), b); + return { b[0], b[1], b[2] }; + } + + vector camera::axis_x() const + { + vector b{ 1.f, 0.f, 0.f, 0.f }; + gauss(view(), b); + return { b[0], b[1], b[2] }; + } + + vector camera::axis_y() const + { + vector b{ 0.f, 1.f, 0.f, 0.f }; + gauss(view(), b); + return { b[0], b[1], b[2] }; + } + + vector camera::axis_z() const + { + vector b{ 0.f, 0.f, 1.f, 0.f }; + gauss(view(), b); + return { b[0], b[1], b[2] }; + } + + vector camera::direction(float x, float y) const + { + vector b{ x, y, -1.f, 1.f}; + gauss(transform(), b); + + point p{ b[0] / b[3], b[1] / b[3], b[2] / b[3] }; + return p - position(); + } + + std::array, 6> camera::clip_planes() const + { + auto const m = transpose(transform()); + + std::array, 6> p; + + p[0] = m * vector{1.f, 0.f, 0.f, 1.f}; + p[1] = m * vector{-1.f, 0.f, 0.f, 1.f}; + p[2] = m * vector{0.f, 1.f, 0.f, 1.f}; + p[3] = m * vector{0.f, -1.f, 0.f, 1.f}; + p[4] = m * vector{0.f, 0.f, 1.f, 1.f}; + p[5] = m * vector{0.f, 0.f, -1.f, 1.f}; + + return p; + } + + matrix perspective_camera::projection() const + { + return perspective(fov_x, fov_y, near_clip, far_clip).homogeneous_matrix(); + } + + matrix spherical_camera::view() const + { + return + translation({0.f, 0.f, -distance}).homogeneous_matrix() + * homogeneous(plane_rotation(1, 2, elevation_angle).matrix()) + * homogeneous(plane_rotation(2, 0, azimuthal_angle).matrix()) + * translation({ -target[0], -target[1], -target[2] }).homogeneous_matrix() + ; + } + +} diff --git a/libs/gfx/CMakeLists.txt b/libs/gfx/CMakeLists.txt new file mode 100644 index 00000000..22e975cf --- /dev/null +++ b/libs/gfx/CMakeLists.txt @@ -0,0 +1,9 @@ +set(OpenGL_GL_PREFERENCE GLVND) +find_package(OpenGL REQUIRED) + +file(GLOB_RECURSE PSEMEK_GFX_HEADERS RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "include/*.hpp") +file(GLOB_RECURSE PSEMEK_GFX_SOURCES RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "source/*.cpp") + +add_library(gfx ${PSEMEK_GFX_HEADERS} ${PSEMEK_GFX_SOURCES}) +target_include_directories(gfx PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include") +target_link_libraries(gfx PUBLIC util geom OpenGL::GL) diff --git a/libs/gfx/include/psemek/gfx/buffer.hpp b/libs/gfx/include/psemek/gfx/buffer.hpp new file mode 100644 index 00000000..023cb254 --- /dev/null +++ b/libs/gfx/include/psemek/gfx/buffer.hpp @@ -0,0 +1,47 @@ +#pragma once + +#include + +#include + +namespace psemek::gfx +{ + + struct buffer + { + buffer(); + buffer(buffer const &) = delete; + buffer(buffer &&); + + buffer & operator = (buffer const &) = delete; + buffer & operator = (buffer &&); + + ~buffer(); + + static buffer null(); + + GLuint id() const { return id_; } + + void bind() const; + + void load(void const * data, std::size_t size, GLenum usage = gl::STREAM_DRAW); + + template + void load(T const * data, std::size_t size, GLenum usage = gl::STREAM_DRAW) + { + load(static_cast(data), size * sizeof(T), usage); + } + + template + void load(std::vector const & data, GLenum usage = gl::STREAM_DRAW) + { + load(data.data(), data.size(), usage); + } + + private: + GLuint id_; + + explicit buffer(GLuint id); + }; + +} diff --git a/libs/gfx/include/psemek/gfx/framebuffer.hpp b/libs/gfx/include/psemek/gfx/framebuffer.hpp new file mode 100644 index 00000000..b461f22c --- /dev/null +++ b/libs/gfx/include/psemek/gfx/framebuffer.hpp @@ -0,0 +1,41 @@ +#pragma once + +#include +#include +#include + +namespace psemek::gfx +{ + + struct framebuffer + { + framebuffer(); + framebuffer(framebuffer const &) = delete; + framebuffer(framebuffer &&); + + framebuffer & operator = (framebuffer const &) = delete; + framebuffer & operator = (framebuffer &&); + + ~framebuffer(); + + static framebuffer null(); + + GLuint id() const { return id_; } + + void bind() const; + + void color(texture_2d const & tex, int attachment = 0); + void color(renderbuffer const & rb, int attachment = 0); + void depth(renderbuffer const & rb); + + GLenum status() const; + bool complete() const; + void assert_complete() const; + + private: + GLuint id_; + + explicit framebuffer(GLuint id); + }; + +} diff --git a/libs/gfx/include/psemek/gfx/fullscreen.hpp b/libs/gfx/include/psemek/gfx/fullscreen.hpp new file mode 100644 index 00000000..07df9694 --- /dev/null +++ b/libs/gfx/include/psemek/gfx/fullscreen.hpp @@ -0,0 +1,10 @@ +#pragma once + +#include + +namespace psemek::gfx +{ + + indexed_mesh const & fullscreen_quad(); + +} diff --git a/libs/gfx/include/psemek/gfx/gl.hpp b/libs/gfx/include/psemek/gfx/gl.hpp new file mode 100644 index 00000000..655b61c9 --- /dev/null +++ b/libs/gfx/include/psemek/gfx/gl.hpp @@ -0,0 +1,1742 @@ +// Generated with glLoadGen-2.0.5 (https://bitbucket.org/alfonse/glloadgen) +// lua LoadGen.lua -style=func_cpp -spec=gl -version=3.3 -profile=core core_3_3 +// 18.07.2018 + +#ifndef FUNCTION_CPP_GENERATED_HEADEROPENGL_HPP +#define FUNCTION_CPP_GENERATED_HEADEROPENGL_HPP + +#if defined(__glew_h__) || defined(__GLEW_H__) +#error Attempt to include auto-generated header after including glew.h +#endif +#if defined(__gl_h_) || defined(__GL_H__) +#error Attempt to include auto-generated header after including gl.h +#endif +#if defined(__glext_h_) || defined(__GLEXT_H_) +#error Attempt to include auto-generated header after including glext.h +#endif +#if defined(__gltypes_h_) +#error Attempt to include auto-generated header after gltypes.h +#endif +#if defined(__gl_ATI_h_) +#error Attempt to include auto-generated header after including glATI.h +#endif + +#define __glew_h__ +#define __GLEW_H__ +#define __gl_h_ +#define __GL_H__ +#define __glext_h_ +#define __GLEXT_H_ +#define __gltypes_h_ +#define __gl_ATI_h_ + +#ifndef APIENTRY + #if defined(__MINGW32__) + #ifndef WIN32_LEAN_AND_MEAN + #define WIN32_LEAN_AND_MEAN 1 + #endif + #ifndef NOMINMAX + #define NOMINMAX + #endif + #include + #elif (_MSC_VER >= 800) || defined(_STDCALL_SUPPORTED) || defined(__BORLANDC__) + #ifndef WIN32_LEAN_AND_MEAN + #define WIN32_LEAN_AND_MEAN 1 + #endif + #ifndef NOMINMAX + #define NOMINMAX + #endif + #include + #else + #define APIENTRY + #endif +#endif /*APIENTRY*/ + +#ifndef CODEGEN_FUNCPTR + #define CODEGEN_REMOVE_FUNCPTR + #if defined(_WIN32) + #define CODEGEN_FUNCPTR APIENTRY + #else + #define CODEGEN_FUNCPTR + #endif +#endif /*CODEGEN_FUNCPTR*/ + +#ifndef GLAPI + #define GLAPI extern +#endif + + +#ifndef GL_LOAD_GEN_BASIC_OPENGL_TYPEDEFS +#define GL_LOAD_GEN_BASIC_OPENGL_TYPEDEFS + + +#endif /*GL_LOAD_GEN_BASIC_OPENGL_TYPEDEFS*/ + +#include +#ifndef GLEXT_64_TYPES_DEFINED +/* This code block is duplicated in glxext.h, so must be protected */ +#define GLEXT_64_TYPES_DEFINED +/* Define int32_t, int64_t, and uint64_t types for UST/MSC */ +/* (as used in the GL_EXT_timer_query extension). */ +#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L +#include +#elif defined(__sun__) || defined(__digital__) +#include +#if defined(__STDC__) +#if defined(__arch64__) || defined(_LP64) +typedef long int int64_t; +typedef unsigned long int uint64_t; +#else +typedef long long int int64_t; +typedef unsigned long long int uint64_t; +#endif /* __arch64__ */ +#endif /* __STDC__ */ +#elif defined( __VMS ) || defined(__sgi) +#include +#elif defined(__SCO__) || defined(__USLC__) +#include +#elif defined(__UNIXOS2__) || defined(__SOL64__) +typedef long int int32_t; +typedef long long int int64_t; +typedef unsigned long long int uint64_t; +#elif defined(_WIN32) && defined(__GNUC__) +#include +#elif defined(_WIN32) +typedef __int32 int32_t; +typedef __int64 int64_t; +typedef unsigned __int64 uint64_t; +#else +/* Fallback if nothing above works */ +#include +#endif +#endif + typedef unsigned int GLenum; + typedef unsigned char GLboolean; + typedef unsigned int GLbitfield; + typedef void GLvoid; + typedef signed char GLbyte; + typedef short GLshort; + typedef int GLint; + typedef unsigned char GLubyte; + typedef unsigned short GLushort; + typedef unsigned int GLuint; + typedef int GLsizei; + typedef float GLfloat; + typedef float GLclampf; + typedef double GLdouble; + typedef double GLclampd; + typedef char GLchar; + typedef char GLcharARB; + #ifdef __APPLE__ +typedef void *GLhandleARB; +#else +typedef unsigned int GLhandleARB; +#endif + typedef unsigned short GLhalfARB; + typedef unsigned short GLhalf; + typedef GLint GLfixed; + typedef ptrdiff_t GLintptr; + typedef ptrdiff_t GLsizeiptr; + typedef int64_t GLint64; + typedef uint64_t GLuint64; + typedef ptrdiff_t GLintptrARB; + typedef ptrdiff_t GLsizeiptrARB; + typedef int64_t GLint64EXT; + typedef uint64_t GLuint64EXT; + typedef struct __GLsync *GLsync; + struct _cl_context; + struct _cl_event; + typedef void (APIENTRY *GLDEBUGPROC)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,const void *userParam); + typedef void (APIENTRY *GLDEBUGPROCARB)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,const void *userParam); + typedef void (APIENTRY *GLDEBUGPROCAMD)(GLuint id,GLenum category,GLenum severity,GLsizei length,const GLchar *message,void *userParam); + typedef unsigned short GLhalfNV; + typedef GLintptr GLvdpauSurfaceNV; + +namespace gl +{ + namespace exts + { + class LoadTest + { + private: + //Safe bool idiom. Joy! + typedef void (LoadTest::*bool_type)() const; + void big_long_name_that_really_doesnt_matter() const {} + + public: + operator bool_type() const + { + return m_isLoaded ? &LoadTest::big_long_name_that_really_doesnt_matter : 0; + } + + int GetNumMissing() const {return m_numMissing;} + + LoadTest() : m_isLoaded(false), m_numMissing(0) {} + LoadTest(bool isLoaded, int numMissing) : m_isLoaded(isLoaded), m_numMissing(numMissing) {} + private: + bool m_isLoaded; + int m_numMissing; + }; + + } //namespace exts + enum + { + ALPHA = 0x1906, + ALWAYS = 0x0207, + AND = 0x1501, + AND_INVERTED = 0x1504, + AND_REVERSE = 0x1502, + BACK = 0x0405, + BACK_LEFT = 0x0402, + BACK_RIGHT = 0x0403, + BLEND = 0x0BE2, + BLEND_DST = 0x0BE0, + BLEND_SRC = 0x0BE1, + BLUE = 0x1905, + BYTE = 0x1400, + CCW = 0x0901, + CLEAR = 0x1500, + COLOR = 0x1800, + COLOR_BUFFER_BIT = 0x00004000, + COLOR_CLEAR_VALUE = 0x0C22, + COLOR_LOGIC_OP = 0x0BF2, + COLOR_WRITEMASK = 0x0C23, + COPY = 0x1503, + COPY_INVERTED = 0x150C, + CULL_FACE = 0x0B44, + CULL_FACE_MODE = 0x0B45, + CW = 0x0900, + DECR = 0x1E03, + DEPTH = 0x1801, + DEPTH_BUFFER_BIT = 0x00000100, + DEPTH_CLEAR_VALUE = 0x0B73, + DEPTH_COMPONENT = 0x1902, + DEPTH_FUNC = 0x0B74, + DEPTH_RANGE = 0x0B70, + DEPTH_TEST = 0x0B71, + DEPTH_WRITEMASK = 0x0B72, + DITHER = 0x0BD0, + DONT_CARE = 0x1100, + DOUBLE = 0x140A, + DOUBLEBUFFER = 0x0C32, + DRAW_BUFFER = 0x0C01, + DST_ALPHA = 0x0304, + DST_COLOR = 0x0306, + EQUAL = 0x0202, + EQUIV = 0x1509, + EXTENSIONS = 0x1F03, + FALSE_ = 0, + FASTEST = 0x1101, + FILL = 0x1B02, + FLOAT = 0x1406, + FRONT = 0x0404, + FRONT_AND_BACK = 0x0408, + FRONT_FACE = 0x0B46, + FRONT_LEFT = 0x0400, + FRONT_RIGHT = 0x0401, + GEQUAL = 0x0206, + GREATER = 0x0204, + GREEN = 0x1904, + INCR = 0x1E02, + INT = 0x1404, + INVALID_ENUM = 0x0500, + INVALID_OPERATION = 0x0502, + INVALID_VALUE = 0x0501, + INVERT = 0x150A, + KEEP = 0x1E00, + LEFT = 0x0406, + LEQUAL = 0x0203, + LESS = 0x0201, + LINE = 0x1B01, + LINEAR = 0x2601, + LINEAR_MIPMAP_LINEAR = 0x2703, + LINEAR_MIPMAP_NEAREST = 0x2701, + LINES = 0x0001, + LINE_LOOP = 0x0002, + LINE_SMOOTH = 0x0B20, + LINE_SMOOTH_HINT = 0x0C52, + LINE_STRIP = 0x0003, + LINE_WIDTH = 0x0B21, + LINE_WIDTH_GRANULARITY = 0x0B23, + LINE_WIDTH_RANGE = 0x0B22, + LOGIC_OP_MODE = 0x0BF0, + MAX_TEXTURE_SIZE = 0x0D33, + MAX_VIEWPORT_DIMS = 0x0D3A, + NAND = 0x150E, + NEAREST = 0x2600, + NEAREST_MIPMAP_LINEAR = 0x2702, + NEAREST_MIPMAP_NEAREST = 0x2700, + NEVER = 0x0200, + NICEST = 0x1102, + NONE = 0, + NOOP = 0x1505, + NOR = 0x1508, + NOTEQUAL = 0x0205, + NO_ERROR_ = 0, + ONE = 1, + ONE_MINUS_DST_ALPHA = 0x0305, + ONE_MINUS_DST_COLOR = 0x0307, + ONE_MINUS_SRC_ALPHA = 0x0303, + ONE_MINUS_SRC_COLOR = 0x0301, + OR = 0x1507, + OR_INVERTED = 0x150D, + OR_REVERSE = 0x150B, + OUT_OF_MEMORY = 0x0505, + PACK_ALIGNMENT = 0x0D05, + PACK_LSB_FIRST = 0x0D01, + PACK_ROW_LENGTH = 0x0D02, + PACK_SKIP_PIXELS = 0x0D04, + PACK_SKIP_ROWS = 0x0D03, + PACK_SWAP_BYTES = 0x0D00, + POINT = 0x1B00, + POINTS = 0x0000, + POINT_SIZE = 0x0B11, + POINT_SIZE_GRANULARITY = 0x0B13, + POINT_SIZE_RANGE = 0x0B12, + POLYGON_MODE = 0x0B40, + POLYGON_OFFSET_FACTOR = 0x8038, + POLYGON_OFFSET_FILL = 0x8037, + POLYGON_OFFSET_LINE = 0x2A02, + POLYGON_OFFSET_POINT = 0x2A01, + POLYGON_OFFSET_UNITS = 0x2A00, + POLYGON_SMOOTH = 0x0B41, + POLYGON_SMOOTH_HINT = 0x0C53, + PROXY_TEXTURE_1D = 0x8063, + PROXY_TEXTURE_2D = 0x8064, + R3_G3_B2 = 0x2A10, + READ_BUFFER = 0x0C02, + RED = 0x1903, + RENDERER = 0x1F01, + REPEAT = 0x2901, + REPLACE = 0x1E01, + RGB = 0x1907, + RGB10 = 0x8052, + RGB10_A2 = 0x8059, + RGB12 = 0x8053, + RGB16 = 0x8054, + RGB4 = 0x804F, + RGB5 = 0x8050, + RGB5_A1 = 0x8057, + RGB8 = 0x8051, + RGBA = 0x1908, + RGBA12 = 0x805A, + RGBA16 = 0x805B, + RGBA2 = 0x8055, + RGBA4 = 0x8056, + RGBA8 = 0x8058, + RIGHT = 0x0407, + SCISSOR_BOX = 0x0C10, + SCISSOR_TEST = 0x0C11, + SET = 0x150F, + SHORT = 0x1402, + SRC_ALPHA = 0x0302, + SRC_ALPHA_SATURATE = 0x0308, + SRC_COLOR = 0x0300, + STENCIL = 0x1802, + STENCIL_BUFFER_BIT = 0x00000400, + STENCIL_CLEAR_VALUE = 0x0B91, + STENCIL_FAIL = 0x0B94, + STENCIL_FUNC = 0x0B92, + STENCIL_INDEX = 0x1901, + STENCIL_PASS_DEPTH_FAIL = 0x0B95, + STENCIL_PASS_DEPTH_PASS = 0x0B96, + STENCIL_REF = 0x0B97, + STENCIL_TEST = 0x0B90, + STENCIL_VALUE_MASK = 0x0B93, + STENCIL_WRITEMASK = 0x0B98, + STEREO = 0x0C33, + SUBPIXEL_BITS = 0x0D50, + TEXTURE = 0x1702, + TEXTURE_1D = 0x0DE0, + TEXTURE_2D = 0x0DE1, + TEXTURE_ALPHA_SIZE = 0x805F, + TEXTURE_BINDING_1D = 0x8068, + TEXTURE_BINDING_2D = 0x8069, + TEXTURE_BLUE_SIZE = 0x805E, + TEXTURE_BORDER_COLOR = 0x1004, + TEXTURE_GREEN_SIZE = 0x805D, + TEXTURE_HEIGHT = 0x1001, + TEXTURE_INTERNAL_FORMAT = 0x1003, + TEXTURE_MAG_FILTER = 0x2800, + TEXTURE_MIN_FILTER = 0x2801, + TEXTURE_RED_SIZE = 0x805C, + TEXTURE_WIDTH = 0x1000, + TEXTURE_WRAP_S = 0x2802, + TEXTURE_WRAP_T = 0x2803, + TRIANGLES = 0x0004, + TRIANGLE_FAN = 0x0006, + TRIANGLE_STRIP = 0x0005, + TRUE_ = 1, + UNPACK_ALIGNMENT = 0x0CF5, + UNPACK_LSB_FIRST = 0x0CF1, + UNPACK_ROW_LENGTH = 0x0CF2, + UNPACK_SKIP_PIXELS = 0x0CF4, + UNPACK_SKIP_ROWS = 0x0CF3, + UNPACK_SWAP_BYTES = 0x0CF0, + UNSIGNED_BYTE = 0x1401, + UNSIGNED_INT = 0x1405, + UNSIGNED_SHORT = 0x1403, + VENDOR = 0x1F00, + VERSION = 0x1F02, + VIEWPORT = 0x0BA2, + XOR = 0x1506, + ZERO = 0, + + ALIASED_LINE_WIDTH_RANGE = 0x846E, + BGR = 0x80E0, + BGRA = 0x80E1, + CLAMP_TO_EDGE = 0x812F, + MAX_3D_TEXTURE_SIZE = 0x8073, + MAX_ELEMENTS_INDICES = 0x80E9, + MAX_ELEMENTS_VERTICES = 0x80E8, + PACK_IMAGE_HEIGHT = 0x806C, + PACK_SKIP_IMAGES = 0x806B, + PROXY_TEXTURE_3D = 0x8070, + SMOOTH_LINE_WIDTH_GRANULARITY = 0x0B23, + SMOOTH_LINE_WIDTH_RANGE = 0x0B22, + SMOOTH_POINT_SIZE_GRANULARITY = 0x0B13, + SMOOTH_POINT_SIZE_RANGE = 0x0B12, + TEXTURE_3D = 0x806F, + TEXTURE_BASE_LEVEL = 0x813C, + TEXTURE_BINDING_3D = 0x806A, + TEXTURE_DEPTH = 0x8071, + TEXTURE_MAX_LEVEL = 0x813D, + TEXTURE_MAX_LOD = 0x813B, + TEXTURE_MIN_LOD = 0x813A, + TEXTURE_WRAP_R = 0x8072, + UNPACK_IMAGE_HEIGHT = 0x806E, + UNPACK_SKIP_IMAGES = 0x806D, + UNSIGNED_BYTE_2_3_3_REV = 0x8362, + UNSIGNED_BYTE_3_3_2 = 0x8032, + UNSIGNED_INT_10_10_10_2 = 0x8036, + UNSIGNED_INT_2_10_10_10_REV = 0x8368, + UNSIGNED_INT_8_8_8_8 = 0x8035, + UNSIGNED_INT_8_8_8_8_REV = 0x8367, + UNSIGNED_SHORT_1_5_5_5_REV = 0x8366, + UNSIGNED_SHORT_4_4_4_4 = 0x8033, + UNSIGNED_SHORT_4_4_4_4_REV = 0x8365, + UNSIGNED_SHORT_5_5_5_1 = 0x8034, + UNSIGNED_SHORT_5_6_5 = 0x8363, + UNSIGNED_SHORT_5_6_5_REV = 0x8364, + + ACTIVE_TEXTURE = 0x84E0, + CLAMP_TO_BORDER = 0x812D, + COMPRESSED_RGB = 0x84ED, + COMPRESSED_RGBA = 0x84EE, + COMPRESSED_TEXTURE_FORMATS = 0x86A3, + MAX_CUBE_MAP_TEXTURE_SIZE = 0x851C, + MULTISAMPLE = 0x809D, + NUM_COMPRESSED_TEXTURE_FORMATS = 0x86A2, + PROXY_TEXTURE_CUBE_MAP = 0x851B, + SAMPLES = 0x80A9, + SAMPLE_ALPHA_TO_COVERAGE = 0x809E, + SAMPLE_ALPHA_TO_ONE = 0x809F, + SAMPLE_BUFFERS = 0x80A8, + SAMPLE_COVERAGE = 0x80A0, + SAMPLE_COVERAGE_INVERT = 0x80AB, + SAMPLE_COVERAGE_VALUE = 0x80AA, + TEXTURE0 = 0x84C0, + TEXTURE1 = 0x84C1, + TEXTURE10 = 0x84CA, + TEXTURE11 = 0x84CB, + TEXTURE12 = 0x84CC, + TEXTURE13 = 0x84CD, + TEXTURE14 = 0x84CE, + TEXTURE15 = 0x84CF, + TEXTURE16 = 0x84D0, + TEXTURE17 = 0x84D1, + TEXTURE18 = 0x84D2, + TEXTURE19 = 0x84D3, + TEXTURE2 = 0x84C2, + TEXTURE20 = 0x84D4, + TEXTURE21 = 0x84D5, + TEXTURE22 = 0x84D6, + TEXTURE23 = 0x84D7, + TEXTURE24 = 0x84D8, + TEXTURE25 = 0x84D9, + TEXTURE26 = 0x84DA, + TEXTURE27 = 0x84DB, + TEXTURE28 = 0x84DC, + TEXTURE29 = 0x84DD, + TEXTURE3 = 0x84C3, + TEXTURE30 = 0x84DE, + TEXTURE31 = 0x84DF, + TEXTURE4 = 0x84C4, + TEXTURE5 = 0x84C5, + TEXTURE6 = 0x84C6, + TEXTURE7 = 0x84C7, + TEXTURE8 = 0x84C8, + TEXTURE9 = 0x84C9, + TEXTURE_BINDING_CUBE_MAP = 0x8514, + TEXTURE_COMPRESSED = 0x86A1, + TEXTURE_COMPRESSED_IMAGE_SIZE = 0x86A0, + TEXTURE_COMPRESSION_HINT = 0x84EF, + TEXTURE_CUBE_MAP = 0x8513, + TEXTURE_CUBE_MAP_NEGATIVE_X = 0x8516, + TEXTURE_CUBE_MAP_NEGATIVE_Y = 0x8518, + TEXTURE_CUBE_MAP_NEGATIVE_Z = 0x851A, + TEXTURE_CUBE_MAP_POSITIVE_X = 0x8515, + TEXTURE_CUBE_MAP_POSITIVE_Y = 0x8517, + TEXTURE_CUBE_MAP_POSITIVE_Z = 0x8519, + + BLEND_COLOR = 0x8005, + BLEND_DST_ALPHA = 0x80CA, + BLEND_DST_RGB = 0x80C8, + BLEND_SRC_ALPHA = 0x80CB, + BLEND_SRC_RGB = 0x80C9, + CONSTANT_ALPHA = 0x8003, + CONSTANT_COLOR = 0x8001, + DECR_WRAP = 0x8508, + DEPTH_COMPONENT16 = 0x81A5, + DEPTH_COMPONENT24 = 0x81A6, + DEPTH_COMPONENT32 = 0x81A7, + FUNC_ADD = 0x8006, + FUNC_REVERSE_SUBTRACT = 0x800B, + FUNC_SUBTRACT = 0x800A, + INCR_WRAP = 0x8507, + MAX = 0x8008, + MAX_TEXTURE_LOD_BIAS = 0x84FD, + MIN = 0x8007, + MIRRORED_REPEAT = 0x8370, + ONE_MINUS_CONSTANT_ALPHA = 0x8004, + ONE_MINUS_CONSTANT_COLOR = 0x8002, + POINT_FADE_THRESHOLD_SIZE = 0x8128, + TEXTURE_COMPARE_FUNC = 0x884D, + TEXTURE_COMPARE_MODE = 0x884C, + TEXTURE_DEPTH_SIZE = 0x884A, + TEXTURE_LOD_BIAS = 0x8501, + + ARRAY_BUFFER = 0x8892, + ARRAY_BUFFER_BINDING = 0x8894, + BUFFER_ACCESS = 0x88BB, + BUFFER_MAPPED = 0x88BC, + BUFFER_MAP_POINTER = 0x88BD, + BUFFER_SIZE = 0x8764, + BUFFER_USAGE = 0x8765, + CURRENT_QUERY = 0x8865, + DYNAMIC_COPY = 0x88EA, + DYNAMIC_DRAW = 0x88E8, + DYNAMIC_READ = 0x88E9, + ELEMENT_ARRAY_BUFFER = 0x8893, + ELEMENT_ARRAY_BUFFER_BINDING = 0x8895, + QUERY_COUNTER_BITS = 0x8864, + QUERY_RESULT = 0x8866, + QUERY_RESULT_AVAILABLE = 0x8867, + READ_ONLY = 0x88B8, + READ_WRITE = 0x88BA, + SAMPLES_PASSED = 0x8914, + SRC1_ALPHA = 0x8589, + STATIC_COPY = 0x88E6, + STATIC_DRAW = 0x88E4, + STATIC_READ = 0x88E5, + STREAM_COPY = 0x88E2, + STREAM_DRAW = 0x88E0, + STREAM_READ = 0x88E1, + VERTEX_ATTRIB_ARRAY_BUFFER_BINDING = 0x889F, + WRITE_ONLY = 0x88B9, + + ACTIVE_ATTRIBUTES = 0x8B89, + ACTIVE_ATTRIBUTE_MAX_LENGTH = 0x8B8A, + ACTIVE_UNIFORMS = 0x8B86, + ACTIVE_UNIFORM_MAX_LENGTH = 0x8B87, + ATTACHED_SHADERS = 0x8B85, + BLEND_EQUATION_ALPHA = 0x883D, + BLEND_EQUATION_RGB = 0x8009, + BOOL = 0x8B56, + BOOL_VEC2 = 0x8B57, + BOOL_VEC3 = 0x8B58, + BOOL_VEC4 = 0x8B59, + COMPILE_STATUS = 0x8B81, + CURRENT_PROGRAM = 0x8B8D, + CURRENT_VERTEX_ATTRIB = 0x8626, + DELETE_STATUS = 0x8B80, + DRAW_BUFFER0 = 0x8825, + DRAW_BUFFER1 = 0x8826, + DRAW_BUFFER10 = 0x882F, + DRAW_BUFFER11 = 0x8830, + DRAW_BUFFER12 = 0x8831, + DRAW_BUFFER13 = 0x8832, + DRAW_BUFFER14 = 0x8833, + DRAW_BUFFER15 = 0x8834, + DRAW_BUFFER2 = 0x8827, + DRAW_BUFFER3 = 0x8828, + DRAW_BUFFER4 = 0x8829, + DRAW_BUFFER5 = 0x882A, + DRAW_BUFFER6 = 0x882B, + DRAW_BUFFER7 = 0x882C, + DRAW_BUFFER8 = 0x882D, + DRAW_BUFFER9 = 0x882E, + FLOAT_MAT2 = 0x8B5A, + FLOAT_MAT3 = 0x8B5B, + FLOAT_MAT4 = 0x8B5C, + FLOAT_VEC2 = 0x8B50, + FLOAT_VEC3 = 0x8B51, + FLOAT_VEC4 = 0x8B52, + FRAGMENT_SHADER = 0x8B30, + FRAGMENT_SHADER_DERIVATIVE_HINT = 0x8B8B, + INFO_LOG_LENGTH = 0x8B84, + INT_VEC2 = 0x8B53, + INT_VEC3 = 0x8B54, + INT_VEC4 = 0x8B55, + LINK_STATUS = 0x8B82, + LOWER_LEFT = 0x8CA1, + MAX_COMBINED_TEXTURE_IMAGE_UNITS = 0x8B4D, + MAX_DRAW_BUFFERS = 0x8824, + MAX_FRAGMENT_UNIFORM_COMPONENTS = 0x8B49, + MAX_TEXTURE_IMAGE_UNITS = 0x8872, + MAX_VARYING_FLOATS = 0x8B4B, + MAX_VERTEX_ATTRIBS = 0x8869, + MAX_VERTEX_TEXTURE_IMAGE_UNITS = 0x8B4C, + MAX_VERTEX_UNIFORM_COMPONENTS = 0x8B4A, + POINT_SPRITE_COORD_ORIGIN = 0x8CA0, + SAMPLER_1D = 0x8B5D, + SAMPLER_1D_SHADOW = 0x8B61, + SAMPLER_2D = 0x8B5E, + SAMPLER_2D_SHADOW = 0x8B62, + SAMPLER_3D = 0x8B5F, + SAMPLER_CUBE = 0x8B60, + SHADER_SOURCE_LENGTH = 0x8B88, + SHADER_TYPE = 0x8B4F, + SHADING_LANGUAGE_VERSION = 0x8B8C, + STENCIL_BACK_FAIL = 0x8801, + STENCIL_BACK_FUNC = 0x8800, + STENCIL_BACK_PASS_DEPTH_FAIL = 0x8802, + STENCIL_BACK_PASS_DEPTH_PASS = 0x8803, + STENCIL_BACK_REF = 0x8CA3, + STENCIL_BACK_VALUE_MASK = 0x8CA4, + STENCIL_BACK_WRITEMASK = 0x8CA5, + UPPER_LEFT = 0x8CA2, + VALIDATE_STATUS = 0x8B83, + VERTEX_ATTRIB_ARRAY_ENABLED = 0x8622, + VERTEX_ATTRIB_ARRAY_NORMALIZED = 0x886A, + VERTEX_ATTRIB_ARRAY_POINTER = 0x8645, + VERTEX_ATTRIB_ARRAY_SIZE = 0x8623, + VERTEX_ATTRIB_ARRAY_STRIDE = 0x8624, + VERTEX_ATTRIB_ARRAY_TYPE = 0x8625, + VERTEX_PROGRAM_POINT_SIZE = 0x8642, + VERTEX_SHADER = 0x8B31, + + COMPRESSED_SRGB = 0x8C48, + COMPRESSED_SRGB_ALPHA = 0x8C49, + FLOAT_MAT2x3 = 0x8B65, + FLOAT_MAT2x4 = 0x8B66, + FLOAT_MAT3x2 = 0x8B67, + FLOAT_MAT3x4 = 0x8B68, + FLOAT_MAT4x2 = 0x8B69, + FLOAT_MAT4x3 = 0x8B6A, + PIXEL_PACK_BUFFER = 0x88EB, + PIXEL_PACK_BUFFER_BINDING = 0x88ED, + PIXEL_UNPACK_BUFFER = 0x88EC, + PIXEL_UNPACK_BUFFER_BINDING = 0x88EF, + SRGB = 0x8C40, + SRGB8 = 0x8C41, + SRGB8_ALPHA8 = 0x8C43, + SRGB_ALPHA = 0x8C42, + + BGRA_INTEGER = 0x8D9B, + BGR_INTEGER = 0x8D9A, + BLUE_INTEGER = 0x8D96, + BUFFER_ACCESS_FLAGS = 0x911F, + BUFFER_MAP_LENGTH = 0x9120, + BUFFER_MAP_OFFSET = 0x9121, + CLAMP_READ_COLOR = 0x891C, + CLIP_DISTANCE0 = 0x3000, + CLIP_DISTANCE1 = 0x3001, + CLIP_DISTANCE2 = 0x3002, + CLIP_DISTANCE3 = 0x3003, + CLIP_DISTANCE4 = 0x3004, + CLIP_DISTANCE5 = 0x3005, + CLIP_DISTANCE6 = 0x3006, + CLIP_DISTANCE7 = 0x3007, + COLOR_ATTACHMENT0 = 0x8CE0, + COLOR_ATTACHMENT1 = 0x8CE1, + COLOR_ATTACHMENT10 = 0x8CEA, + COLOR_ATTACHMENT11 = 0x8CEB, + COLOR_ATTACHMENT12 = 0x8CEC, + COLOR_ATTACHMENT13 = 0x8CED, + COLOR_ATTACHMENT14 = 0x8CEE, + COLOR_ATTACHMENT15 = 0x8CEF, + COLOR_ATTACHMENT16 = 0x8CF0, + COLOR_ATTACHMENT17 = 0x8CF1, + COLOR_ATTACHMENT18 = 0x8CF2, + COLOR_ATTACHMENT19 = 0x8CF3, + COLOR_ATTACHMENT2 = 0x8CE2, + COLOR_ATTACHMENT20 = 0x8CF4, + COLOR_ATTACHMENT21 = 0x8CF5, + COLOR_ATTACHMENT22 = 0x8CF6, + COLOR_ATTACHMENT23 = 0x8CF7, + COLOR_ATTACHMENT24 = 0x8CF8, + COLOR_ATTACHMENT25 = 0x8CF9, + COLOR_ATTACHMENT26 = 0x8CFA, + COLOR_ATTACHMENT27 = 0x8CFB, + COLOR_ATTACHMENT28 = 0x8CFC, + COLOR_ATTACHMENT29 = 0x8CFD, + COLOR_ATTACHMENT3 = 0x8CE3, + COLOR_ATTACHMENT30 = 0x8CFE, + COLOR_ATTACHMENT31 = 0x8CFF, + COLOR_ATTACHMENT4 = 0x8CE4, + COLOR_ATTACHMENT5 = 0x8CE5, + COLOR_ATTACHMENT6 = 0x8CE6, + COLOR_ATTACHMENT7 = 0x8CE7, + COLOR_ATTACHMENT8 = 0x8CE8, + COLOR_ATTACHMENT9 = 0x8CE9, + COMPARE_REF_TO_TEXTURE = 0x884E, + COMPRESSED_RED = 0x8225, + COMPRESSED_RED_RGTC1 = 0x8DBB, + COMPRESSED_RG = 0x8226, + COMPRESSED_RG_RGTC2 = 0x8DBD, + COMPRESSED_SIGNED_RED_RGTC1 = 0x8DBC, + COMPRESSED_SIGNED_RG_RGTC2 = 0x8DBE, + CONTEXT_FLAGS = 0x821E, + CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT = 0x00000001, + DEPTH24_STENCIL8 = 0x88F0, + DEPTH32F_STENCIL8 = 0x8CAD, + DEPTH_ATTACHMENT = 0x8D00, + DEPTH_COMPONENT32F = 0x8CAC, + DEPTH_STENCIL = 0x84F9, + DEPTH_STENCIL_ATTACHMENT = 0x821A, + DRAW_FRAMEBUFFER = 0x8CA9, + DRAW_FRAMEBUFFER_BINDING = 0x8CA6, + FIXED_ONLY = 0x891D, + FLOAT_32_UNSIGNED_INT_24_8_REV = 0x8DAD, + FRAMEBUFFER = 0x8D40, + FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE = 0x8215, + FRAMEBUFFER_ATTACHMENT_BLUE_SIZE = 0x8214, + FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING = 0x8210, + FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE = 0x8211, + FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE = 0x8216, + FRAMEBUFFER_ATTACHMENT_GREEN_SIZE = 0x8213, + FRAMEBUFFER_ATTACHMENT_OBJECT_NAME = 0x8CD1, + FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE = 0x8CD0, + FRAMEBUFFER_ATTACHMENT_RED_SIZE = 0x8212, + FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE = 0x8217, + FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE = 0x8CD3, + FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER = 0x8CD4, + FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL = 0x8CD2, + FRAMEBUFFER_BINDING = 0x8CA6, + FRAMEBUFFER_COMPLETE = 0x8CD5, + FRAMEBUFFER_DEFAULT = 0x8218, + FRAMEBUFFER_INCOMPLETE_ATTACHMENT = 0x8CD6, + FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER = 0x8CDB, + FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT = 0x8CD7, + FRAMEBUFFER_INCOMPLETE_MULTISAMPLE = 0x8D56, + FRAMEBUFFER_INCOMPLETE_READ_BUFFER = 0x8CDC, + FRAMEBUFFER_SRGB = 0x8DB9, + FRAMEBUFFER_UNDEFINED = 0x8219, + FRAMEBUFFER_UNSUPPORTED = 0x8CDD, + GREEN_INTEGER = 0x8D95, + HALF_FLOAT = 0x140B, + INTERLEAVED_ATTRIBS = 0x8C8C, + INT_SAMPLER_1D = 0x8DC9, + INT_SAMPLER_1D_ARRAY = 0x8DCE, + INT_SAMPLER_2D = 0x8DCA, + INT_SAMPLER_2D_ARRAY = 0x8DCF, + INT_SAMPLER_3D = 0x8DCB, + INT_SAMPLER_CUBE = 0x8DCC, + INVALID_FRAMEBUFFER_OPERATION = 0x0506, + MAJOR_VERSION = 0x821B, + MAP_FLUSH_EXPLICIT_BIT = 0x0010, + MAP_INVALIDATE_BUFFER_BIT = 0x0008, + MAP_INVALIDATE_RANGE_BIT = 0x0004, + MAP_READ_BIT = 0x0001, + MAP_UNSYNCHRONIZED_BIT = 0x0020, + MAP_WRITE_BIT = 0x0002, + MAX_ARRAY_TEXTURE_LAYERS = 0x88FF, + MAX_CLIP_DISTANCES = 0x0D32, + MAX_COLOR_ATTACHMENTS = 0x8CDF, + MAX_PROGRAM_TEXEL_OFFSET = 0x8905, + MAX_RENDERBUFFER_SIZE = 0x84E8, + MAX_SAMPLES = 0x8D57, + MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS = 0x8C8A, + MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS = 0x8C8B, + MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS = 0x8C80, + MAX_VARYING_COMPONENTS = 0x8B4B, + MINOR_VERSION = 0x821C, + MIN_PROGRAM_TEXEL_OFFSET = 0x8904, + NUM_EXTENSIONS = 0x821D, + PRIMITIVES_GENERATED = 0x8C87, + PROXY_TEXTURE_1D_ARRAY = 0x8C19, + PROXY_TEXTURE_2D_ARRAY = 0x8C1B, + QUERY_BY_REGION_NO_WAIT = 0x8E16, + QUERY_BY_REGION_WAIT = 0x8E15, + QUERY_NO_WAIT = 0x8E14, + QUERY_WAIT = 0x8E13, + R11F_G11F_B10F = 0x8C3A, + R16 = 0x822A, + R16F = 0x822D, + R16I = 0x8233, + R16UI = 0x8234, + R32F = 0x822E, + R32I = 0x8235, + R32UI = 0x8236, + R8 = 0x8229, + R8I = 0x8231, + R8UI = 0x8232, + RASTERIZER_DISCARD = 0x8C89, + READ_FRAMEBUFFER = 0x8CA8, + READ_FRAMEBUFFER_BINDING = 0x8CAA, + RED_INTEGER = 0x8D94, + RENDERBUFFER = 0x8D41, + RENDERBUFFER_ALPHA_SIZE = 0x8D53, + RENDERBUFFER_BINDING = 0x8CA7, + RENDERBUFFER_BLUE_SIZE = 0x8D52, + RENDERBUFFER_DEPTH_SIZE = 0x8D54, + RENDERBUFFER_GREEN_SIZE = 0x8D51, + RENDERBUFFER_HEIGHT = 0x8D43, + RENDERBUFFER_INTERNAL_FORMAT = 0x8D44, + RENDERBUFFER_RED_SIZE = 0x8D50, + RENDERBUFFER_SAMPLES = 0x8CAB, + RENDERBUFFER_STENCIL_SIZE = 0x8D55, + RENDERBUFFER_WIDTH = 0x8D42, + RG = 0x8227, + RG16 = 0x822C, + RG16F = 0x822F, + RG16I = 0x8239, + RG16UI = 0x823A, + RG32F = 0x8230, + RG32I = 0x823B, + RG32UI = 0x823C, + RG8 = 0x822B, + RG8I = 0x8237, + RG8UI = 0x8238, + RGB16F = 0x881B, + RGB16I = 0x8D89, + RGB16UI = 0x8D77, + RGB32F = 0x8815, + RGB32I = 0x8D83, + RGB32UI = 0x8D71, + RGB8I = 0x8D8F, + RGB8UI = 0x8D7D, + RGB9_E5 = 0x8C3D, + RGBA16F = 0x881A, + RGBA16I = 0x8D88, + RGBA16UI = 0x8D76, + RGBA32F = 0x8814, + RGBA32I = 0x8D82, + RGBA32UI = 0x8D70, + RGBA8I = 0x8D8E, + RGBA8UI = 0x8D7C, + RGBA_INTEGER = 0x8D99, + RGB_INTEGER = 0x8D98, + RG_INTEGER = 0x8228, + SAMPLER_1D_ARRAY = 0x8DC0, + SAMPLER_1D_ARRAY_SHADOW = 0x8DC3, + SAMPLER_2D_ARRAY = 0x8DC1, + SAMPLER_2D_ARRAY_SHADOW = 0x8DC4, + SAMPLER_CUBE_SHADOW = 0x8DC5, + SEPARATE_ATTRIBS = 0x8C8D, + STENCIL_ATTACHMENT = 0x8D20, + STENCIL_INDEX1 = 0x8D46, + STENCIL_INDEX16 = 0x8D49, + STENCIL_INDEX4 = 0x8D47, + STENCIL_INDEX8 = 0x8D48, + TEXTURE_1D_ARRAY = 0x8C18, + TEXTURE_2D_ARRAY = 0x8C1A, + TEXTURE_ALPHA_TYPE = 0x8C13, + TEXTURE_BINDING_1D_ARRAY = 0x8C1C, + TEXTURE_BINDING_2D_ARRAY = 0x8C1D, + TEXTURE_BLUE_TYPE = 0x8C12, + TEXTURE_DEPTH_TYPE = 0x8C16, + TEXTURE_GREEN_TYPE = 0x8C11, + TEXTURE_RED_TYPE = 0x8C10, + TEXTURE_SHARED_SIZE = 0x8C3F, + TEXTURE_STENCIL_SIZE = 0x88F1, + TRANSFORM_FEEDBACK_BUFFER = 0x8C8E, + TRANSFORM_FEEDBACK_BUFFER_BINDING = 0x8C8F, + TRANSFORM_FEEDBACK_BUFFER_MODE = 0x8C7F, + TRANSFORM_FEEDBACK_BUFFER_SIZE = 0x8C85, + TRANSFORM_FEEDBACK_BUFFER_START = 0x8C84, + TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN = 0x8C88, + TRANSFORM_FEEDBACK_VARYINGS = 0x8C83, + TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH = 0x8C76, + UNSIGNED_INT_10F_11F_11F_REV = 0x8C3B, + UNSIGNED_INT_24_8 = 0x84FA, + UNSIGNED_INT_5_9_9_9_REV = 0x8C3E, + UNSIGNED_INT_SAMPLER_1D = 0x8DD1, + UNSIGNED_INT_SAMPLER_1D_ARRAY = 0x8DD6, + UNSIGNED_INT_SAMPLER_2D = 0x8DD2, + UNSIGNED_INT_SAMPLER_2D_ARRAY = 0x8DD7, + UNSIGNED_INT_SAMPLER_3D = 0x8DD3, + UNSIGNED_INT_SAMPLER_CUBE = 0x8DD4, + UNSIGNED_INT_VEC2 = 0x8DC6, + UNSIGNED_INT_VEC3 = 0x8DC7, + UNSIGNED_INT_VEC4 = 0x8DC8, + UNSIGNED_NORMALIZED = 0x8C17, + VERTEX_ARRAY_BINDING = 0x85B5, + VERTEX_ATTRIB_ARRAY_INTEGER = 0x88FD, + + ACTIVE_UNIFORM_BLOCKS = 0x8A36, + ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH = 0x8A35, + COPY_READ_BUFFER = 0x8F36, + COPY_WRITE_BUFFER = 0x8F37, + INT_SAMPLER_2D_RECT = 0x8DCD, + INT_SAMPLER_BUFFER = 0x8DD0, + INVALID_INDEX = 0xFFFFFFFF, + MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS = 0x8A33, + MAX_COMBINED_GEOMETRY_UNIFORM_COMPONENTS = 0x8A32, + MAX_COMBINED_UNIFORM_BLOCKS = 0x8A2E, + MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS = 0x8A31, + MAX_FRAGMENT_UNIFORM_BLOCKS = 0x8A2D, + MAX_GEOMETRY_UNIFORM_BLOCKS = 0x8A2C, + MAX_RECTANGLE_TEXTURE_SIZE = 0x84F8, + MAX_TEXTURE_BUFFER_SIZE = 0x8C2B, + MAX_UNIFORM_BLOCK_SIZE = 0x8A30, + MAX_UNIFORM_BUFFER_BINDINGS = 0x8A2F, + MAX_VERTEX_UNIFORM_BLOCKS = 0x8A2B, + PRIMITIVE_RESTART = 0x8F9D, + PRIMITIVE_RESTART_INDEX = 0x8F9E, + PROXY_TEXTURE_RECTANGLE = 0x84F7, + R16_SNORM = 0x8F98, + R8_SNORM = 0x8F94, + RG16_SNORM = 0x8F99, + RG8_SNORM = 0x8F95, + RGB16_SNORM = 0x8F9A, + RGB8_SNORM = 0x8F96, + RGBA16_SNORM = 0x8F9B, + RGBA8_SNORM = 0x8F97, + SAMPLER_2D_RECT = 0x8B63, + SAMPLER_2D_RECT_SHADOW = 0x8B64, + SAMPLER_BUFFER = 0x8DC2, + SIGNED_NORMALIZED = 0x8F9C, + TEXTURE_BINDING_BUFFER = 0x8C2C, + TEXTURE_BINDING_RECTANGLE = 0x84F6, + TEXTURE_BUFFER = 0x8C2A, + TEXTURE_BUFFER_DATA_STORE_BINDING = 0x8C2D, + TEXTURE_RECTANGLE = 0x84F5, + UNIFORM_ARRAY_STRIDE = 0x8A3C, + UNIFORM_BLOCK_ACTIVE_UNIFORMS = 0x8A42, + UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES = 0x8A43, + UNIFORM_BLOCK_BINDING = 0x8A3F, + UNIFORM_BLOCK_DATA_SIZE = 0x8A40, + UNIFORM_BLOCK_INDEX = 0x8A3A, + UNIFORM_BLOCK_NAME_LENGTH = 0x8A41, + UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER = 0x8A46, + UNIFORM_BLOCK_REFERENCED_BY_GEOMETRY_SHADER = 0x8A45, + UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER = 0x8A44, + UNIFORM_BUFFER = 0x8A11, + UNIFORM_BUFFER_BINDING = 0x8A28, + UNIFORM_BUFFER_OFFSET_ALIGNMENT = 0x8A34, + UNIFORM_BUFFER_SIZE = 0x8A2A, + UNIFORM_BUFFER_START = 0x8A29, + UNIFORM_IS_ROW_MAJOR = 0x8A3E, + UNIFORM_MATRIX_STRIDE = 0x8A3D, + UNIFORM_NAME_LENGTH = 0x8A39, + UNIFORM_OFFSET = 0x8A3B, + UNIFORM_SIZE = 0x8A38, + UNIFORM_TYPE = 0x8A37, + UNSIGNED_INT_SAMPLER_2D_RECT = 0x8DD5, + UNSIGNED_INT_SAMPLER_BUFFER = 0x8DD8, + + ALREADY_SIGNALED = 0x911A, + CONDITION_SATISFIED = 0x911C, + CONTEXT_COMPATIBILITY_PROFILE_BIT = 0x00000002, + CONTEXT_CORE_PROFILE_BIT = 0x00000001, + CONTEXT_PROFILE_MASK = 0x9126, + DEPTH_CLAMP = 0x864F, + FIRST_VERTEX_CONVENTION = 0x8E4D, + FRAMEBUFFER_ATTACHMENT_LAYERED = 0x8DA7, + FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS = 0x8DA8, + GEOMETRY_INPUT_TYPE = 0x8917, + GEOMETRY_OUTPUT_TYPE = 0x8918, + GEOMETRY_SHADER = 0x8DD9, + GEOMETRY_VERTICES_OUT = 0x8916, + INT_SAMPLER_2D_MULTISAMPLE = 0x9109, + INT_SAMPLER_2D_MULTISAMPLE_ARRAY = 0x910C, + LAST_VERTEX_CONVENTION = 0x8E4E, + LINES_ADJACENCY = 0x000A, + LINE_STRIP_ADJACENCY = 0x000B, + MAX_COLOR_TEXTURE_SAMPLES = 0x910E, + MAX_DEPTH_TEXTURE_SAMPLES = 0x910F, + MAX_FRAGMENT_INPUT_COMPONENTS = 0x9125, + MAX_GEOMETRY_INPUT_COMPONENTS = 0x9123, + MAX_GEOMETRY_OUTPUT_COMPONENTS = 0x9124, + MAX_GEOMETRY_OUTPUT_VERTICES = 0x8DE0, + MAX_GEOMETRY_TEXTURE_IMAGE_UNITS = 0x8C29, + MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS = 0x8DE1, + MAX_GEOMETRY_UNIFORM_COMPONENTS = 0x8DDF, + MAX_INTEGER_SAMPLES = 0x9110, + MAX_SAMPLE_MASK_WORDS = 0x8E59, + MAX_SERVER_WAIT_TIMEOUT = 0x9111, + MAX_VERTEX_OUTPUT_COMPONENTS = 0x9122, + OBJECT_TYPE = 0x9112, + PROGRAM_POINT_SIZE = 0x8642, + PROVOKING_VERTEX = 0x8E4F, + PROXY_TEXTURE_2D_MULTISAMPLE = 0x9101, + PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY = 0x9103, + QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION = 0x8E4C, + SAMPLER_2D_MULTISAMPLE = 0x9108, + SAMPLER_2D_MULTISAMPLE_ARRAY = 0x910B, + SAMPLE_MASK = 0x8E51, + SAMPLE_MASK_VALUE = 0x8E52, + SAMPLE_POSITION = 0x8E50, + SIGNALED = 0x9119, + SYNC_CONDITION = 0x9113, + SYNC_FENCE = 0x9116, + SYNC_FLAGS = 0x9115, + SYNC_FLUSH_COMMANDS_BIT = 0x00000001, + SYNC_GPU_COMMANDS_COMPLETE = 0x9117, + SYNC_STATUS = 0x9114, + TEXTURE_2D_MULTISAMPLE = 0x9100, + TEXTURE_2D_MULTISAMPLE_ARRAY = 0x9102, + TEXTURE_BINDING_2D_MULTISAMPLE = 0x9104, + TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY = 0x9105, + TEXTURE_CUBE_MAP_SEAMLESS = 0x884F, + TEXTURE_FIXED_SAMPLE_LOCATIONS = 0x9107, + TEXTURE_SAMPLES = 0x9106, + TIMEOUT_EXPIRED = 0x911B, + TIMEOUT_IGNORED = 0xFFFFFFFFFFFFFFFF, + TRIANGLES_ADJACENCY = 0x000C, + TRIANGLE_STRIP_ADJACENCY = 0x000D, + UNSIGNALED = 0x9118, + UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE = 0x910A, + UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY = 0x910D, + WAIT_FAILED_ = 0x911D, + + ANY_SAMPLES_PASSED = 0x8C2F, + INT_2_10_10_10_REV = 0x8D9F, + MAX_DUAL_SOURCE_DRAW_BUFFERS = 0x88FC, + ONE_MINUS_SRC1_ALPHA = 0x88FB, + ONE_MINUS_SRC1_COLOR = 0x88FA, + RGB10_A2UI = 0x906F, + SAMPLER_BINDING = 0x8919, + SRC1_COLOR = 0x88F9, + TEXTURE_SWIZZLE_A = 0x8E45, + TEXTURE_SWIZZLE_B = 0x8E44, + TEXTURE_SWIZZLE_G = 0x8E43, + TEXTURE_SWIZZLE_R = 0x8E42, + TEXTURE_SWIZZLE_RGBA = 0x8E46, + TIMESTAMP = 0x8E28, + TIME_ELAPSED = 0x88BF, + VERTEX_ATTRIB_ARRAY_DIVISOR = 0x88FE, + + }; + + namespace _detail + { + extern void (CODEGEN_FUNCPTR *BlendFunc)(GLenum sfactor, GLenum dfactor); + extern void (CODEGEN_FUNCPTR *Clear)(GLbitfield mask); + extern void (CODEGEN_FUNCPTR *ClearColor)(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); + extern void (CODEGEN_FUNCPTR *ClearDepth)(GLdouble depth); + extern void (CODEGEN_FUNCPTR *ClearStencil)(GLint s); + extern void (CODEGEN_FUNCPTR *ColorMask)(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha); + extern void (CODEGEN_FUNCPTR *CullFace)(GLenum mode); + extern void (CODEGEN_FUNCPTR *DepthFunc)(GLenum func); + extern void (CODEGEN_FUNCPTR *DepthMask)(GLboolean flag); + extern void (CODEGEN_FUNCPTR *DepthRange)(GLdouble ren_near, GLdouble ren_far); + extern void (CODEGEN_FUNCPTR *Disable)(GLenum cap); + extern void (CODEGEN_FUNCPTR *DrawBuffer)(GLenum buf); + extern void (CODEGEN_FUNCPTR *Enable)(GLenum cap); + extern void (CODEGEN_FUNCPTR *Finish)(void); + extern void (CODEGEN_FUNCPTR *Flush)(void); + extern void (CODEGEN_FUNCPTR *FrontFace)(GLenum mode); + extern void (CODEGEN_FUNCPTR *GetBooleanv)(GLenum pname, GLboolean * data); + extern void (CODEGEN_FUNCPTR *GetDoublev)(GLenum pname, GLdouble * data); + extern GLenum (CODEGEN_FUNCPTR *GetError)(void); + extern void (CODEGEN_FUNCPTR *GetFloatv)(GLenum pname, GLfloat * data); + extern void (CODEGEN_FUNCPTR *GetIntegerv)(GLenum pname, GLint * data); + extern const GLubyte * (CODEGEN_FUNCPTR *GetString)(GLenum name); + extern void (CODEGEN_FUNCPTR *GetTexImage)(GLenum target, GLint level, GLenum format, GLenum type, void * pixels); + extern void (CODEGEN_FUNCPTR *GetTexLevelParameterfv)(GLenum target, GLint level, GLenum pname, GLfloat * params); + extern void (CODEGEN_FUNCPTR *GetTexLevelParameteriv)(GLenum target, GLint level, GLenum pname, GLint * params); + extern void (CODEGEN_FUNCPTR *GetTexParameterfv)(GLenum target, GLenum pname, GLfloat * params); + extern void (CODEGEN_FUNCPTR *GetTexParameteriv)(GLenum target, GLenum pname, GLint * params); + extern void (CODEGEN_FUNCPTR *Hint)(GLenum target, GLenum mode); + extern GLboolean (CODEGEN_FUNCPTR *IsEnabled)(GLenum cap); + extern void (CODEGEN_FUNCPTR *LineWidth)(GLfloat width); + extern void (CODEGEN_FUNCPTR *LogicOp)(GLenum opcode); + extern void (CODEGEN_FUNCPTR *PixelStoref)(GLenum pname, GLfloat param); + extern void (CODEGEN_FUNCPTR *PixelStorei)(GLenum pname, GLint param); + extern void (CODEGEN_FUNCPTR *PointSize)(GLfloat size); + extern void (CODEGEN_FUNCPTR *PolygonMode)(GLenum face, GLenum mode); + extern void (CODEGEN_FUNCPTR *ReadBuffer)(GLenum src); + extern void (CODEGEN_FUNCPTR *ReadPixels)(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void * pixels); + extern void (CODEGEN_FUNCPTR *Scissor)(GLint x, GLint y, GLsizei width, GLsizei height); + extern void (CODEGEN_FUNCPTR *StencilFunc)(GLenum func, GLint ref, GLuint mask); + extern void (CODEGEN_FUNCPTR *StencilMask)(GLuint mask); + extern void (CODEGEN_FUNCPTR *StencilOp)(GLenum fail, GLenum zfail, GLenum zpass); + extern void (CODEGEN_FUNCPTR *TexImage1D)(GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const void * pixels); + extern void (CODEGEN_FUNCPTR *TexImage2D)(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void * pixels); + extern void (CODEGEN_FUNCPTR *TexParameterf)(GLenum target, GLenum pname, GLfloat param); + extern void (CODEGEN_FUNCPTR *TexParameterfv)(GLenum target, GLenum pname, const GLfloat * params); + extern void (CODEGEN_FUNCPTR *TexParameteri)(GLenum target, GLenum pname, GLint param); + extern void (CODEGEN_FUNCPTR *TexParameteriv)(GLenum target, GLenum pname, const GLint * params); + extern void (CODEGEN_FUNCPTR *Viewport)(GLint x, GLint y, GLsizei width, GLsizei height); + + extern void (CODEGEN_FUNCPTR *BindTexture)(GLenum target, GLuint texture); + extern void (CODEGEN_FUNCPTR *CopyTexImage1D)(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border); + extern void (CODEGEN_FUNCPTR *CopyTexImage2D)(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border); + extern void (CODEGEN_FUNCPTR *CopyTexSubImage1D)(GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width); + extern void (CODEGEN_FUNCPTR *CopyTexSubImage2D)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height); + extern void (CODEGEN_FUNCPTR *DeleteTextures)(GLsizei n, const GLuint * textures); + extern void (CODEGEN_FUNCPTR *DrawArrays)(GLenum mode, GLint first, GLsizei count); + extern void (CODEGEN_FUNCPTR *DrawElements)(GLenum mode, GLsizei count, GLenum type, const void * indices); + extern void (CODEGEN_FUNCPTR *GenTextures)(GLsizei n, GLuint * textures); + extern GLboolean (CODEGEN_FUNCPTR *IsTexture)(GLuint texture); + extern void (CODEGEN_FUNCPTR *PolygonOffset)(GLfloat factor, GLfloat units); + extern void (CODEGEN_FUNCPTR *TexSubImage1D)(GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const void * pixels); + extern void (CODEGEN_FUNCPTR *TexSubImage2D)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void * pixels); + + extern void (CODEGEN_FUNCPTR *CopyTexSubImage3D)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height); + extern void (CODEGEN_FUNCPTR *DrawRangeElements)(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void * indices); + extern void (CODEGEN_FUNCPTR *TexImage3D)(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void * pixels); + extern void (CODEGEN_FUNCPTR *TexSubImage3D)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void * pixels); + + extern void (CODEGEN_FUNCPTR *ActiveTexture)(GLenum texture); + extern void (CODEGEN_FUNCPTR *CompressedTexImage1D)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const void * data); + extern void (CODEGEN_FUNCPTR *CompressedTexImage2D)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void * data); + extern void (CODEGEN_FUNCPTR *CompressedTexImage3D)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void * data); + extern void (CODEGEN_FUNCPTR *CompressedTexSubImage1D)(GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const void * data); + extern void (CODEGEN_FUNCPTR *CompressedTexSubImage2D)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void * data); + extern void (CODEGEN_FUNCPTR *CompressedTexSubImage3D)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void * data); + extern void (CODEGEN_FUNCPTR *GetCompressedTexImage)(GLenum target, GLint level, void * img); + extern void (CODEGEN_FUNCPTR *SampleCoverage)(GLfloat value, GLboolean invert); + + extern void (CODEGEN_FUNCPTR *BlendColor)(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); + extern void (CODEGEN_FUNCPTR *BlendEquation)(GLenum mode); + extern void (CODEGEN_FUNCPTR *BlendFuncSeparate)(GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha); + extern void (CODEGEN_FUNCPTR *MultiDrawArrays)(GLenum mode, const GLint * first, const GLsizei * count, GLsizei drawcount); + extern void (CODEGEN_FUNCPTR *MultiDrawElements)(GLenum mode, const GLsizei * count, GLenum type, const void *const* indices, GLsizei drawcount); + extern void (CODEGEN_FUNCPTR *PointParameterf)(GLenum pname, GLfloat param); + extern void (CODEGEN_FUNCPTR *PointParameterfv)(GLenum pname, const GLfloat * params); + extern void (CODEGEN_FUNCPTR *PointParameteri)(GLenum pname, GLint param); + extern void (CODEGEN_FUNCPTR *PointParameteriv)(GLenum pname, const GLint * params); + + extern void (CODEGEN_FUNCPTR *BeginQuery)(GLenum target, GLuint id); + extern void (CODEGEN_FUNCPTR *BindBuffer)(GLenum target, GLuint buffer); + extern void (CODEGEN_FUNCPTR *BufferData)(GLenum target, GLsizeiptr size, const void * data, GLenum usage); + extern void (CODEGEN_FUNCPTR *BufferSubData)(GLenum target, GLintptr offset, GLsizeiptr size, const void * data); + extern void (CODEGEN_FUNCPTR *DeleteBuffers)(GLsizei n, const GLuint * buffers); + extern void (CODEGEN_FUNCPTR *DeleteQueries)(GLsizei n, const GLuint * ids); + extern void (CODEGEN_FUNCPTR *EndQuery)(GLenum target); + extern void (CODEGEN_FUNCPTR *GenBuffers)(GLsizei n, GLuint * buffers); + extern void (CODEGEN_FUNCPTR *GenQueries)(GLsizei n, GLuint * ids); + extern void (CODEGEN_FUNCPTR *GetBufferParameteriv)(GLenum target, GLenum pname, GLint * params); + extern void (CODEGEN_FUNCPTR *GetBufferPointerv)(GLenum target, GLenum pname, void ** params); + extern void (CODEGEN_FUNCPTR *GetBufferSubData)(GLenum target, GLintptr offset, GLsizeiptr size, void * data); + extern void (CODEGEN_FUNCPTR *GetQueryObjectiv)(GLuint id, GLenum pname, GLint * params); + extern void (CODEGEN_FUNCPTR *GetQueryObjectuiv)(GLuint id, GLenum pname, GLuint * params); + extern void (CODEGEN_FUNCPTR *GetQueryiv)(GLenum target, GLenum pname, GLint * params); + extern GLboolean (CODEGEN_FUNCPTR *IsBuffer)(GLuint buffer); + extern GLboolean (CODEGEN_FUNCPTR *IsQuery)(GLuint id); + extern void * (CODEGEN_FUNCPTR *MapBuffer)(GLenum target, GLenum access); + extern GLboolean (CODEGEN_FUNCPTR *UnmapBuffer)(GLenum target); + + extern void (CODEGEN_FUNCPTR *AttachShader)(GLuint program, GLuint shader); + extern void (CODEGEN_FUNCPTR *BindAttribLocation)(GLuint program, GLuint index, const GLchar * name); + extern void (CODEGEN_FUNCPTR *BlendEquationSeparate)(GLenum modeRGB, GLenum modeAlpha); + extern void (CODEGEN_FUNCPTR *CompileShader)(GLuint shader); + extern GLuint (CODEGEN_FUNCPTR *CreateProgram)(void); + extern GLuint (CODEGEN_FUNCPTR *CreateShader)(GLenum type); + extern void (CODEGEN_FUNCPTR *DeleteProgram)(GLuint program); + extern void (CODEGEN_FUNCPTR *DeleteShader)(GLuint shader); + extern void (CODEGEN_FUNCPTR *DetachShader)(GLuint program, GLuint shader); + extern void (CODEGEN_FUNCPTR *DisableVertexAttribArray)(GLuint index); + extern void (CODEGEN_FUNCPTR *DrawBuffers)(GLsizei n, const GLenum * bufs); + extern void (CODEGEN_FUNCPTR *EnableVertexAttribArray)(GLuint index); + extern void (CODEGEN_FUNCPTR *GetActiveAttrib)(GLuint program, GLuint index, GLsizei bufSize, GLsizei * length, GLint * size, GLenum * type, GLchar * name); + extern void (CODEGEN_FUNCPTR *GetActiveUniform)(GLuint program, GLuint index, GLsizei bufSize, GLsizei * length, GLint * size, GLenum * type, GLchar * name); + extern void (CODEGEN_FUNCPTR *GetAttachedShaders)(GLuint program, GLsizei maxCount, GLsizei * count, GLuint * shaders); + extern GLint (CODEGEN_FUNCPTR *GetAttribLocation)(GLuint program, const GLchar * name); + extern void (CODEGEN_FUNCPTR *GetProgramInfoLog)(GLuint program, GLsizei bufSize, GLsizei * length, GLchar * infoLog); + extern void (CODEGEN_FUNCPTR *GetProgramiv)(GLuint program, GLenum pname, GLint * params); + extern void (CODEGEN_FUNCPTR *GetShaderInfoLog)(GLuint shader, GLsizei bufSize, GLsizei * length, GLchar * infoLog); + extern void (CODEGEN_FUNCPTR *GetShaderSource)(GLuint shader, GLsizei bufSize, GLsizei * length, GLchar * source); + extern void (CODEGEN_FUNCPTR *GetShaderiv)(GLuint shader, GLenum pname, GLint * params); + extern GLint (CODEGEN_FUNCPTR *GetUniformLocation)(GLuint program, const GLchar * name); + extern void (CODEGEN_FUNCPTR *GetUniformfv)(GLuint program, GLint location, GLfloat * params); + extern void (CODEGEN_FUNCPTR *GetUniformiv)(GLuint program, GLint location, GLint * params); + extern void (CODEGEN_FUNCPTR *GetVertexAttribPointerv)(GLuint index, GLenum pname, void ** pointer); + extern void (CODEGEN_FUNCPTR *GetVertexAttribdv)(GLuint index, GLenum pname, GLdouble * params); + extern void (CODEGEN_FUNCPTR *GetVertexAttribfv)(GLuint index, GLenum pname, GLfloat * params); + extern void (CODEGEN_FUNCPTR *GetVertexAttribiv)(GLuint index, GLenum pname, GLint * params); + extern GLboolean (CODEGEN_FUNCPTR *IsProgram)(GLuint program); + extern GLboolean (CODEGEN_FUNCPTR *IsShader)(GLuint shader); + extern void (CODEGEN_FUNCPTR *LinkProgram)(GLuint program); + extern void (CODEGEN_FUNCPTR *ShaderSource)(GLuint shader, GLsizei count, const GLchar *const* string, const GLint * length); + extern void (CODEGEN_FUNCPTR *StencilFuncSeparate)(GLenum face, GLenum func, GLint ref, GLuint mask); + extern void (CODEGEN_FUNCPTR *StencilMaskSeparate)(GLenum face, GLuint mask); + extern void (CODEGEN_FUNCPTR *StencilOpSeparate)(GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass); + extern void (CODEGEN_FUNCPTR *Uniform1f)(GLint location, GLfloat v0); + extern void (CODEGEN_FUNCPTR *Uniform1fv)(GLint location, GLsizei count, const GLfloat * value); + extern void (CODEGEN_FUNCPTR *Uniform1i)(GLint location, GLint v0); + extern void (CODEGEN_FUNCPTR *Uniform1iv)(GLint location, GLsizei count, const GLint * value); + extern void (CODEGEN_FUNCPTR *Uniform2f)(GLint location, GLfloat v0, GLfloat v1); + extern void (CODEGEN_FUNCPTR *Uniform2fv)(GLint location, GLsizei count, const GLfloat * value); + extern void (CODEGEN_FUNCPTR *Uniform2i)(GLint location, GLint v0, GLint v1); + extern void (CODEGEN_FUNCPTR *Uniform2iv)(GLint location, GLsizei count, const GLint * value); + extern void (CODEGEN_FUNCPTR *Uniform3f)(GLint location, GLfloat v0, GLfloat v1, GLfloat v2); + extern void (CODEGEN_FUNCPTR *Uniform3fv)(GLint location, GLsizei count, const GLfloat * value); + extern void (CODEGEN_FUNCPTR *Uniform3i)(GLint location, GLint v0, GLint v1, GLint v2); + extern void (CODEGEN_FUNCPTR *Uniform3iv)(GLint location, GLsizei count, const GLint * value); + extern void (CODEGEN_FUNCPTR *Uniform4f)(GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3); + extern void (CODEGEN_FUNCPTR *Uniform4fv)(GLint location, GLsizei count, const GLfloat * value); + extern void (CODEGEN_FUNCPTR *Uniform4i)(GLint location, GLint v0, GLint v1, GLint v2, GLint v3); + extern void (CODEGEN_FUNCPTR *Uniform4iv)(GLint location, GLsizei count, const GLint * value); + extern void (CODEGEN_FUNCPTR *UniformMatrix2fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); + extern void (CODEGEN_FUNCPTR *UniformMatrix3fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); + extern void (CODEGEN_FUNCPTR *UniformMatrix4fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); + extern void (CODEGEN_FUNCPTR *UseProgram)(GLuint program); + extern void (CODEGEN_FUNCPTR *ValidateProgram)(GLuint program); + extern void (CODEGEN_FUNCPTR *VertexAttrib1d)(GLuint index, GLdouble x); + extern void (CODEGEN_FUNCPTR *VertexAttrib1dv)(GLuint index, const GLdouble * v); + extern void (CODEGEN_FUNCPTR *VertexAttrib1f)(GLuint index, GLfloat x); + extern void (CODEGEN_FUNCPTR *VertexAttrib1fv)(GLuint index, const GLfloat * v); + extern void (CODEGEN_FUNCPTR *VertexAttrib1s)(GLuint index, GLshort x); + extern void (CODEGEN_FUNCPTR *VertexAttrib1sv)(GLuint index, const GLshort * v); + extern void (CODEGEN_FUNCPTR *VertexAttrib2d)(GLuint index, GLdouble x, GLdouble y); + extern void (CODEGEN_FUNCPTR *VertexAttrib2dv)(GLuint index, const GLdouble * v); + extern void (CODEGEN_FUNCPTR *VertexAttrib2f)(GLuint index, GLfloat x, GLfloat y); + extern void (CODEGEN_FUNCPTR *VertexAttrib2fv)(GLuint index, const GLfloat * v); + extern void (CODEGEN_FUNCPTR *VertexAttrib2s)(GLuint index, GLshort x, GLshort y); + extern void (CODEGEN_FUNCPTR *VertexAttrib2sv)(GLuint index, const GLshort * v); + extern void (CODEGEN_FUNCPTR *VertexAttrib3d)(GLuint index, GLdouble x, GLdouble y, GLdouble z); + extern void (CODEGEN_FUNCPTR *VertexAttrib3dv)(GLuint index, const GLdouble * v); + extern void (CODEGEN_FUNCPTR *VertexAttrib3f)(GLuint index, GLfloat x, GLfloat y, GLfloat z); + extern void (CODEGEN_FUNCPTR *VertexAttrib3fv)(GLuint index, const GLfloat * v); + extern void (CODEGEN_FUNCPTR *VertexAttrib3s)(GLuint index, GLshort x, GLshort y, GLshort z); + extern void (CODEGEN_FUNCPTR *VertexAttrib3sv)(GLuint index, const GLshort * v); + extern void (CODEGEN_FUNCPTR *VertexAttrib4Nbv)(GLuint index, const GLbyte * v); + extern void (CODEGEN_FUNCPTR *VertexAttrib4Niv)(GLuint index, const GLint * v); + extern void (CODEGEN_FUNCPTR *VertexAttrib4Nsv)(GLuint index, const GLshort * v); + extern void (CODEGEN_FUNCPTR *VertexAttrib4Nub)(GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w); + extern void (CODEGEN_FUNCPTR *VertexAttrib4Nubv)(GLuint index, const GLubyte * v); + extern void (CODEGEN_FUNCPTR *VertexAttrib4Nuiv)(GLuint index, const GLuint * v); + extern void (CODEGEN_FUNCPTR *VertexAttrib4Nusv)(GLuint index, const GLushort * v); + extern void (CODEGEN_FUNCPTR *VertexAttrib4bv)(GLuint index, const GLbyte * v); + extern void (CODEGEN_FUNCPTR *VertexAttrib4d)(GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w); + extern void (CODEGEN_FUNCPTR *VertexAttrib4dv)(GLuint index, const GLdouble * v); + extern void (CODEGEN_FUNCPTR *VertexAttrib4f)(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); + extern void (CODEGEN_FUNCPTR *VertexAttrib4fv)(GLuint index, const GLfloat * v); + extern void (CODEGEN_FUNCPTR *VertexAttrib4iv)(GLuint index, const GLint * v); + extern void (CODEGEN_FUNCPTR *VertexAttrib4s)(GLuint index, GLshort x, GLshort y, GLshort z, GLshort w); + extern void (CODEGEN_FUNCPTR *VertexAttrib4sv)(GLuint index, const GLshort * v); + extern void (CODEGEN_FUNCPTR *VertexAttrib4ubv)(GLuint index, const GLubyte * v); + extern void (CODEGEN_FUNCPTR *VertexAttrib4uiv)(GLuint index, const GLuint * v); + extern void (CODEGEN_FUNCPTR *VertexAttrib4usv)(GLuint index, const GLushort * v); + extern void (CODEGEN_FUNCPTR *VertexAttribPointer)(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void * pointer); + + extern void (CODEGEN_FUNCPTR *UniformMatrix2x3fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); + extern void (CODEGEN_FUNCPTR *UniformMatrix2x4fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); + extern void (CODEGEN_FUNCPTR *UniformMatrix3x2fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); + extern void (CODEGEN_FUNCPTR *UniformMatrix3x4fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); + extern void (CODEGEN_FUNCPTR *UniformMatrix4x2fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); + extern void (CODEGEN_FUNCPTR *UniformMatrix4x3fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); + + extern void (CODEGEN_FUNCPTR *BeginConditionalRender)(GLuint id, GLenum mode); + extern void (CODEGEN_FUNCPTR *BeginTransformFeedback)(GLenum primitiveMode); + extern void (CODEGEN_FUNCPTR *BindBufferBase)(GLenum target, GLuint index, GLuint buffer); + extern void (CODEGEN_FUNCPTR *BindBufferRange)(GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size); + extern void (CODEGEN_FUNCPTR *BindFragDataLocation)(GLuint program, GLuint color, const GLchar * name); + extern void (CODEGEN_FUNCPTR *BindFramebuffer)(GLenum target, GLuint framebuffer); + extern void (CODEGEN_FUNCPTR *BindRenderbuffer)(GLenum target, GLuint renderbuffer); + extern void (CODEGEN_FUNCPTR *BindVertexArray)(GLuint ren_array); + extern void (CODEGEN_FUNCPTR *BlitFramebuffer)(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); + extern GLenum (CODEGEN_FUNCPTR *CheckFramebufferStatus)(GLenum target); + extern void (CODEGEN_FUNCPTR *ClampColor)(GLenum target, GLenum clamp); + extern void (CODEGEN_FUNCPTR *ClearBufferfi)(GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil); + extern void (CODEGEN_FUNCPTR *ClearBufferfv)(GLenum buffer, GLint drawbuffer, const GLfloat * value); + extern void (CODEGEN_FUNCPTR *ClearBufferiv)(GLenum buffer, GLint drawbuffer, const GLint * value); + extern void (CODEGEN_FUNCPTR *ClearBufferuiv)(GLenum buffer, GLint drawbuffer, const GLuint * value); + extern void (CODEGEN_FUNCPTR *ColorMaski)(GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a); + extern void (CODEGEN_FUNCPTR *DeleteFramebuffers)(GLsizei n, const GLuint * framebuffers); + extern void (CODEGEN_FUNCPTR *DeleteRenderbuffers)(GLsizei n, const GLuint * renderbuffers); + extern void (CODEGEN_FUNCPTR *DeleteVertexArrays)(GLsizei n, const GLuint * arrays); + extern void (CODEGEN_FUNCPTR *Disablei)(GLenum target, GLuint index); + extern void (CODEGEN_FUNCPTR *Enablei)(GLenum target, GLuint index); + extern void (CODEGEN_FUNCPTR *EndConditionalRender)(void); + extern void (CODEGEN_FUNCPTR *EndTransformFeedback)(void); + extern void (CODEGEN_FUNCPTR *FlushMappedBufferRange)(GLenum target, GLintptr offset, GLsizeiptr length); + extern void (CODEGEN_FUNCPTR *FramebufferRenderbuffer)(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer); + extern void (CODEGEN_FUNCPTR *FramebufferTexture1D)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); + extern void (CODEGEN_FUNCPTR *FramebufferTexture2D)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); + extern void (CODEGEN_FUNCPTR *FramebufferTexture3D)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset); + extern void (CODEGEN_FUNCPTR *FramebufferTextureLayer)(GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer); + extern void (CODEGEN_FUNCPTR *GenFramebuffers)(GLsizei n, GLuint * framebuffers); + extern void (CODEGEN_FUNCPTR *GenRenderbuffers)(GLsizei n, GLuint * renderbuffers); + extern void (CODEGEN_FUNCPTR *GenVertexArrays)(GLsizei n, GLuint * arrays); + extern void (CODEGEN_FUNCPTR *GenerateMipmap)(GLenum target); + extern void (CODEGEN_FUNCPTR *GetBooleani_v)(GLenum target, GLuint index, GLboolean * data); + extern GLint (CODEGEN_FUNCPTR *GetFragDataLocation)(GLuint program, const GLchar * name); + extern void (CODEGEN_FUNCPTR *GetFramebufferAttachmentParameteriv)(GLenum target, GLenum attachment, GLenum pname, GLint * params); + extern void (CODEGEN_FUNCPTR *GetIntegeri_v)(GLenum target, GLuint index, GLint * data); + extern void (CODEGEN_FUNCPTR *GetRenderbufferParameteriv)(GLenum target, GLenum pname, GLint * params); + extern const GLubyte * (CODEGEN_FUNCPTR *GetStringi)(GLenum name, GLuint index); + extern void (CODEGEN_FUNCPTR *GetTexParameterIiv)(GLenum target, GLenum pname, GLint * params); + extern void (CODEGEN_FUNCPTR *GetTexParameterIuiv)(GLenum target, GLenum pname, GLuint * params); + extern void (CODEGEN_FUNCPTR *GetTransformFeedbackVarying)(GLuint program, GLuint index, GLsizei bufSize, GLsizei * length, GLsizei * size, GLenum * type, GLchar * name); + extern void (CODEGEN_FUNCPTR *GetUniformuiv)(GLuint program, GLint location, GLuint * params); + extern void (CODEGEN_FUNCPTR *GetVertexAttribIiv)(GLuint index, GLenum pname, GLint * params); + extern void (CODEGEN_FUNCPTR *GetVertexAttribIuiv)(GLuint index, GLenum pname, GLuint * params); + extern GLboolean (CODEGEN_FUNCPTR *IsEnabledi)(GLenum target, GLuint index); + extern GLboolean (CODEGEN_FUNCPTR *IsFramebuffer)(GLuint framebuffer); + extern GLboolean (CODEGEN_FUNCPTR *IsRenderbuffer)(GLuint renderbuffer); + extern GLboolean (CODEGEN_FUNCPTR *IsVertexArray)(GLuint ren_array); + extern void * (CODEGEN_FUNCPTR *MapBufferRange)(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access); + extern void (CODEGEN_FUNCPTR *RenderbufferStorage)(GLenum target, GLenum internalformat, GLsizei width, GLsizei height); + extern void (CODEGEN_FUNCPTR *RenderbufferStorageMultisample)(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); + extern void (CODEGEN_FUNCPTR *TexParameterIiv)(GLenum target, GLenum pname, const GLint * params); + extern void (CODEGEN_FUNCPTR *TexParameterIuiv)(GLenum target, GLenum pname, const GLuint * params); + extern void (CODEGEN_FUNCPTR *TransformFeedbackVaryings)(GLuint program, GLsizei count, const GLchar *const* varyings, GLenum bufferMode); + extern void (CODEGEN_FUNCPTR *Uniform1ui)(GLint location, GLuint v0); + extern void (CODEGEN_FUNCPTR *Uniform1uiv)(GLint location, GLsizei count, const GLuint * value); + extern void (CODEGEN_FUNCPTR *Uniform2ui)(GLint location, GLuint v0, GLuint v1); + extern void (CODEGEN_FUNCPTR *Uniform2uiv)(GLint location, GLsizei count, const GLuint * value); + extern void (CODEGEN_FUNCPTR *Uniform3ui)(GLint location, GLuint v0, GLuint v1, GLuint v2); + extern void (CODEGEN_FUNCPTR *Uniform3uiv)(GLint location, GLsizei count, const GLuint * value); + extern void (CODEGEN_FUNCPTR *Uniform4ui)(GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3); + extern void (CODEGEN_FUNCPTR *Uniform4uiv)(GLint location, GLsizei count, const GLuint * value); + extern void (CODEGEN_FUNCPTR *VertexAttribI1i)(GLuint index, GLint x); + extern void (CODEGEN_FUNCPTR *VertexAttribI1iv)(GLuint index, const GLint * v); + extern void (CODEGEN_FUNCPTR *VertexAttribI1ui)(GLuint index, GLuint x); + extern void (CODEGEN_FUNCPTR *VertexAttribI1uiv)(GLuint index, const GLuint * v); + extern void (CODEGEN_FUNCPTR *VertexAttribI2i)(GLuint index, GLint x, GLint y); + extern void (CODEGEN_FUNCPTR *VertexAttribI2iv)(GLuint index, const GLint * v); + extern void (CODEGEN_FUNCPTR *VertexAttribI2ui)(GLuint index, GLuint x, GLuint y); + extern void (CODEGEN_FUNCPTR *VertexAttribI2uiv)(GLuint index, const GLuint * v); + extern void (CODEGEN_FUNCPTR *VertexAttribI3i)(GLuint index, GLint x, GLint y, GLint z); + extern void (CODEGEN_FUNCPTR *VertexAttribI3iv)(GLuint index, const GLint * v); + extern void (CODEGEN_FUNCPTR *VertexAttribI3ui)(GLuint index, GLuint x, GLuint y, GLuint z); + extern void (CODEGEN_FUNCPTR *VertexAttribI3uiv)(GLuint index, const GLuint * v); + extern void (CODEGEN_FUNCPTR *VertexAttribI4bv)(GLuint index, const GLbyte * v); + extern void (CODEGEN_FUNCPTR *VertexAttribI4i)(GLuint index, GLint x, GLint y, GLint z, GLint w); + extern void (CODEGEN_FUNCPTR *VertexAttribI4iv)(GLuint index, const GLint * v); + extern void (CODEGEN_FUNCPTR *VertexAttribI4sv)(GLuint index, const GLshort * v); + extern void (CODEGEN_FUNCPTR *VertexAttribI4ubv)(GLuint index, const GLubyte * v); + extern void (CODEGEN_FUNCPTR *VertexAttribI4ui)(GLuint index, GLuint x, GLuint y, GLuint z, GLuint w); + extern void (CODEGEN_FUNCPTR *VertexAttribI4uiv)(GLuint index, const GLuint * v); + extern void (CODEGEN_FUNCPTR *VertexAttribI4usv)(GLuint index, const GLushort * v); + extern void (CODEGEN_FUNCPTR *VertexAttribIPointer)(GLuint index, GLint size, GLenum type, GLsizei stride, const void * pointer); + + extern void (CODEGEN_FUNCPTR *CopyBufferSubData)(GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size); + extern void (CODEGEN_FUNCPTR *DrawArraysInstanced)(GLenum mode, GLint first, GLsizei count, GLsizei instancecount); + extern void (CODEGEN_FUNCPTR *DrawElementsInstanced)(GLenum mode, GLsizei count, GLenum type, const void * indices, GLsizei instancecount); + extern void (CODEGEN_FUNCPTR *GetActiveUniformBlockName)(GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei * length, GLchar * uniformBlockName); + extern void (CODEGEN_FUNCPTR *GetActiveUniformBlockiv)(GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint * params); + extern void (CODEGEN_FUNCPTR *GetActiveUniformName)(GLuint program, GLuint uniformIndex, GLsizei bufSize, GLsizei * length, GLchar * uniformName); + extern void (CODEGEN_FUNCPTR *GetActiveUniformsiv)(GLuint program, GLsizei uniformCount, const GLuint * uniformIndices, GLenum pname, GLint * params); + extern GLuint (CODEGEN_FUNCPTR *GetUniformBlockIndex)(GLuint program, const GLchar * uniformBlockName); + extern void (CODEGEN_FUNCPTR *GetUniformIndices)(GLuint program, GLsizei uniformCount, const GLchar *const* uniformNames, GLuint * uniformIndices); + extern void (CODEGEN_FUNCPTR *PrimitiveRestartIndex)(GLuint index); + extern void (CODEGEN_FUNCPTR *TexBuffer)(GLenum target, GLenum internalformat, GLuint buffer); + extern void (CODEGEN_FUNCPTR *UniformBlockBinding)(GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding); + + extern GLenum (CODEGEN_FUNCPTR *ClientWaitSync)(GLsync sync, GLbitfield flags, GLuint64 timeout); + extern void (CODEGEN_FUNCPTR *DeleteSync)(GLsync sync); + extern void (CODEGEN_FUNCPTR *DrawElementsBaseVertex)(GLenum mode, GLsizei count, GLenum type, const void * indices, GLint basevertex); + extern void (CODEGEN_FUNCPTR *DrawElementsInstancedBaseVertex)(GLenum mode, GLsizei count, GLenum type, const void * indices, GLsizei instancecount, GLint basevertex); + extern void (CODEGEN_FUNCPTR *DrawRangeElementsBaseVertex)(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void * indices, GLint basevertex); + extern GLsync (CODEGEN_FUNCPTR *FenceSync)(GLenum condition, GLbitfield flags); + extern void (CODEGEN_FUNCPTR *FramebufferTexture)(GLenum target, GLenum attachment, GLuint texture, GLint level); + extern void (CODEGEN_FUNCPTR *GetBufferParameteri64v)(GLenum target, GLenum pname, GLint64 * params); + extern void (CODEGEN_FUNCPTR *GetInteger64i_v)(GLenum target, GLuint index, GLint64 * data); + extern void (CODEGEN_FUNCPTR *GetInteger64v)(GLenum pname, GLint64 * data); + extern void (CODEGEN_FUNCPTR *GetMultisamplefv)(GLenum pname, GLuint index, GLfloat * val); + extern void (CODEGEN_FUNCPTR *GetSynciv)(GLsync sync, GLenum pname, GLsizei bufSize, GLsizei * length, GLint * values); + extern GLboolean (CODEGEN_FUNCPTR *IsSync)(GLsync sync); + extern void (CODEGEN_FUNCPTR *MultiDrawElementsBaseVertex)(GLenum mode, const GLsizei * count, GLenum type, const void *const* indices, GLsizei drawcount, const GLint * basevertex); + extern void (CODEGEN_FUNCPTR *ProvokingVertex)(GLenum mode); + extern void (CODEGEN_FUNCPTR *SampleMaski)(GLuint maskNumber, GLbitfield mask); + extern void (CODEGEN_FUNCPTR *TexImage2DMultisample)(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations); + extern void (CODEGEN_FUNCPTR *TexImage3DMultisample)(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations); + extern void (CODEGEN_FUNCPTR *WaitSync)(GLsync sync, GLbitfield flags, GLuint64 timeout); + + extern void (CODEGEN_FUNCPTR *BindFragDataLocationIndexed)(GLuint program, GLuint colorNumber, GLuint index, const GLchar * name); + extern void (CODEGEN_FUNCPTR *BindSampler)(GLuint unit, GLuint sampler); + extern void (CODEGEN_FUNCPTR *DeleteSamplers)(GLsizei count, const GLuint * samplers); + extern void (CODEGEN_FUNCPTR *GenSamplers)(GLsizei count, GLuint * samplers); + extern GLint (CODEGEN_FUNCPTR *GetFragDataIndex)(GLuint program, const GLchar * name); + extern void (CODEGEN_FUNCPTR *GetQueryObjecti64v)(GLuint id, GLenum pname, GLint64 * params); + extern void (CODEGEN_FUNCPTR *GetQueryObjectui64v)(GLuint id, GLenum pname, GLuint64 * params); + extern void (CODEGEN_FUNCPTR *GetSamplerParameterIiv)(GLuint sampler, GLenum pname, GLint * params); + extern void (CODEGEN_FUNCPTR *GetSamplerParameterIuiv)(GLuint sampler, GLenum pname, GLuint * params); + extern void (CODEGEN_FUNCPTR *GetSamplerParameterfv)(GLuint sampler, GLenum pname, GLfloat * params); + extern void (CODEGEN_FUNCPTR *GetSamplerParameteriv)(GLuint sampler, GLenum pname, GLint * params); + extern GLboolean (CODEGEN_FUNCPTR *IsSampler)(GLuint sampler); + extern void (CODEGEN_FUNCPTR *QueryCounter)(GLuint id, GLenum target); + extern void (CODEGEN_FUNCPTR *SamplerParameterIiv)(GLuint sampler, GLenum pname, const GLint * param); + extern void (CODEGEN_FUNCPTR *SamplerParameterIuiv)(GLuint sampler, GLenum pname, const GLuint * param); + extern void (CODEGEN_FUNCPTR *SamplerParameterf)(GLuint sampler, GLenum pname, GLfloat param); + extern void (CODEGEN_FUNCPTR *SamplerParameterfv)(GLuint sampler, GLenum pname, const GLfloat * param); + extern void (CODEGEN_FUNCPTR *SamplerParameteri)(GLuint sampler, GLenum pname, GLint param); + extern void (CODEGEN_FUNCPTR *SamplerParameteriv)(GLuint sampler, GLenum pname, const GLint * param); + extern void (CODEGEN_FUNCPTR *VertexAttribDivisor)(GLuint index, GLuint divisor); + extern void (CODEGEN_FUNCPTR *VertexAttribP1ui)(GLuint index, GLenum type, GLboolean normalized, GLuint value); + extern void (CODEGEN_FUNCPTR *VertexAttribP1uiv)(GLuint index, GLenum type, GLboolean normalized, const GLuint * value); + extern void (CODEGEN_FUNCPTR *VertexAttribP2ui)(GLuint index, GLenum type, GLboolean normalized, GLuint value); + extern void (CODEGEN_FUNCPTR *VertexAttribP2uiv)(GLuint index, GLenum type, GLboolean normalized, const GLuint * value); + extern void (CODEGEN_FUNCPTR *VertexAttribP3ui)(GLuint index, GLenum type, GLboolean normalized, GLuint value); + extern void (CODEGEN_FUNCPTR *VertexAttribP3uiv)(GLuint index, GLenum type, GLboolean normalized, const GLuint * value); + extern void (CODEGEN_FUNCPTR *VertexAttribP4ui)(GLuint index, GLenum type, GLboolean normalized, GLuint value); + extern void (CODEGEN_FUNCPTR *VertexAttribP4uiv)(GLuint index, GLenum type, GLboolean normalized, const GLuint * value); + + } //namespace _detail + + inline void BlendFunc(GLenum sfactor, GLenum dfactor){_detail::BlendFunc(sfactor, dfactor);} + inline void Clear(GLbitfield mask){_detail::Clear(mask);} + inline void ClearColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha){_detail::ClearColor(red, green, blue, alpha);} + inline void ClearDepth(GLdouble depth){_detail::ClearDepth(depth);} + inline void ClearStencil(GLint s){_detail::ClearStencil(s);} + inline void ColorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha){_detail::ColorMask(red, green, blue, alpha);} + inline void CullFace(GLenum mode){_detail::CullFace(mode);} + inline void DepthFunc(GLenum func){_detail::DepthFunc(func);} + inline void DepthMask(GLboolean flag){_detail::DepthMask(flag);} + inline void DepthRange(GLdouble ren_near, GLdouble ren_far){_detail::DepthRange(ren_near, ren_far);} + inline void Disable(GLenum cap){_detail::Disable(cap);} + inline void DrawBuffer(GLenum buf){_detail::DrawBuffer(buf);} + inline void Enable(GLenum cap){_detail::Enable(cap);} + inline void Finish(void){_detail::Finish();} + inline void Flush(void){_detail::Flush();} + inline void FrontFace(GLenum mode){_detail::FrontFace(mode);} + inline void GetBooleanv(GLenum pname, GLboolean * data){_detail::GetBooleanv(pname, data);} + inline void GetDoublev(GLenum pname, GLdouble * data){_detail::GetDoublev(pname, data);} + inline GLenum GetError(void){return _detail::GetError();} + inline void GetFloatv(GLenum pname, GLfloat * data){_detail::GetFloatv(pname, data);} + inline void GetIntegerv(GLenum pname, GLint * data){_detail::GetIntegerv(pname, data);} + inline const GLubyte * GetString(GLenum name){return _detail::GetString(name);} + inline void GetTexImage(GLenum target, GLint level, GLenum format, GLenum type, void * pixels){_detail::GetTexImage(target, level, format, type, pixels);} + inline void GetTexLevelParameterfv(GLenum target, GLint level, GLenum pname, GLfloat * params){_detail::GetTexLevelParameterfv(target, level, pname, params);} + inline void GetTexLevelParameteriv(GLenum target, GLint level, GLenum pname, GLint * params){_detail::GetTexLevelParameteriv(target, level, pname, params);} + inline void GetTexParameterfv(GLenum target, GLenum pname, GLfloat * params){_detail::GetTexParameterfv(target, pname, params);} + inline void GetTexParameteriv(GLenum target, GLenum pname, GLint * params){_detail::GetTexParameteriv(target, pname, params);} + inline void Hint(GLenum target, GLenum mode){_detail::Hint(target, mode);} + inline GLboolean IsEnabled(GLenum cap){return _detail::IsEnabled(cap);} + inline void LineWidth(GLfloat width){_detail::LineWidth(width);} + inline void LogicOp(GLenum opcode){_detail::LogicOp(opcode);} + inline void PixelStoref(GLenum pname, GLfloat param){_detail::PixelStoref(pname, param);} + inline void PixelStorei(GLenum pname, GLint param){_detail::PixelStorei(pname, param);} + inline void PointSize(GLfloat size){_detail::PointSize(size);} + inline void PolygonMode(GLenum face, GLenum mode){_detail::PolygonMode(face, mode);} + inline void ReadBuffer(GLenum src){_detail::ReadBuffer(src);} + inline void ReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void * pixels){_detail::ReadPixels(x, y, width, height, format, type, pixels);} + inline void Scissor(GLint x, GLint y, GLsizei width, GLsizei height){_detail::Scissor(x, y, width, height);} + inline void StencilFunc(GLenum func, GLint ref, GLuint mask){_detail::StencilFunc(func, ref, mask);} + inline void StencilMask(GLuint mask){_detail::StencilMask(mask);} + inline void StencilOp(GLenum fail, GLenum zfail, GLenum zpass){_detail::StencilOp(fail, zfail, zpass);} + inline void TexImage1D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const void * pixels){_detail::TexImage1D(target, level, internalformat, width, border, format, type, pixels);} + inline void TexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void * pixels){_detail::TexImage2D(target, level, internalformat, width, height, border, format, type, pixels);} + inline void TexParameterf(GLenum target, GLenum pname, GLfloat param){_detail::TexParameterf(target, pname, param);} + inline void TexParameterfv(GLenum target, GLenum pname, const GLfloat * params){_detail::TexParameterfv(target, pname, params);} + inline void TexParameteri(GLenum target, GLenum pname, GLint param){_detail::TexParameteri(target, pname, param);} + inline void TexParameteriv(GLenum target, GLenum pname, const GLint * params){_detail::TexParameteriv(target, pname, params);} + inline void Viewport(GLint x, GLint y, GLsizei width, GLsizei height){_detail::Viewport(x, y, width, height);} + + inline void BindTexture(GLenum target, GLuint texture){_detail::BindTexture(target, texture);} + inline void CopyTexImage1D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border){_detail::CopyTexImage1D(target, level, internalformat, x, y, width, border);} + inline void CopyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border){_detail::CopyTexImage2D(target, level, internalformat, x, y, width, height, border);} + inline void CopyTexSubImage1D(GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width){_detail::CopyTexSubImage1D(target, level, xoffset, x, y, width);} + inline void CopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height){_detail::CopyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height);} + inline void DeleteTextures(GLsizei n, const GLuint * textures){_detail::DeleteTextures(n, textures);} + inline void DrawArrays(GLenum mode, GLint first, GLsizei count){_detail::DrawArrays(mode, first, count);} + inline void DrawElements(GLenum mode, GLsizei count, GLenum type, const void * indices){_detail::DrawElements(mode, count, type, indices);} + inline void GenTextures(GLsizei n, GLuint * textures){_detail::GenTextures(n, textures);} + inline GLboolean IsTexture(GLuint texture){return _detail::IsTexture(texture);} + inline void PolygonOffset(GLfloat factor, GLfloat units){_detail::PolygonOffset(factor, units);} + inline void TexSubImage1D(GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const void * pixels){_detail::TexSubImage1D(target, level, xoffset, width, format, type, pixels);} + inline void TexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void * pixels){_detail::TexSubImage2D(target, level, xoffset, yoffset, width, height, format, type, pixels);} + + inline void CopyTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height){_detail::CopyTexSubImage3D(target, level, xoffset, yoffset, zoffset, x, y, width, height);} + inline void DrawRangeElements(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void * indices){_detail::DrawRangeElements(mode, start, end, count, type, indices);} + inline void TexImage3D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void * pixels){_detail::TexImage3D(target, level, internalformat, width, height, depth, border, format, type, pixels);} + inline void TexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void * pixels){_detail::TexSubImage3D(target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, pixels);} + + inline void ActiveTexture(GLenum texture){_detail::ActiveTexture(texture);} + inline void CompressedTexImage1D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const void * data){_detail::CompressedTexImage1D(target, level, internalformat, width, border, imageSize, data);} + inline void CompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void * data){_detail::CompressedTexImage2D(target, level, internalformat, width, height, border, imageSize, data);} + inline void CompressedTexImage3D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void * data){_detail::CompressedTexImage3D(target, level, internalformat, width, height, depth, border, imageSize, data);} + inline void CompressedTexSubImage1D(GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const void * data){_detail::CompressedTexSubImage1D(target, level, xoffset, width, format, imageSize, data);} + inline void CompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void * data){_detail::CompressedTexSubImage2D(target, level, xoffset, yoffset, width, height, format, imageSize, data);} + inline void CompressedTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void * data){_detail::CompressedTexSubImage3D(target, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, data);} + inline void GetCompressedTexImage(GLenum target, GLint level, void * img){_detail::GetCompressedTexImage(target, level, img);} + inline void SampleCoverage(GLfloat value, GLboolean invert){_detail::SampleCoverage(value, invert);} + + inline void BlendColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha){_detail::BlendColor(red, green, blue, alpha);} + inline void BlendEquation(GLenum mode){_detail::BlendEquation(mode);} + inline void BlendFuncSeparate(GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha){_detail::BlendFuncSeparate(sfactorRGB, dfactorRGB, sfactorAlpha, dfactorAlpha);} + inline void MultiDrawArrays(GLenum mode, const GLint * first, const GLsizei * count, GLsizei drawcount){_detail::MultiDrawArrays(mode, first, count, drawcount);} + inline void MultiDrawElements(GLenum mode, const GLsizei * count, GLenum type, const void *const* indices, GLsizei drawcount){_detail::MultiDrawElements(mode, count, type, indices, drawcount);} + inline void PointParameterf(GLenum pname, GLfloat param){_detail::PointParameterf(pname, param);} + inline void PointParameterfv(GLenum pname, const GLfloat * params){_detail::PointParameterfv(pname, params);} + inline void PointParameteri(GLenum pname, GLint param){_detail::PointParameteri(pname, param);} + inline void PointParameteriv(GLenum pname, const GLint * params){_detail::PointParameteriv(pname, params);} + + inline void BeginQuery(GLenum target, GLuint id){_detail::BeginQuery(target, id);} + inline void BindBuffer(GLenum target, GLuint buffer){_detail::BindBuffer(target, buffer);} + inline void BufferData(GLenum target, GLsizeiptr size, const void * data, GLenum usage){_detail::BufferData(target, size, data, usage);} + inline void BufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const void * data){_detail::BufferSubData(target, offset, size, data);} + inline void DeleteBuffers(GLsizei n, const GLuint * buffers){_detail::DeleteBuffers(n, buffers);} + inline void DeleteQueries(GLsizei n, const GLuint * ids){_detail::DeleteQueries(n, ids);} + inline void EndQuery(GLenum target){_detail::EndQuery(target);} + inline void GenBuffers(GLsizei n, GLuint * buffers){_detail::GenBuffers(n, buffers);} + inline void GenQueries(GLsizei n, GLuint * ids){_detail::GenQueries(n, ids);} + inline void GetBufferParameteriv(GLenum target, GLenum pname, GLint * params){_detail::GetBufferParameteriv(target, pname, params);} + inline void GetBufferPointerv(GLenum target, GLenum pname, void ** params){_detail::GetBufferPointerv(target, pname, params);} + inline void GetBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, void * data){_detail::GetBufferSubData(target, offset, size, data);} + inline void GetQueryObjectiv(GLuint id, GLenum pname, GLint * params){_detail::GetQueryObjectiv(id, pname, params);} + inline void GetQueryObjectuiv(GLuint id, GLenum pname, GLuint * params){_detail::GetQueryObjectuiv(id, pname, params);} + inline void GetQueryiv(GLenum target, GLenum pname, GLint * params){_detail::GetQueryiv(target, pname, params);} + inline GLboolean IsBuffer(GLuint buffer){return _detail::IsBuffer(buffer);} + inline GLboolean IsQuery(GLuint id){return _detail::IsQuery(id);} + inline void * MapBuffer(GLenum target, GLenum access){return _detail::MapBuffer(target, access);} + inline GLboolean UnmapBuffer(GLenum target){return _detail::UnmapBuffer(target);} + + inline void AttachShader(GLuint program, GLuint shader){_detail::AttachShader(program, shader);} + inline void BindAttribLocation(GLuint program, GLuint index, const GLchar * name){_detail::BindAttribLocation(program, index, name);} + inline void BlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha){_detail::BlendEquationSeparate(modeRGB, modeAlpha);} + inline void CompileShader(GLuint shader){_detail::CompileShader(shader);} + inline GLuint CreateProgram(void){return _detail::CreateProgram();} + inline GLuint CreateShader(GLenum type){return _detail::CreateShader(type);} + inline void DeleteProgram(GLuint program){_detail::DeleteProgram(program);} + inline void DeleteShader(GLuint shader){_detail::DeleteShader(shader);} + inline void DetachShader(GLuint program, GLuint shader){_detail::DetachShader(program, shader);} + inline void DisableVertexAttribArray(GLuint index){_detail::DisableVertexAttribArray(index);} + inline void DrawBuffers(GLsizei n, const GLenum * bufs){_detail::DrawBuffers(n, bufs);} + inline void EnableVertexAttribArray(GLuint index){_detail::EnableVertexAttribArray(index);} + inline void GetActiveAttrib(GLuint program, GLuint index, GLsizei bufSize, GLsizei * length, GLint * size, GLenum * type, GLchar * name){_detail::GetActiveAttrib(program, index, bufSize, length, size, type, name);} + inline void GetActiveUniform(GLuint program, GLuint index, GLsizei bufSize, GLsizei * length, GLint * size, GLenum * type, GLchar * name){_detail::GetActiveUniform(program, index, bufSize, length, size, type, name);} + inline void GetAttachedShaders(GLuint program, GLsizei maxCount, GLsizei * count, GLuint * shaders){_detail::GetAttachedShaders(program, maxCount, count, shaders);} + inline GLint GetAttribLocation(GLuint program, const GLchar * name){return _detail::GetAttribLocation(program, name);} + inline void GetProgramInfoLog(GLuint program, GLsizei bufSize, GLsizei * length, GLchar * infoLog){_detail::GetProgramInfoLog(program, bufSize, length, infoLog);} + inline void GetProgramiv(GLuint program, GLenum pname, GLint * params){_detail::GetProgramiv(program, pname, params);} + inline void GetShaderInfoLog(GLuint shader, GLsizei bufSize, GLsizei * length, GLchar * infoLog){_detail::GetShaderInfoLog(shader, bufSize, length, infoLog);} + inline void GetShaderSource(GLuint shader, GLsizei bufSize, GLsizei * length, GLchar * source){_detail::GetShaderSource(shader, bufSize, length, source);} + inline void GetShaderiv(GLuint shader, GLenum pname, GLint * params){_detail::GetShaderiv(shader, pname, params);} + inline GLint GetUniformLocation(GLuint program, const GLchar * name){return _detail::GetUniformLocation(program, name);} + inline void GetUniformfv(GLuint program, GLint location, GLfloat * params){_detail::GetUniformfv(program, location, params);} + inline void GetUniformiv(GLuint program, GLint location, GLint * params){_detail::GetUniformiv(program, location, params);} + inline void GetVertexAttribPointerv(GLuint index, GLenum pname, void ** pointer){_detail::GetVertexAttribPointerv(index, pname, pointer);} + inline void GetVertexAttribdv(GLuint index, GLenum pname, GLdouble * params){_detail::GetVertexAttribdv(index, pname, params);} + inline void GetVertexAttribfv(GLuint index, GLenum pname, GLfloat * params){_detail::GetVertexAttribfv(index, pname, params);} + inline void GetVertexAttribiv(GLuint index, GLenum pname, GLint * params){_detail::GetVertexAttribiv(index, pname, params);} + inline GLboolean IsProgram(GLuint program){return _detail::IsProgram(program);} + inline GLboolean IsShader(GLuint shader){return _detail::IsShader(shader);} + inline void LinkProgram(GLuint program){_detail::LinkProgram(program);} + inline void ShaderSource(GLuint shader, GLsizei count, const GLchar *const* string, const GLint * length){_detail::ShaderSource(shader, count, string, length);} + inline void StencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask){_detail::StencilFuncSeparate(face, func, ref, mask);} + inline void StencilMaskSeparate(GLenum face, GLuint mask){_detail::StencilMaskSeparate(face, mask);} + inline void StencilOpSeparate(GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass){_detail::StencilOpSeparate(face, sfail, dpfail, dppass);} + inline void Uniform1f(GLint location, GLfloat v0){_detail::Uniform1f(location, v0);} + inline void Uniform1fv(GLint location, GLsizei count, const GLfloat * value){_detail::Uniform1fv(location, count, value);} + inline void Uniform1i(GLint location, GLint v0){_detail::Uniform1i(location, v0);} + inline void Uniform1iv(GLint location, GLsizei count, const GLint * value){_detail::Uniform1iv(location, count, value);} + inline void Uniform2f(GLint location, GLfloat v0, GLfloat v1){_detail::Uniform2f(location, v0, v1);} + inline void Uniform2fv(GLint location, GLsizei count, const GLfloat * value){_detail::Uniform2fv(location, count, value);} + inline void Uniform2i(GLint location, GLint v0, GLint v1){_detail::Uniform2i(location, v0, v1);} + inline void Uniform2iv(GLint location, GLsizei count, const GLint * value){_detail::Uniform2iv(location, count, value);} + inline void Uniform3f(GLint location, GLfloat v0, GLfloat v1, GLfloat v2){_detail::Uniform3f(location, v0, v1, v2);} + inline void Uniform3fv(GLint location, GLsizei count, const GLfloat * value){_detail::Uniform3fv(location, count, value);} + inline void Uniform3i(GLint location, GLint v0, GLint v1, GLint v2){_detail::Uniform3i(location, v0, v1, v2);} + inline void Uniform3iv(GLint location, GLsizei count, const GLint * value){_detail::Uniform3iv(location, count, value);} + inline void Uniform4f(GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3){_detail::Uniform4f(location, v0, v1, v2, v3);} + inline void Uniform4fv(GLint location, GLsizei count, const GLfloat * value){_detail::Uniform4fv(location, count, value);} + inline void Uniform4i(GLint location, GLint v0, GLint v1, GLint v2, GLint v3){_detail::Uniform4i(location, v0, v1, v2, v3);} + inline void Uniform4iv(GLint location, GLsizei count, const GLint * value){_detail::Uniform4iv(location, count, value);} + inline void UniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value){_detail::UniformMatrix2fv(location, count, transpose, value);} + inline void UniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value){_detail::UniformMatrix3fv(location, count, transpose, value);} + inline void UniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value){_detail::UniformMatrix4fv(location, count, transpose, value);} + inline void UseProgram(GLuint program){_detail::UseProgram(program);} + inline void ValidateProgram(GLuint program){_detail::ValidateProgram(program);} + inline void VertexAttrib1d(GLuint index, GLdouble x){_detail::VertexAttrib1d(index, x);} + inline void VertexAttrib1dv(GLuint index, const GLdouble * v){_detail::VertexAttrib1dv(index, v);} + inline void VertexAttrib1f(GLuint index, GLfloat x){_detail::VertexAttrib1f(index, x);} + inline void VertexAttrib1fv(GLuint index, const GLfloat * v){_detail::VertexAttrib1fv(index, v);} + inline void VertexAttrib1s(GLuint index, GLshort x){_detail::VertexAttrib1s(index, x);} + inline void VertexAttrib1sv(GLuint index, const GLshort * v){_detail::VertexAttrib1sv(index, v);} + inline void VertexAttrib2d(GLuint index, GLdouble x, GLdouble y){_detail::VertexAttrib2d(index, x, y);} + inline void VertexAttrib2dv(GLuint index, const GLdouble * v){_detail::VertexAttrib2dv(index, v);} + inline void VertexAttrib2f(GLuint index, GLfloat x, GLfloat y){_detail::VertexAttrib2f(index, x, y);} + inline void VertexAttrib2fv(GLuint index, const GLfloat * v){_detail::VertexAttrib2fv(index, v);} + inline void VertexAttrib2s(GLuint index, GLshort x, GLshort y){_detail::VertexAttrib2s(index, x, y);} + inline void VertexAttrib2sv(GLuint index, const GLshort * v){_detail::VertexAttrib2sv(index, v);} + inline void VertexAttrib3d(GLuint index, GLdouble x, GLdouble y, GLdouble z){_detail::VertexAttrib3d(index, x, y, z);} + inline void VertexAttrib3dv(GLuint index, const GLdouble * v){_detail::VertexAttrib3dv(index, v);} + inline void VertexAttrib3f(GLuint index, GLfloat x, GLfloat y, GLfloat z){_detail::VertexAttrib3f(index, x, y, z);} + inline void VertexAttrib3fv(GLuint index, const GLfloat * v){_detail::VertexAttrib3fv(index, v);} + inline void VertexAttrib3s(GLuint index, GLshort x, GLshort y, GLshort z){_detail::VertexAttrib3s(index, x, y, z);} + inline void VertexAttrib3sv(GLuint index, const GLshort * v){_detail::VertexAttrib3sv(index, v);} + inline void VertexAttrib4Nbv(GLuint index, const GLbyte * v){_detail::VertexAttrib4Nbv(index, v);} + inline void VertexAttrib4Niv(GLuint index, const GLint * v){_detail::VertexAttrib4Niv(index, v);} + inline void VertexAttrib4Nsv(GLuint index, const GLshort * v){_detail::VertexAttrib4Nsv(index, v);} + inline void VertexAttrib4Nub(GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w){_detail::VertexAttrib4Nub(index, x, y, z, w);} + inline void VertexAttrib4Nubv(GLuint index, const GLubyte * v){_detail::VertexAttrib4Nubv(index, v);} + inline void VertexAttrib4Nuiv(GLuint index, const GLuint * v){_detail::VertexAttrib4Nuiv(index, v);} + inline void VertexAttrib4Nusv(GLuint index, const GLushort * v){_detail::VertexAttrib4Nusv(index, v);} + inline void VertexAttrib4bv(GLuint index, const GLbyte * v){_detail::VertexAttrib4bv(index, v);} + inline void VertexAttrib4d(GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w){_detail::VertexAttrib4d(index, x, y, z, w);} + inline void VertexAttrib4dv(GLuint index, const GLdouble * v){_detail::VertexAttrib4dv(index, v);} + inline void VertexAttrib4f(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w){_detail::VertexAttrib4f(index, x, y, z, w);} + inline void VertexAttrib4fv(GLuint index, const GLfloat * v){_detail::VertexAttrib4fv(index, v);} + inline void VertexAttrib4iv(GLuint index, const GLint * v){_detail::VertexAttrib4iv(index, v);} + inline void VertexAttrib4s(GLuint index, GLshort x, GLshort y, GLshort z, GLshort w){_detail::VertexAttrib4s(index, x, y, z, w);} + inline void VertexAttrib4sv(GLuint index, const GLshort * v){_detail::VertexAttrib4sv(index, v);} + inline void VertexAttrib4ubv(GLuint index, const GLubyte * v){_detail::VertexAttrib4ubv(index, v);} + inline void VertexAttrib4uiv(GLuint index, const GLuint * v){_detail::VertexAttrib4uiv(index, v);} + inline void VertexAttrib4usv(GLuint index, const GLushort * v){_detail::VertexAttrib4usv(index, v);} + inline void VertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void * pointer){_detail::VertexAttribPointer(index, size, type, normalized, stride, pointer);} + + inline void UniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value){_detail::UniformMatrix2x3fv(location, count, transpose, value);} + inline void UniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value){_detail::UniformMatrix2x4fv(location, count, transpose, value);} + inline void UniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value){_detail::UniformMatrix3x2fv(location, count, transpose, value);} + inline void UniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value){_detail::UniformMatrix3x4fv(location, count, transpose, value);} + inline void UniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value){_detail::UniformMatrix4x2fv(location, count, transpose, value);} + inline void UniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value){_detail::UniformMatrix4x3fv(location, count, transpose, value);} + + inline void BeginConditionalRender(GLuint id, GLenum mode){_detail::BeginConditionalRender(id, mode);} + inline void BeginTransformFeedback(GLenum primitiveMode){_detail::BeginTransformFeedback(primitiveMode);} + inline void BindBufferBase(GLenum target, GLuint index, GLuint buffer){_detail::BindBufferBase(target, index, buffer);} + inline void BindBufferRange(GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size){_detail::BindBufferRange(target, index, buffer, offset, size);} + inline void BindFragDataLocation(GLuint program, GLuint color, const GLchar * name){_detail::BindFragDataLocation(program, color, name);} + inline void BindFramebuffer(GLenum target, GLuint framebuffer){_detail::BindFramebuffer(target, framebuffer);} + inline void BindRenderbuffer(GLenum target, GLuint renderbuffer){_detail::BindRenderbuffer(target, renderbuffer);} + inline void BindVertexArray(GLuint ren_array){_detail::BindVertexArray(ren_array);} + inline void BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter){_detail::BlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);} + inline GLenum CheckFramebufferStatus(GLenum target){return _detail::CheckFramebufferStatus(target);} + inline void ClampColor(GLenum target, GLenum clamp){_detail::ClampColor(target, clamp);} + inline void ClearBufferfi(GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil){_detail::ClearBufferfi(buffer, drawbuffer, depth, stencil);} + inline void ClearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat * value){_detail::ClearBufferfv(buffer, drawbuffer, value);} + inline void ClearBufferiv(GLenum buffer, GLint drawbuffer, const GLint * value){_detail::ClearBufferiv(buffer, drawbuffer, value);} + inline void ClearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint * value){_detail::ClearBufferuiv(buffer, drawbuffer, value);} + inline void ColorMaski(GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a){_detail::ColorMaski(index, r, g, b, a);} + inline void DeleteFramebuffers(GLsizei n, const GLuint * framebuffers){_detail::DeleteFramebuffers(n, framebuffers);} + inline void DeleteRenderbuffers(GLsizei n, const GLuint * renderbuffers){_detail::DeleteRenderbuffers(n, renderbuffers);} + inline void DeleteVertexArrays(GLsizei n, const GLuint * arrays){_detail::DeleteVertexArrays(n, arrays);} + inline void Disablei(GLenum target, GLuint index){_detail::Disablei(target, index);} + inline void Enablei(GLenum target, GLuint index){_detail::Enablei(target, index);} + inline void EndConditionalRender(void){_detail::EndConditionalRender();} + inline void EndTransformFeedback(void){_detail::EndTransformFeedback();} + inline void FlushMappedBufferRange(GLenum target, GLintptr offset, GLsizeiptr length){_detail::FlushMappedBufferRange(target, offset, length);} + inline void FramebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer){_detail::FramebufferRenderbuffer(target, attachment, renderbuffertarget, renderbuffer);} + inline void FramebufferTexture1D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level){_detail::FramebufferTexture1D(target, attachment, textarget, texture, level);} + inline void FramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level){_detail::FramebufferTexture2D(target, attachment, textarget, texture, level);} + inline void FramebufferTexture3D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset){_detail::FramebufferTexture3D(target, attachment, textarget, texture, level, zoffset);} + inline void FramebufferTextureLayer(GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer){_detail::FramebufferTextureLayer(target, attachment, texture, level, layer);} + inline void GenFramebuffers(GLsizei n, GLuint * framebuffers){_detail::GenFramebuffers(n, framebuffers);} + inline void GenRenderbuffers(GLsizei n, GLuint * renderbuffers){_detail::GenRenderbuffers(n, renderbuffers);} + inline void GenVertexArrays(GLsizei n, GLuint * arrays){_detail::GenVertexArrays(n, arrays);} + inline void GenerateMipmap(GLenum target){_detail::GenerateMipmap(target);} + inline void GetBooleani_v(GLenum target, GLuint index, GLboolean * data){_detail::GetBooleani_v(target, index, data);} + inline GLint GetFragDataLocation(GLuint program, const GLchar * name){return _detail::GetFragDataLocation(program, name);} + inline void GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, GLenum pname, GLint * params){_detail::GetFramebufferAttachmentParameteriv(target, attachment, pname, params);} + inline void GetIntegeri_v(GLenum target, GLuint index, GLint * data){_detail::GetIntegeri_v(target, index, data);} + inline void GetRenderbufferParameteriv(GLenum target, GLenum pname, GLint * params){_detail::GetRenderbufferParameteriv(target, pname, params);} + inline const GLubyte * GetStringi(GLenum name, GLuint index){return _detail::GetStringi(name, index);} + inline void GetTexParameterIiv(GLenum target, GLenum pname, GLint * params){_detail::GetTexParameterIiv(target, pname, params);} + inline void GetTexParameterIuiv(GLenum target, GLenum pname, GLuint * params){_detail::GetTexParameterIuiv(target, pname, params);} + inline void GetTransformFeedbackVarying(GLuint program, GLuint index, GLsizei bufSize, GLsizei * length, GLsizei * size, GLenum * type, GLchar * name){_detail::GetTransformFeedbackVarying(program, index, bufSize, length, size, type, name);} + inline void GetUniformuiv(GLuint program, GLint location, GLuint * params){_detail::GetUniformuiv(program, location, params);} + inline void GetVertexAttribIiv(GLuint index, GLenum pname, GLint * params){_detail::GetVertexAttribIiv(index, pname, params);} + inline void GetVertexAttribIuiv(GLuint index, GLenum pname, GLuint * params){_detail::GetVertexAttribIuiv(index, pname, params);} + inline GLboolean IsEnabledi(GLenum target, GLuint index){return _detail::IsEnabledi(target, index);} + inline GLboolean IsFramebuffer(GLuint framebuffer){return _detail::IsFramebuffer(framebuffer);} + inline GLboolean IsRenderbuffer(GLuint renderbuffer){return _detail::IsRenderbuffer(renderbuffer);} + inline GLboolean IsVertexArray(GLuint ren_array){return _detail::IsVertexArray(ren_array);} + inline void * MapBufferRange(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access){return _detail::MapBufferRange(target, offset, length, access);} + inline void RenderbufferStorage(GLenum target, GLenum internalformat, GLsizei width, GLsizei height){_detail::RenderbufferStorage(target, internalformat, width, height);} + inline void RenderbufferStorageMultisample(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height){_detail::RenderbufferStorageMultisample(target, samples, internalformat, width, height);} + inline void TexParameterIiv(GLenum target, GLenum pname, const GLint * params){_detail::TexParameterIiv(target, pname, params);} + inline void TexParameterIuiv(GLenum target, GLenum pname, const GLuint * params){_detail::TexParameterIuiv(target, pname, params);} + inline void TransformFeedbackVaryings(GLuint program, GLsizei count, const GLchar *const* varyings, GLenum bufferMode){_detail::TransformFeedbackVaryings(program, count, varyings, bufferMode);} + inline void Uniform1ui(GLint location, GLuint v0){_detail::Uniform1ui(location, v0);} + inline void Uniform1uiv(GLint location, GLsizei count, const GLuint * value){_detail::Uniform1uiv(location, count, value);} + inline void Uniform2ui(GLint location, GLuint v0, GLuint v1){_detail::Uniform2ui(location, v0, v1);} + inline void Uniform2uiv(GLint location, GLsizei count, const GLuint * value){_detail::Uniform2uiv(location, count, value);} + inline void Uniform3ui(GLint location, GLuint v0, GLuint v1, GLuint v2){_detail::Uniform3ui(location, v0, v1, v2);} + inline void Uniform3uiv(GLint location, GLsizei count, const GLuint * value){_detail::Uniform3uiv(location, count, value);} + inline void Uniform4ui(GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3){_detail::Uniform4ui(location, v0, v1, v2, v3);} + inline void Uniform4uiv(GLint location, GLsizei count, const GLuint * value){_detail::Uniform4uiv(location, count, value);} + inline void VertexAttribI1i(GLuint index, GLint x){_detail::VertexAttribI1i(index, x);} + inline void VertexAttribI1iv(GLuint index, const GLint * v){_detail::VertexAttribI1iv(index, v);} + inline void VertexAttribI1ui(GLuint index, GLuint x){_detail::VertexAttribI1ui(index, x);} + inline void VertexAttribI1uiv(GLuint index, const GLuint * v){_detail::VertexAttribI1uiv(index, v);} + inline void VertexAttribI2i(GLuint index, GLint x, GLint y){_detail::VertexAttribI2i(index, x, y);} + inline void VertexAttribI2iv(GLuint index, const GLint * v){_detail::VertexAttribI2iv(index, v);} + inline void VertexAttribI2ui(GLuint index, GLuint x, GLuint y){_detail::VertexAttribI2ui(index, x, y);} + inline void VertexAttribI2uiv(GLuint index, const GLuint * v){_detail::VertexAttribI2uiv(index, v);} + inline void VertexAttribI3i(GLuint index, GLint x, GLint y, GLint z){_detail::VertexAttribI3i(index, x, y, z);} + inline void VertexAttribI3iv(GLuint index, const GLint * v){_detail::VertexAttribI3iv(index, v);} + inline void VertexAttribI3ui(GLuint index, GLuint x, GLuint y, GLuint z){_detail::VertexAttribI3ui(index, x, y, z);} + inline void VertexAttribI3uiv(GLuint index, const GLuint * v){_detail::VertexAttribI3uiv(index, v);} + inline void VertexAttribI4bv(GLuint index, const GLbyte * v){_detail::VertexAttribI4bv(index, v);} + inline void VertexAttribI4i(GLuint index, GLint x, GLint y, GLint z, GLint w){_detail::VertexAttribI4i(index, x, y, z, w);} + inline void VertexAttribI4iv(GLuint index, const GLint * v){_detail::VertexAttribI4iv(index, v);} + inline void VertexAttribI4sv(GLuint index, const GLshort * v){_detail::VertexAttribI4sv(index, v);} + inline void VertexAttribI4ubv(GLuint index, const GLubyte * v){_detail::VertexAttribI4ubv(index, v);} + inline void VertexAttribI4ui(GLuint index, GLuint x, GLuint y, GLuint z, GLuint w){_detail::VertexAttribI4ui(index, x, y, z, w);} + inline void VertexAttribI4uiv(GLuint index, const GLuint * v){_detail::VertexAttribI4uiv(index, v);} + inline void VertexAttribI4usv(GLuint index, const GLushort * v){_detail::VertexAttribI4usv(index, v);} + inline void VertexAttribIPointer(GLuint index, GLint size, GLenum type, GLsizei stride, const void * pointer){_detail::VertexAttribIPointer(index, size, type, stride, pointer);} + + inline void CopyBufferSubData(GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size){_detail::CopyBufferSubData(readTarget, writeTarget, readOffset, writeOffset, size);} + inline void DrawArraysInstanced(GLenum mode, GLint first, GLsizei count, GLsizei instancecount){_detail::DrawArraysInstanced(mode, first, count, instancecount);} + inline void DrawElementsInstanced(GLenum mode, GLsizei count, GLenum type, const void * indices, GLsizei instancecount){_detail::DrawElementsInstanced(mode, count, type, indices, instancecount);} + inline void GetActiveUniformBlockName(GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei * length, GLchar * uniformBlockName){_detail::GetActiveUniformBlockName(program, uniformBlockIndex, bufSize, length, uniformBlockName);} + inline void GetActiveUniformBlockiv(GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint * params){_detail::GetActiveUniformBlockiv(program, uniformBlockIndex, pname, params);} + inline void GetActiveUniformName(GLuint program, GLuint uniformIndex, GLsizei bufSize, GLsizei * length, GLchar * uniformName){_detail::GetActiveUniformName(program, uniformIndex, bufSize, length, uniformName);} + inline void GetActiveUniformsiv(GLuint program, GLsizei uniformCount, const GLuint * uniformIndices, GLenum pname, GLint * params){_detail::GetActiveUniformsiv(program, uniformCount, uniformIndices, pname, params);} + inline GLuint GetUniformBlockIndex(GLuint program, const GLchar * uniformBlockName){return _detail::GetUniformBlockIndex(program, uniformBlockName);} + inline void GetUniformIndices(GLuint program, GLsizei uniformCount, const GLchar *const* uniformNames, GLuint * uniformIndices){_detail::GetUniformIndices(program, uniformCount, uniformNames, uniformIndices);} + inline void PrimitiveRestartIndex(GLuint index){_detail::PrimitiveRestartIndex(index);} + inline void TexBuffer(GLenum target, GLenum internalformat, GLuint buffer){_detail::TexBuffer(target, internalformat, buffer);} + inline void UniformBlockBinding(GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding){_detail::UniformBlockBinding(program, uniformBlockIndex, uniformBlockBinding);} + + inline GLenum ClientWaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout){return _detail::ClientWaitSync(sync, flags, timeout);} + inline void DeleteSync(GLsync sync){_detail::DeleteSync(sync);} + inline void DrawElementsBaseVertex(GLenum mode, GLsizei count, GLenum type, const void * indices, GLint basevertex){_detail::DrawElementsBaseVertex(mode, count, type, indices, basevertex);} + inline void DrawElementsInstancedBaseVertex(GLenum mode, GLsizei count, GLenum type, const void * indices, GLsizei instancecount, GLint basevertex){_detail::DrawElementsInstancedBaseVertex(mode, count, type, indices, instancecount, basevertex);} + inline void DrawRangeElementsBaseVertex(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void * indices, GLint basevertex){_detail::DrawRangeElementsBaseVertex(mode, start, end, count, type, indices, basevertex);} + inline GLsync FenceSync(GLenum condition, GLbitfield flags){return _detail::FenceSync(condition, flags);} + inline void FramebufferTexture(GLenum target, GLenum attachment, GLuint texture, GLint level){_detail::FramebufferTexture(target, attachment, texture, level);} + inline void GetBufferParameteri64v(GLenum target, GLenum pname, GLint64 * params){_detail::GetBufferParameteri64v(target, pname, params);} + inline void GetInteger64i_v(GLenum target, GLuint index, GLint64 * data){_detail::GetInteger64i_v(target, index, data);} + inline void GetInteger64v(GLenum pname, GLint64 * data){_detail::GetInteger64v(pname, data);} + inline void GetMultisamplefv(GLenum pname, GLuint index, GLfloat * val){_detail::GetMultisamplefv(pname, index, val);} + inline void GetSynciv(GLsync sync, GLenum pname, GLsizei bufSize, GLsizei * length, GLint * values){_detail::GetSynciv(sync, pname, bufSize, length, values);} + inline GLboolean IsSync(GLsync sync){return _detail::IsSync(sync);} + inline void MultiDrawElementsBaseVertex(GLenum mode, const GLsizei * count, GLenum type, const void *const* indices, GLsizei drawcount, const GLint * basevertex){_detail::MultiDrawElementsBaseVertex(mode, count, type, indices, drawcount, basevertex);} + inline void ProvokingVertex(GLenum mode){_detail::ProvokingVertex(mode);} + inline void SampleMaski(GLuint maskNumber, GLbitfield mask){_detail::SampleMaski(maskNumber, mask);} + inline void TexImage2DMultisample(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations){_detail::TexImage2DMultisample(target, samples, internalformat, width, height, fixedsamplelocations);} + inline void TexImage3DMultisample(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations){_detail::TexImage3DMultisample(target, samples, internalformat, width, height, depth, fixedsamplelocations);} + inline void WaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout){_detail::WaitSync(sync, flags, timeout);} + + inline void BindFragDataLocationIndexed(GLuint program, GLuint colorNumber, GLuint index, const GLchar * name){_detail::BindFragDataLocationIndexed(program, colorNumber, index, name);} + inline void BindSampler(GLuint unit, GLuint sampler){_detail::BindSampler(unit, sampler);} + inline void DeleteSamplers(GLsizei count, const GLuint * samplers){_detail::DeleteSamplers(count, samplers);} + inline void GenSamplers(GLsizei count, GLuint * samplers){_detail::GenSamplers(count, samplers);} + inline GLint GetFragDataIndex(GLuint program, const GLchar * name){return _detail::GetFragDataIndex(program, name);} + inline void GetQueryObjecti64v(GLuint id, GLenum pname, GLint64 * params){_detail::GetQueryObjecti64v(id, pname, params);} + inline void GetQueryObjectui64v(GLuint id, GLenum pname, GLuint64 * params){_detail::GetQueryObjectui64v(id, pname, params);} + inline void GetSamplerParameterIiv(GLuint sampler, GLenum pname, GLint * params){_detail::GetSamplerParameterIiv(sampler, pname, params);} + inline void GetSamplerParameterIuiv(GLuint sampler, GLenum pname, GLuint * params){_detail::GetSamplerParameterIuiv(sampler, pname, params);} + inline void GetSamplerParameterfv(GLuint sampler, GLenum pname, GLfloat * params){_detail::GetSamplerParameterfv(sampler, pname, params);} + inline void GetSamplerParameteriv(GLuint sampler, GLenum pname, GLint * params){_detail::GetSamplerParameteriv(sampler, pname, params);} + inline GLboolean IsSampler(GLuint sampler){return _detail::IsSampler(sampler);} + inline void QueryCounter(GLuint id, GLenum target){_detail::QueryCounter(id, target);} + inline void SamplerParameterIiv(GLuint sampler, GLenum pname, const GLint * param){_detail::SamplerParameterIiv(sampler, pname, param);} + inline void SamplerParameterIuiv(GLuint sampler, GLenum pname, const GLuint * param){_detail::SamplerParameterIuiv(sampler, pname, param);} + inline void SamplerParameterf(GLuint sampler, GLenum pname, GLfloat param){_detail::SamplerParameterf(sampler, pname, param);} + inline void SamplerParameterfv(GLuint sampler, GLenum pname, const GLfloat * param){_detail::SamplerParameterfv(sampler, pname, param);} + inline void SamplerParameteri(GLuint sampler, GLenum pname, GLint param){_detail::SamplerParameteri(sampler, pname, param);} + inline void SamplerParameteriv(GLuint sampler, GLenum pname, const GLint * param){_detail::SamplerParameteriv(sampler, pname, param);} + inline void VertexAttribDivisor(GLuint index, GLuint divisor){_detail::VertexAttribDivisor(index, divisor);} + inline void VertexAttribP1ui(GLuint index, GLenum type, GLboolean normalized, GLuint value){_detail::VertexAttribP1ui(index, type, normalized, value);} + inline void VertexAttribP1uiv(GLuint index, GLenum type, GLboolean normalized, const GLuint * value){_detail::VertexAttribP1uiv(index, type, normalized, value);} + inline void VertexAttribP2ui(GLuint index, GLenum type, GLboolean normalized, GLuint value){_detail::VertexAttribP2ui(index, type, normalized, value);} + inline void VertexAttribP2uiv(GLuint index, GLenum type, GLboolean normalized, const GLuint * value){_detail::VertexAttribP2uiv(index, type, normalized, value);} + inline void VertexAttribP3ui(GLuint index, GLenum type, GLboolean normalized, GLuint value){_detail::VertexAttribP3ui(index, type, normalized, value);} + inline void VertexAttribP3uiv(GLuint index, GLenum type, GLboolean normalized, const GLuint * value){_detail::VertexAttribP3uiv(index, type, normalized, value);} + inline void VertexAttribP4ui(GLuint index, GLenum type, GLboolean normalized, GLuint value){_detail::VertexAttribP4ui(index, type, normalized, value);} + inline void VertexAttribP4uiv(GLuint index, GLenum type, GLboolean normalized, const GLuint * value){_detail::VertexAttribP4uiv(index, type, normalized, value);} + + + namespace sys + { + + exts::LoadTest LoadFunctions(); + + int GetMinorVersion(); + int GetMajorVersion(); + bool IsVersionGEQ(int majorVersion, int minorVersion); + + } //namespace sys +} //namespace gl +#endif //FUNCTION_CPP_GENERATED_HEADEROPENGL_HPP diff --git a/libs/gfx/include/psemek/gfx/mesh.hpp b/libs/gfx/include/psemek/gfx/mesh.hpp new file mode 100644 index 00000000..3ed232d5 --- /dev/null +++ b/libs/gfx/include/psemek/gfx/mesh.hpp @@ -0,0 +1,384 @@ +#pragma once + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +namespace psemek::gfx +{ + + template + struct normalized + {}; + + template + struct attrib_traits; + + template <> + struct attrib_traits + { + using attrib_type = std::uint8_t; + + static constexpr GLint size = 1; + static constexpr GLenum type = gl::UNSIGNED_BYTE; + static constexpr GLboolean normalized = gl::FALSE_; + }; + + template <> + struct attrib_traits + { + using attrib_type = std::int8_t; + + static constexpr GLint size = 1; + static constexpr GLenum type = gl::BYTE; + static constexpr GLboolean normalized = gl::FALSE_; + }; + + template <> + struct attrib_traits + { + using attrib_type = std::uint16_t; + + static constexpr GLint size = 1; + static constexpr GLenum type = gl::UNSIGNED_SHORT; + static constexpr GLboolean normalized = gl::FALSE_; + }; + + template <> + struct attrib_traits + { + using attrib_type = std::int16_t; + + static constexpr GLint size = 1; + static constexpr GLenum type = gl::SHORT; + static constexpr GLboolean normalized = gl::FALSE_; + }; + + template <> + struct attrib_traits + { + using attrib_type = std::uint32_t; + + static constexpr GLint size = 1; + static constexpr GLenum type = gl::UNSIGNED_INT; + static constexpr GLboolean normalized = gl::FALSE_; + }; + + template <> + struct attrib_traits + { + using attrib_type = std::int32_t; + + static constexpr GLint size = 1; + static constexpr GLenum type = gl::INT; + static constexpr GLboolean normalized = gl::FALSE_; + }; + + template <> + struct attrib_traits + { + using attrib_type = float; + + static constexpr GLint size = 1; + static constexpr GLenum type = gl::FLOAT; + static constexpr GLboolean normalized = gl::FALSE_; + }; + + template <> + struct attrib_traits + { + using attrib_type = double; + + static constexpr GLint size = 1; + static constexpr GLenum type = gl::DOUBLE; + static constexpr GLboolean normalized = gl::FALSE_; + }; + + template + struct attrib_traits> + { + using attrib_type = geom::vector; + + static constexpr GLint size = N; + static constexpr GLenum type = attrib_traits::type; + static constexpr GLboolean normalized = gl::FALSE_; + }; + + template + struct attrib_traits> + { + using attrib_type = geom::point; + + static constexpr GLint size = N; + static constexpr GLenum type = attrib_traits::type; + static constexpr GLboolean normalized = gl::FALSE_; + }; + + template + struct attrib_traits> + { + using attrib_type = T; + + static constexpr GLint size = attrib_traits::size; + static constexpr GLenum type = attrib_traits::type; + static constexpr GLboolean normalized = gl::TRUE_; + }; + + template + struct vertex + { + static constexpr std::size_t size = (0 + ... + sizeof(typename attrib_traits::attrib_type)); + + using attribs = std::tuple; + using attrib_types = std::tuple::attrib_type...>; + + template + static constexpr std::size_t offset() + { + return offset_impl(std::make_index_sequence{}); + } + + template + auto & get() + { + using T = std::tuple_element_t; + return *reinterpret_cast(reinterpret_cast(&storage) + offset()); + } + + template + auto const & get() const + { + using T = std::tuple_element_t; + return *reinterpret_cast(reinterpret_cast(&storage) + offset()); + } + + vertex() = default; + + vertex(vertex const & other) + { + copy_impl(std::make_index_sequence{}, other); + } + + vertex (typename attrib_traits::attrib_type const & ... args) + { + construct_impl(std::make_index_sequence{}, args...); + } + + vertex & operator = (vertex const & other) + { + if (this != &other) copy_impl(std::make_index_sequence{}, other); + return *this; + } + + std::aligned_storage_t{alignof(Attribs)...})> storage; + + private: + + template + static constexpr std::size_t offset_impl(std::index_sequence) + { + return (0 + ... + sizeof(std::tuple_element_t)); + } + + template + void construct_impl(std::index_sequence, typename attrib_traits::attrib_type const & ... args) + { + ((get() = args), ...); + } + + template + void copy_impl(std::index_sequence, vertex const & other) + { + ((get() = other.get()), ...); + } + }; + + namespace detail + { + + template + void enable_attribs(std::index_sequence) + { + int x[] { ((void) gl::EnableVertexAttribArray(Is), 0) ... }; + (void) x; + } + + template + void attrib_pointer() + { + using traits = attrib_traits>; + gl::VertexAttribPointer(I, traits::size, traits::type, traits::normalized, sizeof(Vertex), reinterpret_cast(Vertex::template offset())); + } + + template + void attrib_pointers(std::index_sequence) + { + int x[] { ((void) attrib_pointer(), 0) ... }; + (void) x; + } + + template + struct mesh_setup; + + template + struct mesh_setup> + { + static void setup() + { + using indices = std::make_index_sequence; + + enable_attribs(indices{}); + attrib_pointers>(indices{}); + } + }; + + template + struct gl_type; + + template <> + struct gl_type + { + static constexpr GLenum value = gl::UNSIGNED_BYTE; + }; + + template <> + struct gl_type + { + static constexpr GLenum value = gl::UNSIGNED_SHORT; + }; + + template <> + struct gl_type + { + static constexpr GLenum value = gl::UNSIGNED_INT; + }; + + template + static constexpr GLenum gl_type_v = gl_type::value; + + } + + struct mesh + { + static mesh null(); + + mesh(); + mesh(mesh &&); + mesh(mesh const &) = delete; + + mesh & operator =(mesh &&); + mesh & operator =(mesh const &) = delete; + + ~mesh(); + + template + void setup() + { + static_assert(sizeof(Vertex) == Vertex::size); + + gl::BindVertexArray(array_); + gl::BindBuffer(gl::ARRAY_BUFFER, buffer_); + + detail::mesh_setup::setup(); + } + + template + void load(std::vector const & vertices, GLenum usage = gl::STREAM_DRAW) + { + gl::BindBuffer(gl::ARRAY_BUFFER, buffer_); + gl::BufferData(gl::ARRAY_BUFFER, vertices.size() * sizeof(Vertex), vertices.data(), usage); + + count_ = vertices.size(); + } + + void draw(GLenum mode) const + { + if (count_ == 0) return; + + gl::BindVertexArray(array_); + gl::DrawArrays(mode, 0, count_); + } + + GLsizei count() const + { + return count_; + } + + private: + GLuint array_; + GLuint buffer_; + + GLsizei count_ = 0; + + mesh(int); + }; + + struct indexed_mesh + { + static indexed_mesh null(); + + indexed_mesh(); + indexed_mesh(indexed_mesh &&); + indexed_mesh(indexed_mesh const &) = delete; + + indexed_mesh & operator =(indexed_mesh &&); + indexed_mesh & operator =(indexed_mesh const &) = delete; + + ~indexed_mesh(); + + template + void setup() + { + gl::BindVertexArray(array_); + gl::BindBuffer(gl::ARRAY_BUFFER, buffer_); + + detail::mesh_setup::setup(); + + gl::BindBuffer(gl::ELEMENT_ARRAY_BUFFER, index_buffer_); + } + + template + void load(std::vector const & vertices, std::vector const & indices, GLenum usage = gl::STREAM_DRAW) + { + gl::BindBuffer(gl::ARRAY_BUFFER, buffer_); + gl::BufferData(gl::ARRAY_BUFFER, vertices.size() * sizeof(Vertex), vertices.data(), usage); + gl::BindBuffer(gl::ARRAY_BUFFER, index_buffer_); + gl::BufferData(gl::ARRAY_BUFFER, indices.size() * sizeof(Index), indices.data(), usage); + + count_ = indices.size(); + index_type_ = detail::gl_type_v; + } + + void draw(GLenum mode) const + { + if (count_ == 0) return; + + gl::BindVertexArray(array_); + gl::DrawElements(mode, count_, index_type_, nullptr); + } + + GLsizei count() const + { + return count_; + } + + private: + GLuint array_; + GLuint buffer_; + GLuint index_buffer_; + + GLsizei count_ = 0; + GLenum index_type_ = 0; + + indexed_mesh(int); + }; + +} diff --git a/libs/gfx/include/psemek/gfx/program.hpp b/libs/gfx/include/psemek/gfx/program.hpp new file mode 100644 index 00000000..41af9fea --- /dev/null +++ b/libs/gfx/include/psemek/gfx/program.hpp @@ -0,0 +1,94 @@ +#pragma once + +#include + +#include +#include +#include +#include + +#include +#include + +namespace psemek::gfx +{ + + struct program + { + program(std::string_view vertex_source, std::string_view fragment_source); + program(std::string_view vertex_source, std::string_view geometry_source, std::string_view fragment_source); + + GLuint id() const; + + void bind() const; + + GLint location(char const * name) const; + + struct uniform_proxy + { + uniform_proxy(GLint location) + : location_(location) + {} + + GLint location() const { return location_; } + + void operator = (int i); + void operator = (unsigned int i); + void operator = (float f); + + void operator = (geom::vector const & v); + void operator = (geom::vector const & v); + void operator = (geom::vector const & v); + void operator = (geom::vector const & v); + + void operator = (geom::vector const & v); + void operator = (geom::vector const & v); + void operator = (geom::vector const & v); + void operator = (geom::vector const & v); + + void operator = (geom::vector const & v); + void operator = (geom::vector const & v); + void operator = (geom::vector const & v); + void operator = (geom::vector const & v); + + void operator = (geom::point const & v); + void operator = (geom::point const & v); + void operator = (geom::point const & v); + void operator = (geom::point const & v); + + void operator = (geom::point const & v); + void operator = (geom::point const & v); + void operator = (geom::point const & v); + void operator = (geom::point const & v); + + void operator = (geom::point const & v); + void operator = (geom::point const & v); + void operator = (geom::point const & v); + void operator = (geom::point const & v); + + void operator = (geom::matrix const & m); + void operator = (geom::matrix const & m); + void operator = (geom::matrix const & m); + void operator = (geom::matrix const & m); + void operator = (geom::matrix const & m); + void operator = (geom::matrix const & m); + void operator = (geom::matrix const & m); + void operator = (geom::matrix const & m); + void operator = (geom::matrix const & m); + + void operator = (geom::interval const & i); + void operator = (geom::interval const & i); + void operator = (geom::interval const & i); + + private: + GLint location_; + }; + + uniform_proxy operator[] (char const * name) const; + + private: + GLuint program_; + mutable std::unordered_map uniforms_; + }; + +} diff --git a/libs/gfx/include/psemek/gfx/render_to_texture.hpp b/libs/gfx/include/psemek/gfx/render_to_texture.hpp new file mode 100644 index 00000000..aa07ac7d --- /dev/null +++ b/libs/gfx/include/psemek/gfx/render_to_texture.hpp @@ -0,0 +1,36 @@ +#pragma once + +#include +#include + +namespace psemek::gfx +{ + + struct render_to_texture + { + render_to_texture() + { + texture_.bind(); + texture_.unbind(); + framebuffer_.color(texture_); + } + + struct framebuffer & framebuffer() { return framebuffer_; } + texture_2d & texture() { return texture_; } + + void bind() const + { + framebuffer_.bind(); + } + + void unbind() const + { + framebuffer_.unbind(); + } + + private: + texture_2d texture_; + struct framebuffer framebuffer_; + }; + +} diff --git a/libs/gfx/include/psemek/gfx/renderbuffer.hpp b/libs/gfx/include/psemek/gfx/renderbuffer.hpp new file mode 100644 index 00000000..ce91fed6 --- /dev/null +++ b/libs/gfx/include/psemek/gfx/renderbuffer.hpp @@ -0,0 +1,33 @@ +#pragma once + +#include + +namespace psemek::gfx +{ + + struct renderbuffer + { + renderbuffer(); + renderbuffer(renderbuffer const &) = delete; + renderbuffer(renderbuffer &&); + + renderbuffer & operator = (renderbuffer const &) = delete; + renderbuffer & operator = (renderbuffer &&); + + ~renderbuffer(); + + static renderbuffer null(); + + GLuint id() const { return id_; } + + void bind() const; + + void storage(GLenum internal_format, GLsizei width, GLsizei height); + + private: + GLuint id_; + + explicit renderbuffer(GLuint id); + }; + +} diff --git a/libs/gfx/include/psemek/gfx/texture.hpp b/libs/gfx/include/psemek/gfx/texture.hpp new file mode 100644 index 00000000..679ff7af --- /dev/null +++ b/libs/gfx/include/psemek/gfx/texture.hpp @@ -0,0 +1,115 @@ +#pragma once + +#include +#include +#include + +namespace psemek::gfx +{ + + template + struct pixel_traits; + + template <> + struct pixel_traits + { + static constexpr GLenum internal_format = gl::R8; + static constexpr GLenum format = gl::RED; + static constexpr GLenum type = gl::UNSIGNED_BYTE; + }; + + template <> + struct pixel_traits> + { + static constexpr GLenum internal_format = gl::RGB8; + static constexpr GLenum format = gl::RGB; + static constexpr GLenum type = gl::UNSIGNED_BYTE; + }; + + template <> + struct pixel_traits> + { + static constexpr GLenum internal_format = gl::RGBA8; + static constexpr GLenum format = gl::RGBA; + static constexpr GLenum type = gl::UNSIGNED_BYTE; + }; + + template <> + struct pixel_traits + { + static constexpr GLenum internal_format = gl::R32F; + static constexpr GLenum format = gl::RED; + static constexpr GLenum type = gl::FLOAT; + }; + + struct texture_2d + { + texture_2d(); + texture_2d(texture_2d const &) = delete; + texture_2d(texture_2d &&); + + texture_2d & operator = (texture_2d const &) = delete; + texture_2d & operator = (texture_2d &&); + + ~texture_2d(); + + static texture_2d null(); + + GLuint id() const { return id_; } + + void bind() const; + + explicit operator bool () const { return id_ != 0; } + + int width() const { return width_; } + int height() const { return height_; } + + geom::vector size() const { return {width_, height_}; } + + void load(GLint internal_format, std::size_t width, std::size_t height, GLenum format, GLenum type, const void * data); + + template + void load(std::size_t width, std::size_t height, Pixel const * data = nullptr) + { + using traits = pixel_traits; + load(traits::internal_format, width, height, traits::format, traits::type, data); + } + + template + void load(util::basic_pixmap const & p) + { + load(p.width(), p.height(), p.data()); + } + + void pixels(GLenum format, GLenum type, void * data) const; + + template + Pixmap pixels() const + { + using traits = pixel_traits; + Pixmap p(width_, height_); + pixels(traits::format, traits::type, p.data()); + return p; + } + + static texture_2d from_data(GLint internal_format, std::size_t width, std::size_t height, GLenum format, GLenum type, const void * data); + + template + static texture_2d from_pixmap(Pixmap const & p) + { + texture_2d t; + t.load(p); + return t; + } + + void generate_mipmap(); + + private: + GLuint id_; + int width_ = 0; + int height_ = 0; + + texture_2d(GLuint id); + }; + +} diff --git a/libs/gfx/source/gfx/buffer.cpp b/libs/gfx/source/gfx/buffer.cpp new file mode 100644 index 00000000..d8a39312 --- /dev/null +++ b/libs/gfx/source/gfx/buffer.cpp @@ -0,0 +1,52 @@ +#include + +namespace psemek::gfx +{ + + buffer::buffer() + { + gl::GenBuffers(1, &id_); + } + + buffer::buffer(buffer && other) + : id_(other.id_) + { + other.id_ = 0; + } + + buffer & buffer::operator = (buffer && other) + { + if (this == &other) return *this; + + gl::DeleteBuffers(1, &id_); + id_ = other.id_; + other.id_ = 0; + return *this; + } + + buffer::~buffer() + { + gl::DeleteBuffers(1, &id_); + } + + buffer buffer::null() + { + return buffer(0); + } + + void buffer::bind() const + { + gl::BindBuffer(gl::ARRAY_BUFFER, id_); + } + + void buffer::load(void const * data, std::size_t size, GLenum usage) + { + bind(); + gl::BufferData(gl::ARRAY_BUFFER, size, data, usage); + } + + buffer::buffer(GLuint id) + : id_(id) + {} + +} diff --git a/libs/gfx/source/gfx/framebuffer.cpp b/libs/gfx/source/gfx/framebuffer.cpp new file mode 100644 index 00000000..307bc567 --- /dev/null +++ b/libs/gfx/source/gfx/framebuffer.cpp @@ -0,0 +1,95 @@ +#include + +namespace psemek::gfx +{ + + static std::string framebuffer_status_string(GLenum status) + { + switch (status) + { + case gl::FRAMEBUFFER_UNDEFINED: return "GL_FRAMEBUFFER_UNDEFINED"; + case gl::FRAMEBUFFER_INCOMPLETE_ATTACHMENT: return "GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT"; + case gl::FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: return "GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT"; + case gl::FRAMEBUFFER_UNSUPPORTED: return "GL_FRAMEBUFFER_UNSUPPORTED"; + case gl::FRAMEBUFFER_INCOMPLETE_MULTISAMPLE: return "GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE"; + } + + return "(unknown)"; + } + + framebuffer::framebuffer() + { + gl::GenFramebuffers(1, &id_); + } + + framebuffer::framebuffer(GLuint id) + : id_(id) + {} + + framebuffer::framebuffer(framebuffer && other) + : id_(other.id_) + { + other.id_ = 0; + } + + framebuffer & framebuffer::operator = (framebuffer && other) + { + if (this == &other) return *this; + + gl::DeleteFramebuffers(1, &id_); + id_ = other.id_; + other.id_ = 0; + return *this; + } + + framebuffer::~framebuffer() + { + gl::DeleteFramebuffers(1, &id_); + } + + framebuffer framebuffer::null() + { + return framebuffer{0}; + } + + void framebuffer::bind() const + { + gl::BindFramebuffer(gl::DRAW_FRAMEBUFFER, id_); + } + + void framebuffer::color(texture_2d const & tex, int attachment) + { + bind(); + gl::FramebufferTexture2D(gl::DRAW_FRAMEBUFFER, gl::COLOR_ATTACHMENT0 + attachment, gl::TEXTURE_2D, tex.id(), 0); + } + + void framebuffer::color(renderbuffer const & rb, int attachment) + { + bind(); + gl::FramebufferRenderbuffer(gl::DRAW_FRAMEBUFFER, gl::COLOR_ATTACHMENT0 + attachment, gl::RENDERBUFFER, rb.id()); + } + + void framebuffer::depth(renderbuffer const & rb) + { + bind(); + gl::FramebufferRenderbuffer(gl::DRAW_FRAMEBUFFER, gl::DEPTH_STENCIL_ATTACHMENT, gl::RENDERBUFFER, rb.id()); + } + + GLenum framebuffer::status() const + { + bind(); + return gl::CheckFramebufferStatus(gl::DRAW_FRAMEBUFFER); + } + + bool framebuffer::complete() const + { + return status() == gl::FRAMEBUFFER_COMPLETE; + } + + void framebuffer::assert_complete() const + { + if (auto s = status(); s != gl::FRAMEBUFFER_COMPLETE) + throw std::runtime_error("Framebuffer incomplete: " + framebuffer_status_string(s)); + } + +} diff --git a/libs/gfx/source/gfx/fullscreen.cpp b/libs/gfx/source/gfx/fullscreen.cpp new file mode 100644 index 00000000..12f0f295 --- /dev/null +++ b/libs/gfx/source/gfx/fullscreen.cpp @@ -0,0 +1,39 @@ +#include + +namespace psemek::gfx +{ + + static indexed_mesh create_fullscreen_quad() + { + indexed_mesh m; + + using vertex = gfx::vertex>; + + std::vector vertices(4); + std::vector indices(6); + + vertices[0].get<0>() = {-1.f, -1.f}; + vertices[1].get<0>() = { 1.f, -1.f}; + vertices[2].get<0>() = {-1.f, 1.f}; + vertices[3].get<0>() = { 1.f, 1.f}; + + indices[0] = 0; + indices[1] = 1; + indices[2] = 2; + indices[3] = 2; + indices[4] = 1; + indices[5] = 3; + + m.setup(); + m.load(vertices, indices, gl::STATIC_DRAW); + + return m; + } + + indexed_mesh const & fullscreen_quad() + { + static indexed_mesh m = create_fullscreen_quad(); + return m; + } + +} diff --git a/libs/gfx/source/gfx/gl.cpp b/libs/gfx/source/gfx/gl.cpp new file mode 100644 index 00000000..42f622de --- /dev/null +++ b/libs/gfx/source/gfx/gl.cpp @@ -0,0 +1,1617 @@ +#include +#include +#include +#include +#include + +#if defined(__APPLE__) +#include + +static void* AppleGLGetProcAddress (const char *name) +{ + static void* image = NULL; + + if (NULL == image) + image = dlopen("/System/Library/Frameworks/OpenGL.framework/Versions/Current/OpenGL", RTLD_LAZY); + + return (image ? dlsym(image, name) : NULL); +} +#endif /* __APPLE__ */ + +#if defined(__sgi) || defined (__sun) +#include +#include + +static void* SunGetProcAddress (const GLubyte* name) +{ + static void* h = NULL; + static void* gpa; + + if (h == NULL) + { + if ((h = dlopen(NULL, RTLD_LAZY | RTLD_LOCAL)) == NULL) return NULL; + gpa = dlsym(h, "glXGetProcAddress"); + } + + if (gpa != NULL) + return ((void*(*)(const GLubyte*))gpa)(name); + else + return dlsym(h, (const char*)name); +} +#endif /* __sgi || __sun */ + +#if defined(_WIN32) + +#ifdef _MSC_VER +#pragma warning(disable: 4055) +#pragma warning(disable: 4054) +#pragma warning(disable: 4996) +#endif + +static int TestPointer(const PROC pTest) +{ + ptrdiff_t iTest; + if(!pTest) return 0; + iTest = (ptrdiff_t)pTest; + + if(iTest == 1 || iTest == 2 || iTest == 3 || iTest == -1) return 0; + + return 1; +} + +static PROC WinGetProcAddress(const char *name) +{ + HMODULE glMod = NULL; + PROC pFunc = wglGetProcAddress((LPCSTR)name); + if(TestPointer(pFunc)) + { + return pFunc; + } + glMod = GetModuleHandleA("OpenGL32.dll"); + return (PROC)GetProcAddress(glMod, (LPCSTR)name); +} + +#define IntGetProcAddress(name) WinGetProcAddress(name) +#else + #if defined(__APPLE__) + #define IntGetProcAddress(name) AppleGLGetProcAddress(name) + #else + #if defined(__sgi) || defined(__sun) + #define IntGetProcAddress(name) SunGetProcAddress(name) + #else /* GLX */ + #include + + #define IntGetProcAddress(name) (*glXGetProcAddressARB)((const GLubyte*)name) + #endif + #endif +#endif + +namespace gl +{ + namespace exts + { + } //namespace exts + + namespace _detail + { + typedef void (CODEGEN_FUNCPTR *PFNBLENDFUNC)(GLenum, GLenum); + PFNBLENDFUNC BlendFunc = 0; + typedef void (CODEGEN_FUNCPTR *PFNCLEAR)(GLbitfield); + PFNCLEAR Clear = 0; + typedef void (CODEGEN_FUNCPTR *PFNCLEARCOLOR)(GLfloat, GLfloat, GLfloat, GLfloat); + PFNCLEARCOLOR ClearColor = 0; + typedef void (CODEGEN_FUNCPTR *PFNCLEARDEPTH)(GLdouble); + PFNCLEARDEPTH ClearDepth = 0; + typedef void (CODEGEN_FUNCPTR *PFNCLEARSTENCIL)(GLint); + PFNCLEARSTENCIL ClearStencil = 0; + typedef void (CODEGEN_FUNCPTR *PFNCOLORMASK)(GLboolean, GLboolean, GLboolean, GLboolean); + PFNCOLORMASK ColorMask = 0; + typedef void (CODEGEN_FUNCPTR *PFNCULLFACE)(GLenum); + PFNCULLFACE CullFace = 0; + typedef void (CODEGEN_FUNCPTR *PFNDEPTHFUNC)(GLenum); + PFNDEPTHFUNC DepthFunc = 0; + typedef void (CODEGEN_FUNCPTR *PFNDEPTHMASK)(GLboolean); + PFNDEPTHMASK DepthMask = 0; + typedef void (CODEGEN_FUNCPTR *PFNDEPTHRANGE)(GLdouble, GLdouble); + PFNDEPTHRANGE DepthRange = 0; + typedef void (CODEGEN_FUNCPTR *PFNDISABLE)(GLenum); + PFNDISABLE Disable = 0; + typedef void (CODEGEN_FUNCPTR *PFNDRAWBUFFER)(GLenum); + PFNDRAWBUFFER DrawBuffer = 0; + typedef void (CODEGEN_FUNCPTR *PFNENABLE)(GLenum); + PFNENABLE Enable = 0; + typedef void (CODEGEN_FUNCPTR *PFNFINISH)(void); + PFNFINISH Finish = 0; + typedef void (CODEGEN_FUNCPTR *PFNFLUSH)(void); + PFNFLUSH Flush = 0; + typedef void (CODEGEN_FUNCPTR *PFNFRONTFACE)(GLenum); + PFNFRONTFACE FrontFace = 0; + typedef void (CODEGEN_FUNCPTR *PFNGETBOOLEANV)(GLenum, GLboolean *); + PFNGETBOOLEANV GetBooleanv = 0; + typedef void (CODEGEN_FUNCPTR *PFNGETDOUBLEV)(GLenum, GLdouble *); + PFNGETDOUBLEV GetDoublev = 0; + typedef GLenum (CODEGEN_FUNCPTR *PFNGETERROR)(void); + PFNGETERROR GetError = 0; + typedef void (CODEGEN_FUNCPTR *PFNGETFLOATV)(GLenum, GLfloat *); + PFNGETFLOATV GetFloatv = 0; + typedef void (CODEGEN_FUNCPTR *PFNGETINTEGERV)(GLenum, GLint *); + PFNGETINTEGERV GetIntegerv = 0; + typedef const GLubyte * (CODEGEN_FUNCPTR *PFNGETSTRING)(GLenum); + PFNGETSTRING GetString = 0; + typedef void (CODEGEN_FUNCPTR *PFNGETTEXIMAGE)(GLenum, GLint, GLenum, GLenum, void *); + PFNGETTEXIMAGE GetTexImage = 0; + typedef void (CODEGEN_FUNCPTR *PFNGETTEXLEVELPARAMETERFV)(GLenum, GLint, GLenum, GLfloat *); + PFNGETTEXLEVELPARAMETERFV GetTexLevelParameterfv = 0; + typedef void (CODEGEN_FUNCPTR *PFNGETTEXLEVELPARAMETERIV)(GLenum, GLint, GLenum, GLint *); + PFNGETTEXLEVELPARAMETERIV GetTexLevelParameteriv = 0; + typedef void (CODEGEN_FUNCPTR *PFNGETTEXPARAMETERFV)(GLenum, GLenum, GLfloat *); + PFNGETTEXPARAMETERFV GetTexParameterfv = 0; + typedef void (CODEGEN_FUNCPTR *PFNGETTEXPARAMETERIV)(GLenum, GLenum, GLint *); + PFNGETTEXPARAMETERIV GetTexParameteriv = 0; + typedef void (CODEGEN_FUNCPTR *PFNHINT)(GLenum, GLenum); + PFNHINT Hint = 0; + typedef GLboolean (CODEGEN_FUNCPTR *PFNISENABLED)(GLenum); + PFNISENABLED IsEnabled = 0; + typedef void (CODEGEN_FUNCPTR *PFNLINEWIDTH)(GLfloat); + PFNLINEWIDTH LineWidth = 0; + typedef void (CODEGEN_FUNCPTR *PFNLOGICOP)(GLenum); + PFNLOGICOP LogicOp = 0; + typedef void (CODEGEN_FUNCPTR *PFNPIXELSTOREF)(GLenum, GLfloat); + PFNPIXELSTOREF PixelStoref = 0; + typedef void (CODEGEN_FUNCPTR *PFNPIXELSTOREI)(GLenum, GLint); + PFNPIXELSTOREI PixelStorei = 0; + typedef void (CODEGEN_FUNCPTR *PFNPOINTSIZE)(GLfloat); + PFNPOINTSIZE PointSize = 0; + typedef void (CODEGEN_FUNCPTR *PFNPOLYGONMODE)(GLenum, GLenum); + PFNPOLYGONMODE PolygonMode = 0; + typedef void (CODEGEN_FUNCPTR *PFNREADBUFFER)(GLenum); + PFNREADBUFFER ReadBuffer = 0; + typedef void (CODEGEN_FUNCPTR *PFNREADPIXELS)(GLint, GLint, GLsizei, GLsizei, GLenum, GLenum, void *); + PFNREADPIXELS ReadPixels = 0; + typedef void (CODEGEN_FUNCPTR *PFNSCISSOR)(GLint, GLint, GLsizei, GLsizei); + PFNSCISSOR Scissor = 0; + typedef void (CODEGEN_FUNCPTR *PFNSTENCILFUNC)(GLenum, GLint, GLuint); + PFNSTENCILFUNC StencilFunc = 0; + typedef void (CODEGEN_FUNCPTR *PFNSTENCILMASK)(GLuint); + PFNSTENCILMASK StencilMask = 0; + typedef void (CODEGEN_FUNCPTR *PFNSTENCILOP)(GLenum, GLenum, GLenum); + PFNSTENCILOP StencilOp = 0; + typedef void (CODEGEN_FUNCPTR *PFNTEXIMAGE1D)(GLenum, GLint, GLint, GLsizei, GLint, GLenum, GLenum, const void *); + PFNTEXIMAGE1D TexImage1D = 0; + typedef void (CODEGEN_FUNCPTR *PFNTEXIMAGE2D)(GLenum, GLint, GLint, GLsizei, GLsizei, GLint, GLenum, GLenum, const void *); + PFNTEXIMAGE2D TexImage2D = 0; + typedef void (CODEGEN_FUNCPTR *PFNTEXPARAMETERF)(GLenum, GLenum, GLfloat); + PFNTEXPARAMETERF TexParameterf = 0; + typedef void (CODEGEN_FUNCPTR *PFNTEXPARAMETERFV)(GLenum, GLenum, const GLfloat *); + PFNTEXPARAMETERFV TexParameterfv = 0; + typedef void (CODEGEN_FUNCPTR *PFNTEXPARAMETERI)(GLenum, GLenum, GLint); + PFNTEXPARAMETERI TexParameteri = 0; + typedef void (CODEGEN_FUNCPTR *PFNTEXPARAMETERIV)(GLenum, GLenum, const GLint *); + PFNTEXPARAMETERIV TexParameteriv = 0; + typedef void (CODEGEN_FUNCPTR *PFNVIEWPORT)(GLint, GLint, GLsizei, GLsizei); + PFNVIEWPORT Viewport = 0; + + typedef void (CODEGEN_FUNCPTR *PFNBINDTEXTURE)(GLenum, GLuint); + PFNBINDTEXTURE BindTexture = 0; + typedef void (CODEGEN_FUNCPTR *PFNCOPYTEXIMAGE1D)(GLenum, GLint, GLenum, GLint, GLint, GLsizei, GLint); + PFNCOPYTEXIMAGE1D CopyTexImage1D = 0; + typedef void (CODEGEN_FUNCPTR *PFNCOPYTEXIMAGE2D)(GLenum, GLint, GLenum, GLint, GLint, GLsizei, GLsizei, GLint); + PFNCOPYTEXIMAGE2D CopyTexImage2D = 0; + typedef void (CODEGEN_FUNCPTR *PFNCOPYTEXSUBIMAGE1D)(GLenum, GLint, GLint, GLint, GLint, GLsizei); + PFNCOPYTEXSUBIMAGE1D CopyTexSubImage1D = 0; + typedef void (CODEGEN_FUNCPTR *PFNCOPYTEXSUBIMAGE2D)(GLenum, GLint, GLint, GLint, GLint, GLint, GLsizei, GLsizei); + PFNCOPYTEXSUBIMAGE2D CopyTexSubImage2D = 0; + typedef void (CODEGEN_FUNCPTR *PFNDELETETEXTURES)(GLsizei, const GLuint *); + PFNDELETETEXTURES DeleteTextures = 0; + typedef void (CODEGEN_FUNCPTR *PFNDRAWARRAYS)(GLenum, GLint, GLsizei); + PFNDRAWARRAYS DrawArrays = 0; + typedef void (CODEGEN_FUNCPTR *PFNDRAWELEMENTS)(GLenum, GLsizei, GLenum, const void *); + PFNDRAWELEMENTS DrawElements = 0; + typedef void (CODEGEN_FUNCPTR *PFNGENTEXTURES)(GLsizei, GLuint *); + PFNGENTEXTURES GenTextures = 0; + typedef GLboolean (CODEGEN_FUNCPTR *PFNISTEXTURE)(GLuint); + PFNISTEXTURE IsTexture = 0; + typedef void (CODEGEN_FUNCPTR *PFNPOLYGONOFFSET)(GLfloat, GLfloat); + PFNPOLYGONOFFSET PolygonOffset = 0; + typedef void (CODEGEN_FUNCPTR *PFNTEXSUBIMAGE1D)(GLenum, GLint, GLint, GLsizei, GLenum, GLenum, const void *); + PFNTEXSUBIMAGE1D TexSubImage1D = 0; + typedef void (CODEGEN_FUNCPTR *PFNTEXSUBIMAGE2D)(GLenum, GLint, GLint, GLint, GLsizei, GLsizei, GLenum, GLenum, const void *); + PFNTEXSUBIMAGE2D TexSubImage2D = 0; + + typedef void (CODEGEN_FUNCPTR *PFNCOPYTEXSUBIMAGE3D)(GLenum, GLint, GLint, GLint, GLint, GLint, GLint, GLsizei, GLsizei); + PFNCOPYTEXSUBIMAGE3D CopyTexSubImage3D = 0; + typedef void (CODEGEN_FUNCPTR *PFNDRAWRANGEELEMENTS)(GLenum, GLuint, GLuint, GLsizei, GLenum, const void *); + PFNDRAWRANGEELEMENTS DrawRangeElements = 0; + typedef void (CODEGEN_FUNCPTR *PFNTEXIMAGE3D)(GLenum, GLint, GLint, GLsizei, GLsizei, GLsizei, GLint, GLenum, GLenum, const void *); + PFNTEXIMAGE3D TexImage3D = 0; + typedef void (CODEGEN_FUNCPTR *PFNTEXSUBIMAGE3D)(GLenum, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLenum, GLenum, const void *); + PFNTEXSUBIMAGE3D TexSubImage3D = 0; + + typedef void (CODEGEN_FUNCPTR *PFNACTIVETEXTURE)(GLenum); + PFNACTIVETEXTURE ActiveTexture = 0; + typedef void (CODEGEN_FUNCPTR *PFNCOMPRESSEDTEXIMAGE1D)(GLenum, GLint, GLenum, GLsizei, GLint, GLsizei, const void *); + PFNCOMPRESSEDTEXIMAGE1D CompressedTexImage1D = 0; + typedef void (CODEGEN_FUNCPTR *PFNCOMPRESSEDTEXIMAGE2D)(GLenum, GLint, GLenum, GLsizei, GLsizei, GLint, GLsizei, const void *); + PFNCOMPRESSEDTEXIMAGE2D CompressedTexImage2D = 0; + typedef void (CODEGEN_FUNCPTR *PFNCOMPRESSEDTEXIMAGE3D)(GLenum, GLint, GLenum, GLsizei, GLsizei, GLsizei, GLint, GLsizei, const void *); + PFNCOMPRESSEDTEXIMAGE3D CompressedTexImage3D = 0; + typedef void (CODEGEN_FUNCPTR *PFNCOMPRESSEDTEXSUBIMAGE1D)(GLenum, GLint, GLint, GLsizei, GLenum, GLsizei, const void *); + PFNCOMPRESSEDTEXSUBIMAGE1D CompressedTexSubImage1D = 0; + typedef void (CODEGEN_FUNCPTR *PFNCOMPRESSEDTEXSUBIMAGE2D)(GLenum, GLint, GLint, GLint, GLsizei, GLsizei, GLenum, GLsizei, const void *); + PFNCOMPRESSEDTEXSUBIMAGE2D CompressedTexSubImage2D = 0; + typedef void (CODEGEN_FUNCPTR *PFNCOMPRESSEDTEXSUBIMAGE3D)(GLenum, GLint, GLint, GLint, GLint, GLsizei, GLsizei, GLsizei, GLenum, GLsizei, const void *); + PFNCOMPRESSEDTEXSUBIMAGE3D CompressedTexSubImage3D = 0; + typedef void (CODEGEN_FUNCPTR *PFNGETCOMPRESSEDTEXIMAGE)(GLenum, GLint, void *); + PFNGETCOMPRESSEDTEXIMAGE GetCompressedTexImage = 0; + typedef void (CODEGEN_FUNCPTR *PFNSAMPLECOVERAGE)(GLfloat, GLboolean); + PFNSAMPLECOVERAGE SampleCoverage = 0; + + typedef void (CODEGEN_FUNCPTR *PFNBLENDCOLOR)(GLfloat, GLfloat, GLfloat, GLfloat); + PFNBLENDCOLOR BlendColor = 0; + typedef void (CODEGEN_FUNCPTR *PFNBLENDEQUATION)(GLenum); + PFNBLENDEQUATION BlendEquation = 0; + typedef void (CODEGEN_FUNCPTR *PFNBLENDFUNCSEPARATE)(GLenum, GLenum, GLenum, GLenum); + PFNBLENDFUNCSEPARATE BlendFuncSeparate = 0; + typedef void (CODEGEN_FUNCPTR *PFNMULTIDRAWARRAYS)(GLenum, const GLint *, const GLsizei *, GLsizei); + PFNMULTIDRAWARRAYS MultiDrawArrays = 0; + typedef void (CODEGEN_FUNCPTR *PFNMULTIDRAWELEMENTS)(GLenum, const GLsizei *, GLenum, const void *const*, GLsizei); + PFNMULTIDRAWELEMENTS MultiDrawElements = 0; + typedef void (CODEGEN_FUNCPTR *PFNPOINTPARAMETERF)(GLenum, GLfloat); + PFNPOINTPARAMETERF PointParameterf = 0; + typedef void (CODEGEN_FUNCPTR *PFNPOINTPARAMETERFV)(GLenum, const GLfloat *); + PFNPOINTPARAMETERFV PointParameterfv = 0; + typedef void (CODEGEN_FUNCPTR *PFNPOINTPARAMETERI)(GLenum, GLint); + PFNPOINTPARAMETERI PointParameteri = 0; + typedef void (CODEGEN_FUNCPTR *PFNPOINTPARAMETERIV)(GLenum, const GLint *); + PFNPOINTPARAMETERIV PointParameteriv = 0; + + typedef void (CODEGEN_FUNCPTR *PFNBEGINQUERY)(GLenum, GLuint); + PFNBEGINQUERY BeginQuery = 0; + typedef void (CODEGEN_FUNCPTR *PFNBINDBUFFER)(GLenum, GLuint); + PFNBINDBUFFER BindBuffer = 0; + typedef void (CODEGEN_FUNCPTR *PFNBUFFERDATA)(GLenum, GLsizeiptr, const void *, GLenum); + PFNBUFFERDATA BufferData = 0; + typedef void (CODEGEN_FUNCPTR *PFNBUFFERSUBDATA)(GLenum, GLintptr, GLsizeiptr, const void *); + PFNBUFFERSUBDATA BufferSubData = 0; + typedef void (CODEGEN_FUNCPTR *PFNDELETEBUFFERS)(GLsizei, const GLuint *); + PFNDELETEBUFFERS DeleteBuffers = 0; + typedef void (CODEGEN_FUNCPTR *PFNDELETEQUERIES)(GLsizei, const GLuint *); + PFNDELETEQUERIES DeleteQueries = 0; + typedef void (CODEGEN_FUNCPTR *PFNENDQUERY)(GLenum); + PFNENDQUERY EndQuery = 0; + typedef void (CODEGEN_FUNCPTR *PFNGENBUFFERS)(GLsizei, GLuint *); + PFNGENBUFFERS GenBuffers = 0; + typedef void (CODEGEN_FUNCPTR *PFNGENQUERIES)(GLsizei, GLuint *); + PFNGENQUERIES GenQueries = 0; + typedef void (CODEGEN_FUNCPTR *PFNGETBUFFERPARAMETERIV)(GLenum, GLenum, GLint *); + PFNGETBUFFERPARAMETERIV GetBufferParameteriv = 0; + typedef void (CODEGEN_FUNCPTR *PFNGETBUFFERPOINTERV)(GLenum, GLenum, void **); + PFNGETBUFFERPOINTERV GetBufferPointerv = 0; + typedef void (CODEGEN_FUNCPTR *PFNGETBUFFERSUBDATA)(GLenum, GLintptr, GLsizeiptr, void *); + PFNGETBUFFERSUBDATA GetBufferSubData = 0; + typedef void (CODEGEN_FUNCPTR *PFNGETQUERYOBJECTIV)(GLuint, GLenum, GLint *); + PFNGETQUERYOBJECTIV GetQueryObjectiv = 0; + typedef void (CODEGEN_FUNCPTR *PFNGETQUERYOBJECTUIV)(GLuint, GLenum, GLuint *); + PFNGETQUERYOBJECTUIV GetQueryObjectuiv = 0; + typedef void (CODEGEN_FUNCPTR *PFNGETQUERYIV)(GLenum, GLenum, GLint *); + PFNGETQUERYIV GetQueryiv = 0; + typedef GLboolean (CODEGEN_FUNCPTR *PFNISBUFFER)(GLuint); + PFNISBUFFER IsBuffer = 0; + typedef GLboolean (CODEGEN_FUNCPTR *PFNISQUERY)(GLuint); + PFNISQUERY IsQuery = 0; + typedef void * (CODEGEN_FUNCPTR *PFNMAPBUFFER)(GLenum, GLenum); + PFNMAPBUFFER MapBuffer = 0; + typedef GLboolean (CODEGEN_FUNCPTR *PFNUNMAPBUFFER)(GLenum); + PFNUNMAPBUFFER UnmapBuffer = 0; + + typedef void (CODEGEN_FUNCPTR *PFNATTACHSHADER)(GLuint, GLuint); + PFNATTACHSHADER AttachShader = 0; + typedef void (CODEGEN_FUNCPTR *PFNBINDATTRIBLOCATION)(GLuint, GLuint, const GLchar *); + PFNBINDATTRIBLOCATION BindAttribLocation = 0; + typedef void (CODEGEN_FUNCPTR *PFNBLENDEQUATIONSEPARATE)(GLenum, GLenum); + PFNBLENDEQUATIONSEPARATE BlendEquationSeparate = 0; + typedef void (CODEGEN_FUNCPTR *PFNCOMPILESHADER)(GLuint); + PFNCOMPILESHADER CompileShader = 0; + typedef GLuint (CODEGEN_FUNCPTR *PFNCREATEPROGRAM)(void); + PFNCREATEPROGRAM CreateProgram = 0; + typedef GLuint (CODEGEN_FUNCPTR *PFNCREATESHADER)(GLenum); + PFNCREATESHADER CreateShader = 0; + typedef void (CODEGEN_FUNCPTR *PFNDELETEPROGRAM)(GLuint); + PFNDELETEPROGRAM DeleteProgram = 0; + typedef void (CODEGEN_FUNCPTR *PFNDELETESHADER)(GLuint); + PFNDELETESHADER DeleteShader = 0; + typedef void (CODEGEN_FUNCPTR *PFNDETACHSHADER)(GLuint, GLuint); + PFNDETACHSHADER DetachShader = 0; + typedef void (CODEGEN_FUNCPTR *PFNDISABLEVERTEXATTRIBARRAY)(GLuint); + PFNDISABLEVERTEXATTRIBARRAY DisableVertexAttribArray = 0; + typedef void (CODEGEN_FUNCPTR *PFNDRAWBUFFERS)(GLsizei, const GLenum *); + PFNDRAWBUFFERS DrawBuffers = 0; + typedef void (CODEGEN_FUNCPTR *PFNENABLEVERTEXATTRIBARRAY)(GLuint); + PFNENABLEVERTEXATTRIBARRAY EnableVertexAttribArray = 0; + typedef void (CODEGEN_FUNCPTR *PFNGETACTIVEATTRIB)(GLuint, GLuint, GLsizei, GLsizei *, GLint *, GLenum *, GLchar *); + PFNGETACTIVEATTRIB GetActiveAttrib = 0; + typedef void (CODEGEN_FUNCPTR *PFNGETACTIVEUNIFORM)(GLuint, GLuint, GLsizei, GLsizei *, GLint *, GLenum *, GLchar *); + PFNGETACTIVEUNIFORM GetActiveUniform = 0; + typedef void (CODEGEN_FUNCPTR *PFNGETATTACHEDSHADERS)(GLuint, GLsizei, GLsizei *, GLuint *); + PFNGETATTACHEDSHADERS GetAttachedShaders = 0; + typedef GLint (CODEGEN_FUNCPTR *PFNGETATTRIBLOCATION)(GLuint, const GLchar *); + PFNGETATTRIBLOCATION GetAttribLocation = 0; + typedef void (CODEGEN_FUNCPTR *PFNGETPROGRAMINFOLOG)(GLuint, GLsizei, GLsizei *, GLchar *); + PFNGETPROGRAMINFOLOG GetProgramInfoLog = 0; + typedef void (CODEGEN_FUNCPTR *PFNGETPROGRAMIV)(GLuint, GLenum, GLint *); + PFNGETPROGRAMIV GetProgramiv = 0; + typedef void (CODEGEN_FUNCPTR *PFNGETSHADERINFOLOG)(GLuint, GLsizei, GLsizei *, GLchar *); + PFNGETSHADERINFOLOG GetShaderInfoLog = 0; + typedef void (CODEGEN_FUNCPTR *PFNGETSHADERSOURCE)(GLuint, GLsizei, GLsizei *, GLchar *); + PFNGETSHADERSOURCE GetShaderSource = 0; + typedef void (CODEGEN_FUNCPTR *PFNGETSHADERIV)(GLuint, GLenum, GLint *); + PFNGETSHADERIV GetShaderiv = 0; + typedef GLint (CODEGEN_FUNCPTR *PFNGETUNIFORMLOCATION)(GLuint, const GLchar *); + PFNGETUNIFORMLOCATION GetUniformLocation = 0; + typedef void (CODEGEN_FUNCPTR *PFNGETUNIFORMFV)(GLuint, GLint, GLfloat *); + PFNGETUNIFORMFV GetUniformfv = 0; + typedef void (CODEGEN_FUNCPTR *PFNGETUNIFORMIV)(GLuint, GLint, GLint *); + PFNGETUNIFORMIV GetUniformiv = 0; + typedef void (CODEGEN_FUNCPTR *PFNGETVERTEXATTRIBPOINTERV)(GLuint, GLenum, void **); + PFNGETVERTEXATTRIBPOINTERV GetVertexAttribPointerv = 0; + typedef void (CODEGEN_FUNCPTR *PFNGETVERTEXATTRIBDV)(GLuint, GLenum, GLdouble *); + PFNGETVERTEXATTRIBDV GetVertexAttribdv = 0; + typedef void (CODEGEN_FUNCPTR *PFNGETVERTEXATTRIBFV)(GLuint, GLenum, GLfloat *); + PFNGETVERTEXATTRIBFV GetVertexAttribfv = 0; + typedef void (CODEGEN_FUNCPTR *PFNGETVERTEXATTRIBIV)(GLuint, GLenum, GLint *); + PFNGETVERTEXATTRIBIV GetVertexAttribiv = 0; + typedef GLboolean (CODEGEN_FUNCPTR *PFNISPROGRAM)(GLuint); + PFNISPROGRAM IsProgram = 0; + typedef GLboolean (CODEGEN_FUNCPTR *PFNISSHADER)(GLuint); + PFNISSHADER IsShader = 0; + typedef void (CODEGEN_FUNCPTR *PFNLINKPROGRAM)(GLuint); + PFNLINKPROGRAM LinkProgram = 0; + typedef void (CODEGEN_FUNCPTR *PFNSHADERSOURCE)(GLuint, GLsizei, const GLchar *const*, const GLint *); + PFNSHADERSOURCE ShaderSource = 0; + typedef void (CODEGEN_FUNCPTR *PFNSTENCILFUNCSEPARATE)(GLenum, GLenum, GLint, GLuint); + PFNSTENCILFUNCSEPARATE StencilFuncSeparate = 0; + typedef void (CODEGEN_FUNCPTR *PFNSTENCILMASKSEPARATE)(GLenum, GLuint); + PFNSTENCILMASKSEPARATE StencilMaskSeparate = 0; + typedef void (CODEGEN_FUNCPTR *PFNSTENCILOPSEPARATE)(GLenum, GLenum, GLenum, GLenum); + PFNSTENCILOPSEPARATE StencilOpSeparate = 0; + typedef void (CODEGEN_FUNCPTR *PFNUNIFORM1F)(GLint, GLfloat); + PFNUNIFORM1F Uniform1f = 0; + typedef void (CODEGEN_FUNCPTR *PFNUNIFORM1FV)(GLint, GLsizei, const GLfloat *); + PFNUNIFORM1FV Uniform1fv = 0; + typedef void (CODEGEN_FUNCPTR *PFNUNIFORM1I)(GLint, GLint); + PFNUNIFORM1I Uniform1i = 0; + typedef void (CODEGEN_FUNCPTR *PFNUNIFORM1IV)(GLint, GLsizei, const GLint *); + PFNUNIFORM1IV Uniform1iv = 0; + typedef void (CODEGEN_FUNCPTR *PFNUNIFORM2F)(GLint, GLfloat, GLfloat); + PFNUNIFORM2F Uniform2f = 0; + typedef void (CODEGEN_FUNCPTR *PFNUNIFORM2FV)(GLint, GLsizei, const GLfloat *); + PFNUNIFORM2FV Uniform2fv = 0; + typedef void (CODEGEN_FUNCPTR *PFNUNIFORM2I)(GLint, GLint, GLint); + PFNUNIFORM2I Uniform2i = 0; + typedef void (CODEGEN_FUNCPTR *PFNUNIFORM2IV)(GLint, GLsizei, const GLint *); + PFNUNIFORM2IV Uniform2iv = 0; + typedef void (CODEGEN_FUNCPTR *PFNUNIFORM3F)(GLint, GLfloat, GLfloat, GLfloat); + PFNUNIFORM3F Uniform3f = 0; + typedef void (CODEGEN_FUNCPTR *PFNUNIFORM3FV)(GLint, GLsizei, const GLfloat *); + PFNUNIFORM3FV Uniform3fv = 0; + typedef void (CODEGEN_FUNCPTR *PFNUNIFORM3I)(GLint, GLint, GLint, GLint); + PFNUNIFORM3I Uniform3i = 0; + typedef void (CODEGEN_FUNCPTR *PFNUNIFORM3IV)(GLint, GLsizei, const GLint *); + PFNUNIFORM3IV Uniform3iv = 0; + typedef void (CODEGEN_FUNCPTR *PFNUNIFORM4F)(GLint, GLfloat, GLfloat, GLfloat, GLfloat); + PFNUNIFORM4F Uniform4f = 0; + typedef void (CODEGEN_FUNCPTR *PFNUNIFORM4FV)(GLint, GLsizei, const GLfloat *); + PFNUNIFORM4FV Uniform4fv = 0; + typedef void (CODEGEN_FUNCPTR *PFNUNIFORM4I)(GLint, GLint, GLint, GLint, GLint); + PFNUNIFORM4I Uniform4i = 0; + typedef void (CODEGEN_FUNCPTR *PFNUNIFORM4IV)(GLint, GLsizei, const GLint *); + PFNUNIFORM4IV Uniform4iv = 0; + typedef void (CODEGEN_FUNCPTR *PFNUNIFORMMATRIX2FV)(GLint, GLsizei, GLboolean, const GLfloat *); + PFNUNIFORMMATRIX2FV UniformMatrix2fv = 0; + typedef void (CODEGEN_FUNCPTR *PFNUNIFORMMATRIX3FV)(GLint, GLsizei, GLboolean, const GLfloat *); + PFNUNIFORMMATRIX3FV UniformMatrix3fv = 0; + typedef void (CODEGEN_FUNCPTR *PFNUNIFORMMATRIX4FV)(GLint, GLsizei, GLboolean, const GLfloat *); + PFNUNIFORMMATRIX4FV UniformMatrix4fv = 0; + typedef void (CODEGEN_FUNCPTR *PFNUSEPROGRAM)(GLuint); + PFNUSEPROGRAM UseProgram = 0; + typedef void (CODEGEN_FUNCPTR *PFNVALIDATEPROGRAM)(GLuint); + PFNVALIDATEPROGRAM ValidateProgram = 0; + typedef void (CODEGEN_FUNCPTR *PFNVERTEXATTRIB1D)(GLuint, GLdouble); + PFNVERTEXATTRIB1D VertexAttrib1d = 0; + typedef void (CODEGEN_FUNCPTR *PFNVERTEXATTRIB1DV)(GLuint, const GLdouble *); + PFNVERTEXATTRIB1DV VertexAttrib1dv = 0; + typedef void (CODEGEN_FUNCPTR *PFNVERTEXATTRIB1F)(GLuint, GLfloat); + PFNVERTEXATTRIB1F VertexAttrib1f = 0; + typedef void (CODEGEN_FUNCPTR *PFNVERTEXATTRIB1FV)(GLuint, const GLfloat *); + PFNVERTEXATTRIB1FV VertexAttrib1fv = 0; + typedef void (CODEGEN_FUNCPTR *PFNVERTEXATTRIB1S)(GLuint, GLshort); + PFNVERTEXATTRIB1S VertexAttrib1s = 0; + typedef void (CODEGEN_FUNCPTR *PFNVERTEXATTRIB1SV)(GLuint, const GLshort *); + PFNVERTEXATTRIB1SV VertexAttrib1sv = 0; + typedef void (CODEGEN_FUNCPTR *PFNVERTEXATTRIB2D)(GLuint, GLdouble, GLdouble); + PFNVERTEXATTRIB2D VertexAttrib2d = 0; + typedef void (CODEGEN_FUNCPTR *PFNVERTEXATTRIB2DV)(GLuint, const GLdouble *); + PFNVERTEXATTRIB2DV VertexAttrib2dv = 0; + typedef void (CODEGEN_FUNCPTR *PFNVERTEXATTRIB2F)(GLuint, GLfloat, GLfloat); + PFNVERTEXATTRIB2F VertexAttrib2f = 0; + typedef void (CODEGEN_FUNCPTR *PFNVERTEXATTRIB2FV)(GLuint, const GLfloat *); + PFNVERTEXATTRIB2FV VertexAttrib2fv = 0; + typedef void (CODEGEN_FUNCPTR *PFNVERTEXATTRIB2S)(GLuint, GLshort, GLshort); + PFNVERTEXATTRIB2S VertexAttrib2s = 0; + typedef void (CODEGEN_FUNCPTR *PFNVERTEXATTRIB2SV)(GLuint, const GLshort *); + PFNVERTEXATTRIB2SV VertexAttrib2sv = 0; + typedef void (CODEGEN_FUNCPTR *PFNVERTEXATTRIB3D)(GLuint, GLdouble, GLdouble, GLdouble); + PFNVERTEXATTRIB3D VertexAttrib3d = 0; + typedef void (CODEGEN_FUNCPTR *PFNVERTEXATTRIB3DV)(GLuint, const GLdouble *); + PFNVERTEXATTRIB3DV VertexAttrib3dv = 0; + typedef void (CODEGEN_FUNCPTR *PFNVERTEXATTRIB3F)(GLuint, GLfloat, GLfloat, GLfloat); + PFNVERTEXATTRIB3F VertexAttrib3f = 0; + typedef void (CODEGEN_FUNCPTR *PFNVERTEXATTRIB3FV)(GLuint, const GLfloat *); + PFNVERTEXATTRIB3FV VertexAttrib3fv = 0; + typedef void (CODEGEN_FUNCPTR *PFNVERTEXATTRIB3S)(GLuint, GLshort, GLshort, GLshort); + PFNVERTEXATTRIB3S VertexAttrib3s = 0; + typedef void (CODEGEN_FUNCPTR *PFNVERTEXATTRIB3SV)(GLuint, const GLshort *); + PFNVERTEXATTRIB3SV VertexAttrib3sv = 0; + typedef void (CODEGEN_FUNCPTR *PFNVERTEXATTRIB4NBV)(GLuint, const GLbyte *); + PFNVERTEXATTRIB4NBV VertexAttrib4Nbv = 0; + typedef void (CODEGEN_FUNCPTR *PFNVERTEXATTRIB4NIV)(GLuint, const GLint *); + PFNVERTEXATTRIB4NIV VertexAttrib4Niv = 0; + typedef void (CODEGEN_FUNCPTR *PFNVERTEXATTRIB4NSV)(GLuint, const GLshort *); + PFNVERTEXATTRIB4NSV VertexAttrib4Nsv = 0; + typedef void (CODEGEN_FUNCPTR *PFNVERTEXATTRIB4NUB)(GLuint, GLubyte, GLubyte, GLubyte, GLubyte); + PFNVERTEXATTRIB4NUB VertexAttrib4Nub = 0; + typedef void (CODEGEN_FUNCPTR *PFNVERTEXATTRIB4NUBV)(GLuint, const GLubyte *); + PFNVERTEXATTRIB4NUBV VertexAttrib4Nubv = 0; + typedef void (CODEGEN_FUNCPTR *PFNVERTEXATTRIB4NUIV)(GLuint, const GLuint *); + PFNVERTEXATTRIB4NUIV VertexAttrib4Nuiv = 0; + typedef void (CODEGEN_FUNCPTR *PFNVERTEXATTRIB4NUSV)(GLuint, const GLushort *); + PFNVERTEXATTRIB4NUSV VertexAttrib4Nusv = 0; + typedef void (CODEGEN_FUNCPTR *PFNVERTEXATTRIB4BV)(GLuint, const GLbyte *); + PFNVERTEXATTRIB4BV VertexAttrib4bv = 0; + typedef void (CODEGEN_FUNCPTR *PFNVERTEXATTRIB4D)(GLuint, GLdouble, GLdouble, GLdouble, GLdouble); + PFNVERTEXATTRIB4D VertexAttrib4d = 0; + typedef void (CODEGEN_FUNCPTR *PFNVERTEXATTRIB4DV)(GLuint, const GLdouble *); + PFNVERTEXATTRIB4DV VertexAttrib4dv = 0; + typedef void (CODEGEN_FUNCPTR *PFNVERTEXATTRIB4F)(GLuint, GLfloat, GLfloat, GLfloat, GLfloat); + PFNVERTEXATTRIB4F VertexAttrib4f = 0; + typedef void (CODEGEN_FUNCPTR *PFNVERTEXATTRIB4FV)(GLuint, const GLfloat *); + PFNVERTEXATTRIB4FV VertexAttrib4fv = 0; + typedef void (CODEGEN_FUNCPTR *PFNVERTEXATTRIB4IV)(GLuint, const GLint *); + PFNVERTEXATTRIB4IV VertexAttrib4iv = 0; + typedef void (CODEGEN_FUNCPTR *PFNVERTEXATTRIB4S)(GLuint, GLshort, GLshort, GLshort, GLshort); + PFNVERTEXATTRIB4S VertexAttrib4s = 0; + typedef void (CODEGEN_FUNCPTR *PFNVERTEXATTRIB4SV)(GLuint, const GLshort *); + PFNVERTEXATTRIB4SV VertexAttrib4sv = 0; + typedef void (CODEGEN_FUNCPTR *PFNVERTEXATTRIB4UBV)(GLuint, const GLubyte *); + PFNVERTEXATTRIB4UBV VertexAttrib4ubv = 0; + typedef void (CODEGEN_FUNCPTR *PFNVERTEXATTRIB4UIV)(GLuint, const GLuint *); + PFNVERTEXATTRIB4UIV VertexAttrib4uiv = 0; + typedef void (CODEGEN_FUNCPTR *PFNVERTEXATTRIB4USV)(GLuint, const GLushort *); + PFNVERTEXATTRIB4USV VertexAttrib4usv = 0; + typedef void (CODEGEN_FUNCPTR *PFNVERTEXATTRIBPOINTER)(GLuint, GLint, GLenum, GLboolean, GLsizei, const void *); + PFNVERTEXATTRIBPOINTER VertexAttribPointer = 0; + + typedef void (CODEGEN_FUNCPTR *PFNUNIFORMMATRIX2X3FV)(GLint, GLsizei, GLboolean, const GLfloat *); + PFNUNIFORMMATRIX2X3FV UniformMatrix2x3fv = 0; + typedef void (CODEGEN_FUNCPTR *PFNUNIFORMMATRIX2X4FV)(GLint, GLsizei, GLboolean, const GLfloat *); + PFNUNIFORMMATRIX2X4FV UniformMatrix2x4fv = 0; + typedef void (CODEGEN_FUNCPTR *PFNUNIFORMMATRIX3X2FV)(GLint, GLsizei, GLboolean, const GLfloat *); + PFNUNIFORMMATRIX3X2FV UniformMatrix3x2fv = 0; + typedef void (CODEGEN_FUNCPTR *PFNUNIFORMMATRIX3X4FV)(GLint, GLsizei, GLboolean, const GLfloat *); + PFNUNIFORMMATRIX3X4FV UniformMatrix3x4fv = 0; + typedef void (CODEGEN_FUNCPTR *PFNUNIFORMMATRIX4X2FV)(GLint, GLsizei, GLboolean, const GLfloat *); + PFNUNIFORMMATRIX4X2FV UniformMatrix4x2fv = 0; + typedef void (CODEGEN_FUNCPTR *PFNUNIFORMMATRIX4X3FV)(GLint, GLsizei, GLboolean, const GLfloat *); + PFNUNIFORMMATRIX4X3FV UniformMatrix4x3fv = 0; + + typedef void (CODEGEN_FUNCPTR *PFNBEGINCONDITIONALRENDER)(GLuint, GLenum); + PFNBEGINCONDITIONALRENDER BeginConditionalRender = 0; + typedef void (CODEGEN_FUNCPTR *PFNBEGINTRANSFORMFEEDBACK)(GLenum); + PFNBEGINTRANSFORMFEEDBACK BeginTransformFeedback = 0; + typedef void (CODEGEN_FUNCPTR *PFNBINDBUFFERBASE)(GLenum, GLuint, GLuint); + PFNBINDBUFFERBASE BindBufferBase = 0; + typedef void (CODEGEN_FUNCPTR *PFNBINDBUFFERRANGE)(GLenum, GLuint, GLuint, GLintptr, GLsizeiptr); + PFNBINDBUFFERRANGE BindBufferRange = 0; + typedef void (CODEGEN_FUNCPTR *PFNBINDFRAGDATALOCATION)(GLuint, GLuint, const GLchar *); + PFNBINDFRAGDATALOCATION BindFragDataLocation = 0; + typedef void (CODEGEN_FUNCPTR *PFNBINDFRAMEBUFFER)(GLenum, GLuint); + PFNBINDFRAMEBUFFER BindFramebuffer = 0; + typedef void (CODEGEN_FUNCPTR *PFNBINDRENDERBUFFER)(GLenum, GLuint); + PFNBINDRENDERBUFFER BindRenderbuffer = 0; + typedef void (CODEGEN_FUNCPTR *PFNBINDVERTEXARRAY)(GLuint); + PFNBINDVERTEXARRAY BindVertexArray = 0; + typedef void (CODEGEN_FUNCPTR *PFNBLITFRAMEBUFFER)(GLint, GLint, GLint, GLint, GLint, GLint, GLint, GLint, GLbitfield, GLenum); + PFNBLITFRAMEBUFFER BlitFramebuffer = 0; + typedef GLenum (CODEGEN_FUNCPTR *PFNCHECKFRAMEBUFFERSTATUS)(GLenum); + PFNCHECKFRAMEBUFFERSTATUS CheckFramebufferStatus = 0; + typedef void (CODEGEN_FUNCPTR *PFNCLAMPCOLOR)(GLenum, GLenum); + PFNCLAMPCOLOR ClampColor = 0; + typedef void (CODEGEN_FUNCPTR *PFNCLEARBUFFERFI)(GLenum, GLint, GLfloat, GLint); + PFNCLEARBUFFERFI ClearBufferfi = 0; + typedef void (CODEGEN_FUNCPTR *PFNCLEARBUFFERFV)(GLenum, GLint, const GLfloat *); + PFNCLEARBUFFERFV ClearBufferfv = 0; + typedef void (CODEGEN_FUNCPTR *PFNCLEARBUFFERIV)(GLenum, GLint, const GLint *); + PFNCLEARBUFFERIV ClearBufferiv = 0; + typedef void (CODEGEN_FUNCPTR *PFNCLEARBUFFERUIV)(GLenum, GLint, const GLuint *); + PFNCLEARBUFFERUIV ClearBufferuiv = 0; + typedef void (CODEGEN_FUNCPTR *PFNCOLORMASKI)(GLuint, GLboolean, GLboolean, GLboolean, GLboolean); + PFNCOLORMASKI ColorMaski = 0; + typedef void (CODEGEN_FUNCPTR *PFNDELETEFRAMEBUFFERS)(GLsizei, const GLuint *); + PFNDELETEFRAMEBUFFERS DeleteFramebuffers = 0; + typedef void (CODEGEN_FUNCPTR *PFNDELETERENDERBUFFERS)(GLsizei, const GLuint *); + PFNDELETERENDERBUFFERS DeleteRenderbuffers = 0; + typedef void (CODEGEN_FUNCPTR *PFNDELETEVERTEXARRAYS)(GLsizei, const GLuint *); + PFNDELETEVERTEXARRAYS DeleteVertexArrays = 0; + typedef void (CODEGEN_FUNCPTR *PFNDISABLEI)(GLenum, GLuint); + PFNDISABLEI Disablei = 0; + typedef void (CODEGEN_FUNCPTR *PFNENABLEI)(GLenum, GLuint); + PFNENABLEI Enablei = 0; + typedef void (CODEGEN_FUNCPTR *PFNENDCONDITIONALRENDER)(void); + PFNENDCONDITIONALRENDER EndConditionalRender = 0; + typedef void (CODEGEN_FUNCPTR *PFNENDTRANSFORMFEEDBACK)(void); + PFNENDTRANSFORMFEEDBACK EndTransformFeedback = 0; + typedef void (CODEGEN_FUNCPTR *PFNFLUSHMAPPEDBUFFERRANGE)(GLenum, GLintptr, GLsizeiptr); + PFNFLUSHMAPPEDBUFFERRANGE FlushMappedBufferRange = 0; + typedef void (CODEGEN_FUNCPTR *PFNFRAMEBUFFERRENDERBUFFER)(GLenum, GLenum, GLenum, GLuint); + PFNFRAMEBUFFERRENDERBUFFER FramebufferRenderbuffer = 0; + typedef void (CODEGEN_FUNCPTR *PFNFRAMEBUFFERTEXTURE1D)(GLenum, GLenum, GLenum, GLuint, GLint); + PFNFRAMEBUFFERTEXTURE1D FramebufferTexture1D = 0; + typedef void (CODEGEN_FUNCPTR *PFNFRAMEBUFFERTEXTURE2D)(GLenum, GLenum, GLenum, GLuint, GLint); + PFNFRAMEBUFFERTEXTURE2D FramebufferTexture2D = 0; + typedef void (CODEGEN_FUNCPTR *PFNFRAMEBUFFERTEXTURE3D)(GLenum, GLenum, GLenum, GLuint, GLint, GLint); + PFNFRAMEBUFFERTEXTURE3D FramebufferTexture3D = 0; + typedef void (CODEGEN_FUNCPTR *PFNFRAMEBUFFERTEXTURELAYER)(GLenum, GLenum, GLuint, GLint, GLint); + PFNFRAMEBUFFERTEXTURELAYER FramebufferTextureLayer = 0; + typedef void (CODEGEN_FUNCPTR *PFNGENFRAMEBUFFERS)(GLsizei, GLuint *); + PFNGENFRAMEBUFFERS GenFramebuffers = 0; + typedef void (CODEGEN_FUNCPTR *PFNGENRENDERBUFFERS)(GLsizei, GLuint *); + PFNGENRENDERBUFFERS GenRenderbuffers = 0; + typedef void (CODEGEN_FUNCPTR *PFNGENVERTEXARRAYS)(GLsizei, GLuint *); + PFNGENVERTEXARRAYS GenVertexArrays = 0; + typedef void (CODEGEN_FUNCPTR *PFNGENERATEMIPMAP)(GLenum); + PFNGENERATEMIPMAP GenerateMipmap = 0; + typedef void (CODEGEN_FUNCPTR *PFNGETBOOLEANI_V)(GLenum, GLuint, GLboolean *); + PFNGETBOOLEANI_V GetBooleani_v = 0; + typedef GLint (CODEGEN_FUNCPTR *PFNGETFRAGDATALOCATION)(GLuint, const GLchar *); + PFNGETFRAGDATALOCATION GetFragDataLocation = 0; + typedef void (CODEGEN_FUNCPTR *PFNGETFRAMEBUFFERATTACHMENTPARAMETERIV)(GLenum, GLenum, GLenum, GLint *); + PFNGETFRAMEBUFFERATTACHMENTPARAMETERIV GetFramebufferAttachmentParameteriv = 0; + typedef void (CODEGEN_FUNCPTR *PFNGETINTEGERI_V)(GLenum, GLuint, GLint *); + PFNGETINTEGERI_V GetIntegeri_v = 0; + typedef void (CODEGEN_FUNCPTR *PFNGETRENDERBUFFERPARAMETERIV)(GLenum, GLenum, GLint *); + PFNGETRENDERBUFFERPARAMETERIV GetRenderbufferParameteriv = 0; + typedef const GLubyte * (CODEGEN_FUNCPTR *PFNGETSTRINGI)(GLenum, GLuint); + PFNGETSTRINGI GetStringi = 0; + typedef void (CODEGEN_FUNCPTR *PFNGETTEXPARAMETERIIV)(GLenum, GLenum, GLint *); + PFNGETTEXPARAMETERIIV GetTexParameterIiv = 0; + typedef void (CODEGEN_FUNCPTR *PFNGETTEXPARAMETERIUIV)(GLenum, GLenum, GLuint *); + PFNGETTEXPARAMETERIUIV GetTexParameterIuiv = 0; + typedef void (CODEGEN_FUNCPTR *PFNGETTRANSFORMFEEDBACKVARYING)(GLuint, GLuint, GLsizei, GLsizei *, GLsizei *, GLenum *, GLchar *); + PFNGETTRANSFORMFEEDBACKVARYING GetTransformFeedbackVarying = 0; + typedef void (CODEGEN_FUNCPTR *PFNGETUNIFORMUIV)(GLuint, GLint, GLuint *); + PFNGETUNIFORMUIV GetUniformuiv = 0; + typedef void (CODEGEN_FUNCPTR *PFNGETVERTEXATTRIBIIV)(GLuint, GLenum, GLint *); + PFNGETVERTEXATTRIBIIV GetVertexAttribIiv = 0; + typedef void (CODEGEN_FUNCPTR *PFNGETVERTEXATTRIBIUIV)(GLuint, GLenum, GLuint *); + PFNGETVERTEXATTRIBIUIV GetVertexAttribIuiv = 0; + typedef GLboolean (CODEGEN_FUNCPTR *PFNISENABLEDI)(GLenum, GLuint); + PFNISENABLEDI IsEnabledi = 0; + typedef GLboolean (CODEGEN_FUNCPTR *PFNISFRAMEBUFFER)(GLuint); + PFNISFRAMEBUFFER IsFramebuffer = 0; + typedef GLboolean (CODEGEN_FUNCPTR *PFNISRENDERBUFFER)(GLuint); + PFNISRENDERBUFFER IsRenderbuffer = 0; + typedef GLboolean (CODEGEN_FUNCPTR *PFNISVERTEXARRAY)(GLuint); + PFNISVERTEXARRAY IsVertexArray = 0; + typedef void * (CODEGEN_FUNCPTR *PFNMAPBUFFERRANGE)(GLenum, GLintptr, GLsizeiptr, GLbitfield); + PFNMAPBUFFERRANGE MapBufferRange = 0; + typedef void (CODEGEN_FUNCPTR *PFNRENDERBUFFERSTORAGE)(GLenum, GLenum, GLsizei, GLsizei); + PFNRENDERBUFFERSTORAGE RenderbufferStorage = 0; + typedef void (CODEGEN_FUNCPTR *PFNRENDERBUFFERSTORAGEMULTISAMPLE)(GLenum, GLsizei, GLenum, GLsizei, GLsizei); + PFNRENDERBUFFERSTORAGEMULTISAMPLE RenderbufferStorageMultisample = 0; + typedef void (CODEGEN_FUNCPTR *PFNTEXPARAMETERIIV)(GLenum, GLenum, const GLint *); + PFNTEXPARAMETERIIV TexParameterIiv = 0; + typedef void (CODEGEN_FUNCPTR *PFNTEXPARAMETERIUIV)(GLenum, GLenum, const GLuint *); + PFNTEXPARAMETERIUIV TexParameterIuiv = 0; + typedef void (CODEGEN_FUNCPTR *PFNTRANSFORMFEEDBACKVARYINGS)(GLuint, GLsizei, const GLchar *const*, GLenum); + PFNTRANSFORMFEEDBACKVARYINGS TransformFeedbackVaryings = 0; + typedef void (CODEGEN_FUNCPTR *PFNUNIFORM1UI)(GLint, GLuint); + PFNUNIFORM1UI Uniform1ui = 0; + typedef void (CODEGEN_FUNCPTR *PFNUNIFORM1UIV)(GLint, GLsizei, const GLuint *); + PFNUNIFORM1UIV Uniform1uiv = 0; + typedef void (CODEGEN_FUNCPTR *PFNUNIFORM2UI)(GLint, GLuint, GLuint); + PFNUNIFORM2UI Uniform2ui = 0; + typedef void (CODEGEN_FUNCPTR *PFNUNIFORM2UIV)(GLint, GLsizei, const GLuint *); + PFNUNIFORM2UIV Uniform2uiv = 0; + typedef void (CODEGEN_FUNCPTR *PFNUNIFORM3UI)(GLint, GLuint, GLuint, GLuint); + PFNUNIFORM3UI Uniform3ui = 0; + typedef void (CODEGEN_FUNCPTR *PFNUNIFORM3UIV)(GLint, GLsizei, const GLuint *); + PFNUNIFORM3UIV Uniform3uiv = 0; + typedef void (CODEGEN_FUNCPTR *PFNUNIFORM4UI)(GLint, GLuint, GLuint, GLuint, GLuint); + PFNUNIFORM4UI Uniform4ui = 0; + typedef void (CODEGEN_FUNCPTR *PFNUNIFORM4UIV)(GLint, GLsizei, const GLuint *); + PFNUNIFORM4UIV Uniform4uiv = 0; + typedef void (CODEGEN_FUNCPTR *PFNVERTEXATTRIBI1I)(GLuint, GLint); + PFNVERTEXATTRIBI1I VertexAttribI1i = 0; + typedef void (CODEGEN_FUNCPTR *PFNVERTEXATTRIBI1IV)(GLuint, const GLint *); + PFNVERTEXATTRIBI1IV VertexAttribI1iv = 0; + typedef void (CODEGEN_FUNCPTR *PFNVERTEXATTRIBI1UI)(GLuint, GLuint); + PFNVERTEXATTRIBI1UI VertexAttribI1ui = 0; + typedef void (CODEGEN_FUNCPTR *PFNVERTEXATTRIBI1UIV)(GLuint, const GLuint *); + PFNVERTEXATTRIBI1UIV VertexAttribI1uiv = 0; + typedef void (CODEGEN_FUNCPTR *PFNVERTEXATTRIBI2I)(GLuint, GLint, GLint); + PFNVERTEXATTRIBI2I VertexAttribI2i = 0; + typedef void (CODEGEN_FUNCPTR *PFNVERTEXATTRIBI2IV)(GLuint, const GLint *); + PFNVERTEXATTRIBI2IV VertexAttribI2iv = 0; + typedef void (CODEGEN_FUNCPTR *PFNVERTEXATTRIBI2UI)(GLuint, GLuint, GLuint); + PFNVERTEXATTRIBI2UI VertexAttribI2ui = 0; + typedef void (CODEGEN_FUNCPTR *PFNVERTEXATTRIBI2UIV)(GLuint, const GLuint *); + PFNVERTEXATTRIBI2UIV VertexAttribI2uiv = 0; + typedef void (CODEGEN_FUNCPTR *PFNVERTEXATTRIBI3I)(GLuint, GLint, GLint, GLint); + PFNVERTEXATTRIBI3I VertexAttribI3i = 0; + typedef void (CODEGEN_FUNCPTR *PFNVERTEXATTRIBI3IV)(GLuint, const GLint *); + PFNVERTEXATTRIBI3IV VertexAttribI3iv = 0; + typedef void (CODEGEN_FUNCPTR *PFNVERTEXATTRIBI3UI)(GLuint, GLuint, GLuint, GLuint); + PFNVERTEXATTRIBI3UI VertexAttribI3ui = 0; + typedef void (CODEGEN_FUNCPTR *PFNVERTEXATTRIBI3UIV)(GLuint, const GLuint *); + PFNVERTEXATTRIBI3UIV VertexAttribI3uiv = 0; + typedef void (CODEGEN_FUNCPTR *PFNVERTEXATTRIBI4BV)(GLuint, const GLbyte *); + PFNVERTEXATTRIBI4BV VertexAttribI4bv = 0; + typedef void (CODEGEN_FUNCPTR *PFNVERTEXATTRIBI4I)(GLuint, GLint, GLint, GLint, GLint); + PFNVERTEXATTRIBI4I VertexAttribI4i = 0; + typedef void (CODEGEN_FUNCPTR *PFNVERTEXATTRIBI4IV)(GLuint, const GLint *); + PFNVERTEXATTRIBI4IV VertexAttribI4iv = 0; + typedef void (CODEGEN_FUNCPTR *PFNVERTEXATTRIBI4SV)(GLuint, const GLshort *); + PFNVERTEXATTRIBI4SV VertexAttribI4sv = 0; + typedef void (CODEGEN_FUNCPTR *PFNVERTEXATTRIBI4UBV)(GLuint, const GLubyte *); + PFNVERTEXATTRIBI4UBV VertexAttribI4ubv = 0; + typedef void (CODEGEN_FUNCPTR *PFNVERTEXATTRIBI4UI)(GLuint, GLuint, GLuint, GLuint, GLuint); + PFNVERTEXATTRIBI4UI VertexAttribI4ui = 0; + typedef void (CODEGEN_FUNCPTR *PFNVERTEXATTRIBI4UIV)(GLuint, const GLuint *); + PFNVERTEXATTRIBI4UIV VertexAttribI4uiv = 0; + typedef void (CODEGEN_FUNCPTR *PFNVERTEXATTRIBI4USV)(GLuint, const GLushort *); + PFNVERTEXATTRIBI4USV VertexAttribI4usv = 0; + typedef void (CODEGEN_FUNCPTR *PFNVERTEXATTRIBIPOINTER)(GLuint, GLint, GLenum, GLsizei, const void *); + PFNVERTEXATTRIBIPOINTER VertexAttribIPointer = 0; + + typedef void (CODEGEN_FUNCPTR *PFNCOPYBUFFERSUBDATA)(GLenum, GLenum, GLintptr, GLintptr, GLsizeiptr); + PFNCOPYBUFFERSUBDATA CopyBufferSubData = 0; + typedef void (CODEGEN_FUNCPTR *PFNDRAWARRAYSINSTANCED)(GLenum, GLint, GLsizei, GLsizei); + PFNDRAWARRAYSINSTANCED DrawArraysInstanced = 0; + typedef void (CODEGEN_FUNCPTR *PFNDRAWELEMENTSINSTANCED)(GLenum, GLsizei, GLenum, const void *, GLsizei); + PFNDRAWELEMENTSINSTANCED DrawElementsInstanced = 0; + typedef void (CODEGEN_FUNCPTR *PFNGETACTIVEUNIFORMBLOCKNAME)(GLuint, GLuint, GLsizei, GLsizei *, GLchar *); + PFNGETACTIVEUNIFORMBLOCKNAME GetActiveUniformBlockName = 0; + typedef void (CODEGEN_FUNCPTR *PFNGETACTIVEUNIFORMBLOCKIV)(GLuint, GLuint, GLenum, GLint *); + PFNGETACTIVEUNIFORMBLOCKIV GetActiveUniformBlockiv = 0; + typedef void (CODEGEN_FUNCPTR *PFNGETACTIVEUNIFORMNAME)(GLuint, GLuint, GLsizei, GLsizei *, GLchar *); + PFNGETACTIVEUNIFORMNAME GetActiveUniformName = 0; + typedef void (CODEGEN_FUNCPTR *PFNGETACTIVEUNIFORMSIV)(GLuint, GLsizei, const GLuint *, GLenum, GLint *); + PFNGETACTIVEUNIFORMSIV GetActiveUniformsiv = 0; + typedef GLuint (CODEGEN_FUNCPTR *PFNGETUNIFORMBLOCKINDEX)(GLuint, const GLchar *); + PFNGETUNIFORMBLOCKINDEX GetUniformBlockIndex = 0; + typedef void (CODEGEN_FUNCPTR *PFNGETUNIFORMINDICES)(GLuint, GLsizei, const GLchar *const*, GLuint *); + PFNGETUNIFORMINDICES GetUniformIndices = 0; + typedef void (CODEGEN_FUNCPTR *PFNPRIMITIVERESTARTINDEX)(GLuint); + PFNPRIMITIVERESTARTINDEX PrimitiveRestartIndex = 0; + typedef void (CODEGEN_FUNCPTR *PFNTEXBUFFER)(GLenum, GLenum, GLuint); + PFNTEXBUFFER TexBuffer = 0; + typedef void (CODEGEN_FUNCPTR *PFNUNIFORMBLOCKBINDING)(GLuint, GLuint, GLuint); + PFNUNIFORMBLOCKBINDING UniformBlockBinding = 0; + + typedef GLenum (CODEGEN_FUNCPTR *PFNCLIENTWAITSYNC)(GLsync, GLbitfield, GLuint64); + PFNCLIENTWAITSYNC ClientWaitSync = 0; + typedef void (CODEGEN_FUNCPTR *PFNDELETESYNC)(GLsync); + PFNDELETESYNC DeleteSync = 0; + typedef void (CODEGEN_FUNCPTR *PFNDRAWELEMENTSBASEVERTEX)(GLenum, GLsizei, GLenum, const void *, GLint); + PFNDRAWELEMENTSBASEVERTEX DrawElementsBaseVertex = 0; + typedef void (CODEGEN_FUNCPTR *PFNDRAWELEMENTSINSTANCEDBASEVERTEX)(GLenum, GLsizei, GLenum, const void *, GLsizei, GLint); + PFNDRAWELEMENTSINSTANCEDBASEVERTEX DrawElementsInstancedBaseVertex = 0; + typedef void (CODEGEN_FUNCPTR *PFNDRAWRANGEELEMENTSBASEVERTEX)(GLenum, GLuint, GLuint, GLsizei, GLenum, const void *, GLint); + PFNDRAWRANGEELEMENTSBASEVERTEX DrawRangeElementsBaseVertex = 0; + typedef GLsync (CODEGEN_FUNCPTR *PFNFENCESYNC)(GLenum, GLbitfield); + PFNFENCESYNC FenceSync = 0; + typedef void (CODEGEN_FUNCPTR *PFNFRAMEBUFFERTEXTURE)(GLenum, GLenum, GLuint, GLint); + PFNFRAMEBUFFERTEXTURE FramebufferTexture = 0; + typedef void (CODEGEN_FUNCPTR *PFNGETBUFFERPARAMETERI64V)(GLenum, GLenum, GLint64 *); + PFNGETBUFFERPARAMETERI64V GetBufferParameteri64v = 0; + typedef void (CODEGEN_FUNCPTR *PFNGETINTEGER64I_V)(GLenum, GLuint, GLint64 *); + PFNGETINTEGER64I_V GetInteger64i_v = 0; + typedef void (CODEGEN_FUNCPTR *PFNGETINTEGER64V)(GLenum, GLint64 *); + PFNGETINTEGER64V GetInteger64v = 0; + typedef void (CODEGEN_FUNCPTR *PFNGETMULTISAMPLEFV)(GLenum, GLuint, GLfloat *); + PFNGETMULTISAMPLEFV GetMultisamplefv = 0; + typedef void (CODEGEN_FUNCPTR *PFNGETSYNCIV)(GLsync, GLenum, GLsizei, GLsizei *, GLint *); + PFNGETSYNCIV GetSynciv = 0; + typedef GLboolean (CODEGEN_FUNCPTR *PFNISSYNC)(GLsync); + PFNISSYNC IsSync = 0; + typedef void (CODEGEN_FUNCPTR *PFNMULTIDRAWELEMENTSBASEVERTEX)(GLenum, const GLsizei *, GLenum, const void *const*, GLsizei, const GLint *); + PFNMULTIDRAWELEMENTSBASEVERTEX MultiDrawElementsBaseVertex = 0; + typedef void (CODEGEN_FUNCPTR *PFNPROVOKINGVERTEX)(GLenum); + PFNPROVOKINGVERTEX ProvokingVertex = 0; + typedef void (CODEGEN_FUNCPTR *PFNSAMPLEMASKI)(GLuint, GLbitfield); + PFNSAMPLEMASKI SampleMaski = 0; + typedef void (CODEGEN_FUNCPTR *PFNTEXIMAGE2DMULTISAMPLE)(GLenum, GLsizei, GLenum, GLsizei, GLsizei, GLboolean); + PFNTEXIMAGE2DMULTISAMPLE TexImage2DMultisample = 0; + typedef void (CODEGEN_FUNCPTR *PFNTEXIMAGE3DMULTISAMPLE)(GLenum, GLsizei, GLenum, GLsizei, GLsizei, GLsizei, GLboolean); + PFNTEXIMAGE3DMULTISAMPLE TexImage3DMultisample = 0; + typedef void (CODEGEN_FUNCPTR *PFNWAITSYNC)(GLsync, GLbitfield, GLuint64); + PFNWAITSYNC WaitSync = 0; + + typedef void (CODEGEN_FUNCPTR *PFNBINDFRAGDATALOCATIONINDEXED)(GLuint, GLuint, GLuint, const GLchar *); + PFNBINDFRAGDATALOCATIONINDEXED BindFragDataLocationIndexed = 0; + typedef void (CODEGEN_FUNCPTR *PFNBINDSAMPLER)(GLuint, GLuint); + PFNBINDSAMPLER BindSampler = 0; + typedef void (CODEGEN_FUNCPTR *PFNDELETESAMPLERS)(GLsizei, const GLuint *); + PFNDELETESAMPLERS DeleteSamplers = 0; + typedef void (CODEGEN_FUNCPTR *PFNGENSAMPLERS)(GLsizei, GLuint *); + PFNGENSAMPLERS GenSamplers = 0; + typedef GLint (CODEGEN_FUNCPTR *PFNGETFRAGDATAINDEX)(GLuint, const GLchar *); + PFNGETFRAGDATAINDEX GetFragDataIndex = 0; + typedef void (CODEGEN_FUNCPTR *PFNGETQUERYOBJECTI64V)(GLuint, GLenum, GLint64 *); + PFNGETQUERYOBJECTI64V GetQueryObjecti64v = 0; + typedef void (CODEGEN_FUNCPTR *PFNGETQUERYOBJECTUI64V)(GLuint, GLenum, GLuint64 *); + PFNGETQUERYOBJECTUI64V GetQueryObjectui64v = 0; + typedef void (CODEGEN_FUNCPTR *PFNGETSAMPLERPARAMETERIIV)(GLuint, GLenum, GLint *); + PFNGETSAMPLERPARAMETERIIV GetSamplerParameterIiv = 0; + typedef void (CODEGEN_FUNCPTR *PFNGETSAMPLERPARAMETERIUIV)(GLuint, GLenum, GLuint *); + PFNGETSAMPLERPARAMETERIUIV GetSamplerParameterIuiv = 0; + typedef void (CODEGEN_FUNCPTR *PFNGETSAMPLERPARAMETERFV)(GLuint, GLenum, GLfloat *); + PFNGETSAMPLERPARAMETERFV GetSamplerParameterfv = 0; + typedef void (CODEGEN_FUNCPTR *PFNGETSAMPLERPARAMETERIV)(GLuint, GLenum, GLint *); + PFNGETSAMPLERPARAMETERIV GetSamplerParameteriv = 0; + typedef GLboolean (CODEGEN_FUNCPTR *PFNISSAMPLER)(GLuint); + PFNISSAMPLER IsSampler = 0; + typedef void (CODEGEN_FUNCPTR *PFNQUERYCOUNTER)(GLuint, GLenum); + PFNQUERYCOUNTER QueryCounter = 0; + typedef void (CODEGEN_FUNCPTR *PFNSAMPLERPARAMETERIIV)(GLuint, GLenum, const GLint *); + PFNSAMPLERPARAMETERIIV SamplerParameterIiv = 0; + typedef void (CODEGEN_FUNCPTR *PFNSAMPLERPARAMETERIUIV)(GLuint, GLenum, const GLuint *); + PFNSAMPLERPARAMETERIUIV SamplerParameterIuiv = 0; + typedef void (CODEGEN_FUNCPTR *PFNSAMPLERPARAMETERF)(GLuint, GLenum, GLfloat); + PFNSAMPLERPARAMETERF SamplerParameterf = 0; + typedef void (CODEGEN_FUNCPTR *PFNSAMPLERPARAMETERFV)(GLuint, GLenum, const GLfloat *); + PFNSAMPLERPARAMETERFV SamplerParameterfv = 0; + typedef void (CODEGEN_FUNCPTR *PFNSAMPLERPARAMETERI)(GLuint, GLenum, GLint); + PFNSAMPLERPARAMETERI SamplerParameteri = 0; + typedef void (CODEGEN_FUNCPTR *PFNSAMPLERPARAMETERIV)(GLuint, GLenum, const GLint *); + PFNSAMPLERPARAMETERIV SamplerParameteriv = 0; + typedef void (CODEGEN_FUNCPTR *PFNVERTEXATTRIBDIVISOR)(GLuint, GLuint); + PFNVERTEXATTRIBDIVISOR VertexAttribDivisor = 0; + typedef void (CODEGEN_FUNCPTR *PFNVERTEXATTRIBP1UI)(GLuint, GLenum, GLboolean, GLuint); + PFNVERTEXATTRIBP1UI VertexAttribP1ui = 0; + typedef void (CODEGEN_FUNCPTR *PFNVERTEXATTRIBP1UIV)(GLuint, GLenum, GLboolean, const GLuint *); + PFNVERTEXATTRIBP1UIV VertexAttribP1uiv = 0; + typedef void (CODEGEN_FUNCPTR *PFNVERTEXATTRIBP2UI)(GLuint, GLenum, GLboolean, GLuint); + PFNVERTEXATTRIBP2UI VertexAttribP2ui = 0; + typedef void (CODEGEN_FUNCPTR *PFNVERTEXATTRIBP2UIV)(GLuint, GLenum, GLboolean, const GLuint *); + PFNVERTEXATTRIBP2UIV VertexAttribP2uiv = 0; + typedef void (CODEGEN_FUNCPTR *PFNVERTEXATTRIBP3UI)(GLuint, GLenum, GLboolean, GLuint); + PFNVERTEXATTRIBP3UI VertexAttribP3ui = 0; + typedef void (CODEGEN_FUNCPTR *PFNVERTEXATTRIBP3UIV)(GLuint, GLenum, GLboolean, const GLuint *); + PFNVERTEXATTRIBP3UIV VertexAttribP3uiv = 0; + typedef void (CODEGEN_FUNCPTR *PFNVERTEXATTRIBP4UI)(GLuint, GLenum, GLboolean, GLuint); + PFNVERTEXATTRIBP4UI VertexAttribP4ui = 0; + typedef void (CODEGEN_FUNCPTR *PFNVERTEXATTRIBP4UIV)(GLuint, GLenum, GLboolean, const GLuint *); + PFNVERTEXATTRIBP4UIV VertexAttribP4uiv = 0; + + static int LoadCoreFunctions() + { + int numFailed = 0; + BlendFunc = reinterpret_cast(IntGetProcAddress("glBlendFunc")); + if(!BlendFunc) ++numFailed; + Clear = reinterpret_cast(IntGetProcAddress("glClear")); + if(!Clear) ++numFailed; + ClearColor = reinterpret_cast(IntGetProcAddress("glClearColor")); + if(!ClearColor) ++numFailed; + ClearDepth = reinterpret_cast(IntGetProcAddress("glClearDepth")); + if(!ClearDepth) ++numFailed; + ClearStencil = reinterpret_cast(IntGetProcAddress("glClearStencil")); + if(!ClearStencil) ++numFailed; + ColorMask = reinterpret_cast(IntGetProcAddress("glColorMask")); + if(!ColorMask) ++numFailed; + CullFace = reinterpret_cast(IntGetProcAddress("glCullFace")); + if(!CullFace) ++numFailed; + DepthFunc = reinterpret_cast(IntGetProcAddress("glDepthFunc")); + if(!DepthFunc) ++numFailed; + DepthMask = reinterpret_cast(IntGetProcAddress("glDepthMask")); + if(!DepthMask) ++numFailed; + DepthRange = reinterpret_cast(IntGetProcAddress("glDepthRange")); + if(!DepthRange) ++numFailed; + Disable = reinterpret_cast(IntGetProcAddress("glDisable")); + if(!Disable) ++numFailed; + DrawBuffer = reinterpret_cast(IntGetProcAddress("glDrawBuffer")); + if(!DrawBuffer) ++numFailed; + Enable = reinterpret_cast(IntGetProcAddress("glEnable")); + if(!Enable) ++numFailed; + Finish = reinterpret_cast(IntGetProcAddress("glFinish")); + if(!Finish) ++numFailed; + Flush = reinterpret_cast(IntGetProcAddress("glFlush")); + if(!Flush) ++numFailed; + FrontFace = reinterpret_cast(IntGetProcAddress("glFrontFace")); + if(!FrontFace) ++numFailed; + GetBooleanv = reinterpret_cast(IntGetProcAddress("glGetBooleanv")); + if(!GetBooleanv) ++numFailed; + GetDoublev = reinterpret_cast(IntGetProcAddress("glGetDoublev")); + if(!GetDoublev) ++numFailed; + GetError = reinterpret_cast(IntGetProcAddress("glGetError")); + if(!GetError) ++numFailed; + GetFloatv = reinterpret_cast(IntGetProcAddress("glGetFloatv")); + if(!GetFloatv) ++numFailed; + GetIntegerv = reinterpret_cast(IntGetProcAddress("glGetIntegerv")); + if(!GetIntegerv) ++numFailed; + GetString = reinterpret_cast(IntGetProcAddress("glGetString")); + if(!GetString) ++numFailed; + GetTexImage = reinterpret_cast(IntGetProcAddress("glGetTexImage")); + if(!GetTexImage) ++numFailed; + GetTexLevelParameterfv = reinterpret_cast(IntGetProcAddress("glGetTexLevelParameterfv")); + if(!GetTexLevelParameterfv) ++numFailed; + GetTexLevelParameteriv = reinterpret_cast(IntGetProcAddress("glGetTexLevelParameteriv")); + if(!GetTexLevelParameteriv) ++numFailed; + GetTexParameterfv = reinterpret_cast(IntGetProcAddress("glGetTexParameterfv")); + if(!GetTexParameterfv) ++numFailed; + GetTexParameteriv = reinterpret_cast(IntGetProcAddress("glGetTexParameteriv")); + if(!GetTexParameteriv) ++numFailed; + Hint = reinterpret_cast(IntGetProcAddress("glHint")); + if(!Hint) ++numFailed; + IsEnabled = reinterpret_cast(IntGetProcAddress("glIsEnabled")); + if(!IsEnabled) ++numFailed; + LineWidth = reinterpret_cast(IntGetProcAddress("glLineWidth")); + if(!LineWidth) ++numFailed; + LogicOp = reinterpret_cast(IntGetProcAddress("glLogicOp")); + if(!LogicOp) ++numFailed; + PixelStoref = reinterpret_cast(IntGetProcAddress("glPixelStoref")); + if(!PixelStoref) ++numFailed; + PixelStorei = reinterpret_cast(IntGetProcAddress("glPixelStorei")); + if(!PixelStorei) ++numFailed; + PointSize = reinterpret_cast(IntGetProcAddress("glPointSize")); + if(!PointSize) ++numFailed; + PolygonMode = reinterpret_cast(IntGetProcAddress("glPolygonMode")); + if(!PolygonMode) ++numFailed; + ReadBuffer = reinterpret_cast(IntGetProcAddress("glReadBuffer")); + if(!ReadBuffer) ++numFailed; + ReadPixels = reinterpret_cast(IntGetProcAddress("glReadPixels")); + if(!ReadPixels) ++numFailed; + Scissor = reinterpret_cast(IntGetProcAddress("glScissor")); + if(!Scissor) ++numFailed; + StencilFunc = reinterpret_cast(IntGetProcAddress("glStencilFunc")); + if(!StencilFunc) ++numFailed; + StencilMask = reinterpret_cast(IntGetProcAddress("glStencilMask")); + if(!StencilMask) ++numFailed; + StencilOp = reinterpret_cast(IntGetProcAddress("glStencilOp")); + if(!StencilOp) ++numFailed; + TexImage1D = reinterpret_cast(IntGetProcAddress("glTexImage1D")); + if(!TexImage1D) ++numFailed; + TexImage2D = reinterpret_cast(IntGetProcAddress("glTexImage2D")); + if(!TexImage2D) ++numFailed; + TexParameterf = reinterpret_cast(IntGetProcAddress("glTexParameterf")); + if(!TexParameterf) ++numFailed; + TexParameterfv = reinterpret_cast(IntGetProcAddress("glTexParameterfv")); + if(!TexParameterfv) ++numFailed; + TexParameteri = reinterpret_cast(IntGetProcAddress("glTexParameteri")); + if(!TexParameteri) ++numFailed; + TexParameteriv = reinterpret_cast(IntGetProcAddress("glTexParameteriv")); + if(!TexParameteriv) ++numFailed; + Viewport = reinterpret_cast(IntGetProcAddress("glViewport")); + if(!Viewport) ++numFailed; + BindTexture = reinterpret_cast(IntGetProcAddress("glBindTexture")); + if(!BindTexture) ++numFailed; + CopyTexImage1D = reinterpret_cast(IntGetProcAddress("glCopyTexImage1D")); + if(!CopyTexImage1D) ++numFailed; + CopyTexImage2D = reinterpret_cast(IntGetProcAddress("glCopyTexImage2D")); + if(!CopyTexImage2D) ++numFailed; + CopyTexSubImage1D = reinterpret_cast(IntGetProcAddress("glCopyTexSubImage1D")); + if(!CopyTexSubImage1D) ++numFailed; + CopyTexSubImage2D = reinterpret_cast(IntGetProcAddress("glCopyTexSubImage2D")); + if(!CopyTexSubImage2D) ++numFailed; + DeleteTextures = reinterpret_cast(IntGetProcAddress("glDeleteTextures")); + if(!DeleteTextures) ++numFailed; + DrawArrays = reinterpret_cast(IntGetProcAddress("glDrawArrays")); + if(!DrawArrays) ++numFailed; + DrawElements = reinterpret_cast(IntGetProcAddress("glDrawElements")); + if(!DrawElements) ++numFailed; + GenTextures = reinterpret_cast(IntGetProcAddress("glGenTextures")); + if(!GenTextures) ++numFailed; + IsTexture = reinterpret_cast(IntGetProcAddress("glIsTexture")); + if(!IsTexture) ++numFailed; + PolygonOffset = reinterpret_cast(IntGetProcAddress("glPolygonOffset")); + if(!PolygonOffset) ++numFailed; + TexSubImage1D = reinterpret_cast(IntGetProcAddress("glTexSubImage1D")); + if(!TexSubImage1D) ++numFailed; + TexSubImage2D = reinterpret_cast(IntGetProcAddress("glTexSubImage2D")); + if(!TexSubImage2D) ++numFailed; + CopyTexSubImage3D = reinterpret_cast(IntGetProcAddress("glCopyTexSubImage3D")); + if(!CopyTexSubImage3D) ++numFailed; + DrawRangeElements = reinterpret_cast(IntGetProcAddress("glDrawRangeElements")); + if(!DrawRangeElements) ++numFailed; + TexImage3D = reinterpret_cast(IntGetProcAddress("glTexImage3D")); + if(!TexImage3D) ++numFailed; + TexSubImage3D = reinterpret_cast(IntGetProcAddress("glTexSubImage3D")); + if(!TexSubImage3D) ++numFailed; + ActiveTexture = reinterpret_cast(IntGetProcAddress("glActiveTexture")); + if(!ActiveTexture) ++numFailed; + CompressedTexImage1D = reinterpret_cast(IntGetProcAddress("glCompressedTexImage1D")); + if(!CompressedTexImage1D) ++numFailed; + CompressedTexImage2D = reinterpret_cast(IntGetProcAddress("glCompressedTexImage2D")); + if(!CompressedTexImage2D) ++numFailed; + CompressedTexImage3D = reinterpret_cast(IntGetProcAddress("glCompressedTexImage3D")); + if(!CompressedTexImage3D) ++numFailed; + CompressedTexSubImage1D = reinterpret_cast(IntGetProcAddress("glCompressedTexSubImage1D")); + if(!CompressedTexSubImage1D) ++numFailed; + CompressedTexSubImage2D = reinterpret_cast(IntGetProcAddress("glCompressedTexSubImage2D")); + if(!CompressedTexSubImage2D) ++numFailed; + CompressedTexSubImage3D = reinterpret_cast(IntGetProcAddress("glCompressedTexSubImage3D")); + if(!CompressedTexSubImage3D) ++numFailed; + GetCompressedTexImage = reinterpret_cast(IntGetProcAddress("glGetCompressedTexImage")); + if(!GetCompressedTexImage) ++numFailed; + SampleCoverage = reinterpret_cast(IntGetProcAddress("glSampleCoverage")); + if(!SampleCoverage) ++numFailed; + BlendColor = reinterpret_cast(IntGetProcAddress("glBlendColor")); + if(!BlendColor) ++numFailed; + BlendEquation = reinterpret_cast(IntGetProcAddress("glBlendEquation")); + if(!BlendEquation) ++numFailed; + BlendFuncSeparate = reinterpret_cast(IntGetProcAddress("glBlendFuncSeparate")); + if(!BlendFuncSeparate) ++numFailed; + MultiDrawArrays = reinterpret_cast(IntGetProcAddress("glMultiDrawArrays")); + if(!MultiDrawArrays) ++numFailed; + MultiDrawElements = reinterpret_cast(IntGetProcAddress("glMultiDrawElements")); + if(!MultiDrawElements) ++numFailed; + PointParameterf = reinterpret_cast(IntGetProcAddress("glPointParameterf")); + if(!PointParameterf) ++numFailed; + PointParameterfv = reinterpret_cast(IntGetProcAddress("glPointParameterfv")); + if(!PointParameterfv) ++numFailed; + PointParameteri = reinterpret_cast(IntGetProcAddress("glPointParameteri")); + if(!PointParameteri) ++numFailed; + PointParameteriv = reinterpret_cast(IntGetProcAddress("glPointParameteriv")); + if(!PointParameteriv) ++numFailed; + BeginQuery = reinterpret_cast(IntGetProcAddress("glBeginQuery")); + if(!BeginQuery) ++numFailed; + BindBuffer = reinterpret_cast(IntGetProcAddress("glBindBuffer")); + if(!BindBuffer) ++numFailed; + BufferData = reinterpret_cast(IntGetProcAddress("glBufferData")); + if(!BufferData) ++numFailed; + BufferSubData = reinterpret_cast(IntGetProcAddress("glBufferSubData")); + if(!BufferSubData) ++numFailed; + DeleteBuffers = reinterpret_cast(IntGetProcAddress("glDeleteBuffers")); + if(!DeleteBuffers) ++numFailed; + DeleteQueries = reinterpret_cast(IntGetProcAddress("glDeleteQueries")); + if(!DeleteQueries) ++numFailed; + EndQuery = reinterpret_cast(IntGetProcAddress("glEndQuery")); + if(!EndQuery) ++numFailed; + GenBuffers = reinterpret_cast(IntGetProcAddress("glGenBuffers")); + if(!GenBuffers) ++numFailed; + GenQueries = reinterpret_cast(IntGetProcAddress("glGenQueries")); + if(!GenQueries) ++numFailed; + GetBufferParameteriv = reinterpret_cast(IntGetProcAddress("glGetBufferParameteriv")); + if(!GetBufferParameteriv) ++numFailed; + GetBufferPointerv = reinterpret_cast(IntGetProcAddress("glGetBufferPointerv")); + if(!GetBufferPointerv) ++numFailed; + GetBufferSubData = reinterpret_cast(IntGetProcAddress("glGetBufferSubData")); + if(!GetBufferSubData) ++numFailed; + GetQueryObjectiv = reinterpret_cast(IntGetProcAddress("glGetQueryObjectiv")); + if(!GetQueryObjectiv) ++numFailed; + GetQueryObjectuiv = reinterpret_cast(IntGetProcAddress("glGetQueryObjectuiv")); + if(!GetQueryObjectuiv) ++numFailed; + GetQueryiv = reinterpret_cast(IntGetProcAddress("glGetQueryiv")); + if(!GetQueryiv) ++numFailed; + IsBuffer = reinterpret_cast(IntGetProcAddress("glIsBuffer")); + if(!IsBuffer) ++numFailed; + IsQuery = reinterpret_cast(IntGetProcAddress("glIsQuery")); + if(!IsQuery) ++numFailed; + MapBuffer = reinterpret_cast(IntGetProcAddress("glMapBuffer")); + if(!MapBuffer) ++numFailed; + UnmapBuffer = reinterpret_cast(IntGetProcAddress("glUnmapBuffer")); + if(!UnmapBuffer) ++numFailed; + AttachShader = reinterpret_cast(IntGetProcAddress("glAttachShader")); + if(!AttachShader) ++numFailed; + BindAttribLocation = reinterpret_cast(IntGetProcAddress("glBindAttribLocation")); + if(!BindAttribLocation) ++numFailed; + BlendEquationSeparate = reinterpret_cast(IntGetProcAddress("glBlendEquationSeparate")); + if(!BlendEquationSeparate) ++numFailed; + CompileShader = reinterpret_cast(IntGetProcAddress("glCompileShader")); + if(!CompileShader) ++numFailed; + CreateProgram = reinterpret_cast(IntGetProcAddress("glCreateProgram")); + if(!CreateProgram) ++numFailed; + CreateShader = reinterpret_cast(IntGetProcAddress("glCreateShader")); + if(!CreateShader) ++numFailed; + DeleteProgram = reinterpret_cast(IntGetProcAddress("glDeleteProgram")); + if(!DeleteProgram) ++numFailed; + DeleteShader = reinterpret_cast(IntGetProcAddress("glDeleteShader")); + if(!DeleteShader) ++numFailed; + DetachShader = reinterpret_cast(IntGetProcAddress("glDetachShader")); + if(!DetachShader) ++numFailed; + DisableVertexAttribArray = reinterpret_cast(IntGetProcAddress("glDisableVertexAttribArray")); + if(!DisableVertexAttribArray) ++numFailed; + DrawBuffers = reinterpret_cast(IntGetProcAddress("glDrawBuffers")); + if(!DrawBuffers) ++numFailed; + EnableVertexAttribArray = reinterpret_cast(IntGetProcAddress("glEnableVertexAttribArray")); + if(!EnableVertexAttribArray) ++numFailed; + GetActiveAttrib = reinterpret_cast(IntGetProcAddress("glGetActiveAttrib")); + if(!GetActiveAttrib) ++numFailed; + GetActiveUniform = reinterpret_cast(IntGetProcAddress("glGetActiveUniform")); + if(!GetActiveUniform) ++numFailed; + GetAttachedShaders = reinterpret_cast(IntGetProcAddress("glGetAttachedShaders")); + if(!GetAttachedShaders) ++numFailed; + GetAttribLocation = reinterpret_cast(IntGetProcAddress("glGetAttribLocation")); + if(!GetAttribLocation) ++numFailed; + GetProgramInfoLog = reinterpret_cast(IntGetProcAddress("glGetProgramInfoLog")); + if(!GetProgramInfoLog) ++numFailed; + GetProgramiv = reinterpret_cast(IntGetProcAddress("glGetProgramiv")); + if(!GetProgramiv) ++numFailed; + GetShaderInfoLog = reinterpret_cast(IntGetProcAddress("glGetShaderInfoLog")); + if(!GetShaderInfoLog) ++numFailed; + GetShaderSource = reinterpret_cast(IntGetProcAddress("glGetShaderSource")); + if(!GetShaderSource) ++numFailed; + GetShaderiv = reinterpret_cast(IntGetProcAddress("glGetShaderiv")); + if(!GetShaderiv) ++numFailed; + GetUniformLocation = reinterpret_cast(IntGetProcAddress("glGetUniformLocation")); + if(!GetUniformLocation) ++numFailed; + GetUniformfv = reinterpret_cast(IntGetProcAddress("glGetUniformfv")); + if(!GetUniformfv) ++numFailed; + GetUniformiv = reinterpret_cast(IntGetProcAddress("glGetUniformiv")); + if(!GetUniformiv) ++numFailed; + GetVertexAttribPointerv = reinterpret_cast(IntGetProcAddress("glGetVertexAttribPointerv")); + if(!GetVertexAttribPointerv) ++numFailed; + GetVertexAttribdv = reinterpret_cast(IntGetProcAddress("glGetVertexAttribdv")); + if(!GetVertexAttribdv) ++numFailed; + GetVertexAttribfv = reinterpret_cast(IntGetProcAddress("glGetVertexAttribfv")); + if(!GetVertexAttribfv) ++numFailed; + GetVertexAttribiv = reinterpret_cast(IntGetProcAddress("glGetVertexAttribiv")); + if(!GetVertexAttribiv) ++numFailed; + IsProgram = reinterpret_cast(IntGetProcAddress("glIsProgram")); + if(!IsProgram) ++numFailed; + IsShader = reinterpret_cast(IntGetProcAddress("glIsShader")); + if(!IsShader) ++numFailed; + LinkProgram = reinterpret_cast(IntGetProcAddress("glLinkProgram")); + if(!LinkProgram) ++numFailed; + ShaderSource = reinterpret_cast(IntGetProcAddress("glShaderSource")); + if(!ShaderSource) ++numFailed; + StencilFuncSeparate = reinterpret_cast(IntGetProcAddress("glStencilFuncSeparate")); + if(!StencilFuncSeparate) ++numFailed; + StencilMaskSeparate = reinterpret_cast(IntGetProcAddress("glStencilMaskSeparate")); + if(!StencilMaskSeparate) ++numFailed; + StencilOpSeparate = reinterpret_cast(IntGetProcAddress("glStencilOpSeparate")); + if(!StencilOpSeparate) ++numFailed; + Uniform1f = reinterpret_cast(IntGetProcAddress("glUniform1f")); + if(!Uniform1f) ++numFailed; + Uniform1fv = reinterpret_cast(IntGetProcAddress("glUniform1fv")); + if(!Uniform1fv) ++numFailed; + Uniform1i = reinterpret_cast(IntGetProcAddress("glUniform1i")); + if(!Uniform1i) ++numFailed; + Uniform1iv = reinterpret_cast(IntGetProcAddress("glUniform1iv")); + if(!Uniform1iv) ++numFailed; + Uniform2f = reinterpret_cast(IntGetProcAddress("glUniform2f")); + if(!Uniform2f) ++numFailed; + Uniform2fv = reinterpret_cast(IntGetProcAddress("glUniform2fv")); + if(!Uniform2fv) ++numFailed; + Uniform2i = reinterpret_cast(IntGetProcAddress("glUniform2i")); + if(!Uniform2i) ++numFailed; + Uniform2iv = reinterpret_cast(IntGetProcAddress("glUniform2iv")); + if(!Uniform2iv) ++numFailed; + Uniform3f = reinterpret_cast(IntGetProcAddress("glUniform3f")); + if(!Uniform3f) ++numFailed; + Uniform3fv = reinterpret_cast(IntGetProcAddress("glUniform3fv")); + if(!Uniform3fv) ++numFailed; + Uniform3i = reinterpret_cast(IntGetProcAddress("glUniform3i")); + if(!Uniform3i) ++numFailed; + Uniform3iv = reinterpret_cast(IntGetProcAddress("glUniform3iv")); + if(!Uniform3iv) ++numFailed; + Uniform4f = reinterpret_cast(IntGetProcAddress("glUniform4f")); + if(!Uniform4f) ++numFailed; + Uniform4fv = reinterpret_cast(IntGetProcAddress("glUniform4fv")); + if(!Uniform4fv) ++numFailed; + Uniform4i = reinterpret_cast(IntGetProcAddress("glUniform4i")); + if(!Uniform4i) ++numFailed; + Uniform4iv = reinterpret_cast(IntGetProcAddress("glUniform4iv")); + if(!Uniform4iv) ++numFailed; + UniformMatrix2fv = reinterpret_cast(IntGetProcAddress("glUniformMatrix2fv")); + if(!UniformMatrix2fv) ++numFailed; + UniformMatrix3fv = reinterpret_cast(IntGetProcAddress("glUniformMatrix3fv")); + if(!UniformMatrix3fv) ++numFailed; + UniformMatrix4fv = reinterpret_cast(IntGetProcAddress("glUniformMatrix4fv")); + if(!UniformMatrix4fv) ++numFailed; + UseProgram = reinterpret_cast(IntGetProcAddress("glUseProgram")); + if(!UseProgram) ++numFailed; + ValidateProgram = reinterpret_cast(IntGetProcAddress("glValidateProgram")); + if(!ValidateProgram) ++numFailed; + VertexAttrib1d = reinterpret_cast(IntGetProcAddress("glVertexAttrib1d")); + if(!VertexAttrib1d) ++numFailed; + VertexAttrib1dv = reinterpret_cast(IntGetProcAddress("glVertexAttrib1dv")); + if(!VertexAttrib1dv) ++numFailed; + VertexAttrib1f = reinterpret_cast(IntGetProcAddress("glVertexAttrib1f")); + if(!VertexAttrib1f) ++numFailed; + VertexAttrib1fv = reinterpret_cast(IntGetProcAddress("glVertexAttrib1fv")); + if(!VertexAttrib1fv) ++numFailed; + VertexAttrib1s = reinterpret_cast(IntGetProcAddress("glVertexAttrib1s")); + if(!VertexAttrib1s) ++numFailed; + VertexAttrib1sv = reinterpret_cast(IntGetProcAddress("glVertexAttrib1sv")); + if(!VertexAttrib1sv) ++numFailed; + VertexAttrib2d = reinterpret_cast(IntGetProcAddress("glVertexAttrib2d")); + if(!VertexAttrib2d) ++numFailed; + VertexAttrib2dv = reinterpret_cast(IntGetProcAddress("glVertexAttrib2dv")); + if(!VertexAttrib2dv) ++numFailed; + VertexAttrib2f = reinterpret_cast(IntGetProcAddress("glVertexAttrib2f")); + if(!VertexAttrib2f) ++numFailed; + VertexAttrib2fv = reinterpret_cast(IntGetProcAddress("glVertexAttrib2fv")); + if(!VertexAttrib2fv) ++numFailed; + VertexAttrib2s = reinterpret_cast(IntGetProcAddress("glVertexAttrib2s")); + if(!VertexAttrib2s) ++numFailed; + VertexAttrib2sv = reinterpret_cast(IntGetProcAddress("glVertexAttrib2sv")); + if(!VertexAttrib2sv) ++numFailed; + VertexAttrib3d = reinterpret_cast(IntGetProcAddress("glVertexAttrib3d")); + if(!VertexAttrib3d) ++numFailed; + VertexAttrib3dv = reinterpret_cast(IntGetProcAddress("glVertexAttrib3dv")); + if(!VertexAttrib3dv) ++numFailed; + VertexAttrib3f = reinterpret_cast(IntGetProcAddress("glVertexAttrib3f")); + if(!VertexAttrib3f) ++numFailed; + VertexAttrib3fv = reinterpret_cast(IntGetProcAddress("glVertexAttrib3fv")); + if(!VertexAttrib3fv) ++numFailed; + VertexAttrib3s = reinterpret_cast(IntGetProcAddress("glVertexAttrib3s")); + if(!VertexAttrib3s) ++numFailed; + VertexAttrib3sv = reinterpret_cast(IntGetProcAddress("glVertexAttrib3sv")); + if(!VertexAttrib3sv) ++numFailed; + VertexAttrib4Nbv = reinterpret_cast(IntGetProcAddress("glVertexAttrib4Nbv")); + if(!VertexAttrib4Nbv) ++numFailed; + VertexAttrib4Niv = reinterpret_cast(IntGetProcAddress("glVertexAttrib4Niv")); + if(!VertexAttrib4Niv) ++numFailed; + VertexAttrib4Nsv = reinterpret_cast(IntGetProcAddress("glVertexAttrib4Nsv")); + if(!VertexAttrib4Nsv) ++numFailed; + VertexAttrib4Nub = reinterpret_cast(IntGetProcAddress("glVertexAttrib4Nub")); + if(!VertexAttrib4Nub) ++numFailed; + VertexAttrib4Nubv = reinterpret_cast(IntGetProcAddress("glVertexAttrib4Nubv")); + if(!VertexAttrib4Nubv) ++numFailed; + VertexAttrib4Nuiv = reinterpret_cast(IntGetProcAddress("glVertexAttrib4Nuiv")); + if(!VertexAttrib4Nuiv) ++numFailed; + VertexAttrib4Nusv = reinterpret_cast(IntGetProcAddress("glVertexAttrib4Nusv")); + if(!VertexAttrib4Nusv) ++numFailed; + VertexAttrib4bv = reinterpret_cast(IntGetProcAddress("glVertexAttrib4bv")); + if(!VertexAttrib4bv) ++numFailed; + VertexAttrib4d = reinterpret_cast(IntGetProcAddress("glVertexAttrib4d")); + if(!VertexAttrib4d) ++numFailed; + VertexAttrib4dv = reinterpret_cast(IntGetProcAddress("glVertexAttrib4dv")); + if(!VertexAttrib4dv) ++numFailed; + VertexAttrib4f = reinterpret_cast(IntGetProcAddress("glVertexAttrib4f")); + if(!VertexAttrib4f) ++numFailed; + VertexAttrib4fv = reinterpret_cast(IntGetProcAddress("glVertexAttrib4fv")); + if(!VertexAttrib4fv) ++numFailed; + VertexAttrib4iv = reinterpret_cast(IntGetProcAddress("glVertexAttrib4iv")); + if(!VertexAttrib4iv) ++numFailed; + VertexAttrib4s = reinterpret_cast(IntGetProcAddress("glVertexAttrib4s")); + if(!VertexAttrib4s) ++numFailed; + VertexAttrib4sv = reinterpret_cast(IntGetProcAddress("glVertexAttrib4sv")); + if(!VertexAttrib4sv) ++numFailed; + VertexAttrib4ubv = reinterpret_cast(IntGetProcAddress("glVertexAttrib4ubv")); + if(!VertexAttrib4ubv) ++numFailed; + VertexAttrib4uiv = reinterpret_cast(IntGetProcAddress("glVertexAttrib4uiv")); + if(!VertexAttrib4uiv) ++numFailed; + VertexAttrib4usv = reinterpret_cast(IntGetProcAddress("glVertexAttrib4usv")); + if(!VertexAttrib4usv) ++numFailed; + VertexAttribPointer = reinterpret_cast(IntGetProcAddress("glVertexAttribPointer")); + if(!VertexAttribPointer) ++numFailed; + UniformMatrix2x3fv = reinterpret_cast(IntGetProcAddress("glUniformMatrix2x3fv")); + if(!UniformMatrix2x3fv) ++numFailed; + UniformMatrix2x4fv = reinterpret_cast(IntGetProcAddress("glUniformMatrix2x4fv")); + if(!UniformMatrix2x4fv) ++numFailed; + UniformMatrix3x2fv = reinterpret_cast(IntGetProcAddress("glUniformMatrix3x2fv")); + if(!UniformMatrix3x2fv) ++numFailed; + UniformMatrix3x4fv = reinterpret_cast(IntGetProcAddress("glUniformMatrix3x4fv")); + if(!UniformMatrix3x4fv) ++numFailed; + UniformMatrix4x2fv = reinterpret_cast(IntGetProcAddress("glUniformMatrix4x2fv")); + if(!UniformMatrix4x2fv) ++numFailed; + UniformMatrix4x3fv = reinterpret_cast(IntGetProcAddress("glUniformMatrix4x3fv")); + if(!UniformMatrix4x3fv) ++numFailed; + BeginConditionalRender = reinterpret_cast(IntGetProcAddress("glBeginConditionalRender")); + if(!BeginConditionalRender) ++numFailed; + BeginTransformFeedback = reinterpret_cast(IntGetProcAddress("glBeginTransformFeedback")); + if(!BeginTransformFeedback) ++numFailed; + BindBufferBase = reinterpret_cast(IntGetProcAddress("glBindBufferBase")); + if(!BindBufferBase) ++numFailed; + BindBufferRange = reinterpret_cast(IntGetProcAddress("glBindBufferRange")); + if(!BindBufferRange) ++numFailed; + BindFragDataLocation = reinterpret_cast(IntGetProcAddress("glBindFragDataLocation")); + if(!BindFragDataLocation) ++numFailed; + BindFramebuffer = reinterpret_cast(IntGetProcAddress("glBindFramebuffer")); + if(!BindFramebuffer) ++numFailed; + BindRenderbuffer = reinterpret_cast(IntGetProcAddress("glBindRenderbuffer")); + if(!BindRenderbuffer) ++numFailed; + BindVertexArray = reinterpret_cast(IntGetProcAddress("glBindVertexArray")); + if(!BindVertexArray) ++numFailed; + BlitFramebuffer = reinterpret_cast(IntGetProcAddress("glBlitFramebuffer")); + if(!BlitFramebuffer) ++numFailed; + CheckFramebufferStatus = reinterpret_cast(IntGetProcAddress("glCheckFramebufferStatus")); + if(!CheckFramebufferStatus) ++numFailed; + ClampColor = reinterpret_cast(IntGetProcAddress("glClampColor")); + if(!ClampColor) ++numFailed; + ClearBufferfi = reinterpret_cast(IntGetProcAddress("glClearBufferfi")); + if(!ClearBufferfi) ++numFailed; + ClearBufferfv = reinterpret_cast(IntGetProcAddress("glClearBufferfv")); + if(!ClearBufferfv) ++numFailed; + ClearBufferiv = reinterpret_cast(IntGetProcAddress("glClearBufferiv")); + if(!ClearBufferiv) ++numFailed; + ClearBufferuiv = reinterpret_cast(IntGetProcAddress("glClearBufferuiv")); + if(!ClearBufferuiv) ++numFailed; + ColorMaski = reinterpret_cast(IntGetProcAddress("glColorMaski")); + if(!ColorMaski) ++numFailed; + DeleteFramebuffers = reinterpret_cast(IntGetProcAddress("glDeleteFramebuffers")); + if(!DeleteFramebuffers) ++numFailed; + DeleteRenderbuffers = reinterpret_cast(IntGetProcAddress("glDeleteRenderbuffers")); + if(!DeleteRenderbuffers) ++numFailed; + DeleteVertexArrays = reinterpret_cast(IntGetProcAddress("glDeleteVertexArrays")); + if(!DeleteVertexArrays) ++numFailed; + Disablei = reinterpret_cast(IntGetProcAddress("glDisablei")); + if(!Disablei) ++numFailed; + Enablei = reinterpret_cast(IntGetProcAddress("glEnablei")); + if(!Enablei) ++numFailed; + EndConditionalRender = reinterpret_cast(IntGetProcAddress("glEndConditionalRender")); + if(!EndConditionalRender) ++numFailed; + EndTransformFeedback = reinterpret_cast(IntGetProcAddress("glEndTransformFeedback")); + if(!EndTransformFeedback) ++numFailed; + FlushMappedBufferRange = reinterpret_cast(IntGetProcAddress("glFlushMappedBufferRange")); + if(!FlushMappedBufferRange) ++numFailed; + FramebufferRenderbuffer = reinterpret_cast(IntGetProcAddress("glFramebufferRenderbuffer")); + if(!FramebufferRenderbuffer) ++numFailed; + FramebufferTexture1D = reinterpret_cast(IntGetProcAddress("glFramebufferTexture1D")); + if(!FramebufferTexture1D) ++numFailed; + FramebufferTexture2D = reinterpret_cast(IntGetProcAddress("glFramebufferTexture2D")); + if(!FramebufferTexture2D) ++numFailed; + FramebufferTexture3D = reinterpret_cast(IntGetProcAddress("glFramebufferTexture3D")); + if(!FramebufferTexture3D) ++numFailed; + FramebufferTextureLayer = reinterpret_cast(IntGetProcAddress("glFramebufferTextureLayer")); + if(!FramebufferTextureLayer) ++numFailed; + GenFramebuffers = reinterpret_cast(IntGetProcAddress("glGenFramebuffers")); + if(!GenFramebuffers) ++numFailed; + GenRenderbuffers = reinterpret_cast(IntGetProcAddress("glGenRenderbuffers")); + if(!GenRenderbuffers) ++numFailed; + GenVertexArrays = reinterpret_cast(IntGetProcAddress("glGenVertexArrays")); + if(!GenVertexArrays) ++numFailed; + GenerateMipmap = reinterpret_cast(IntGetProcAddress("glGenerateMipmap")); + if(!GenerateMipmap) ++numFailed; + GetBooleani_v = reinterpret_cast(IntGetProcAddress("glGetBooleani_v")); + if(!GetBooleani_v) ++numFailed; + GetFragDataLocation = reinterpret_cast(IntGetProcAddress("glGetFragDataLocation")); + if(!GetFragDataLocation) ++numFailed; + GetFramebufferAttachmentParameteriv = reinterpret_cast(IntGetProcAddress("glGetFramebufferAttachmentParameteriv")); + if(!GetFramebufferAttachmentParameteriv) ++numFailed; + GetIntegeri_v = reinterpret_cast(IntGetProcAddress("glGetIntegeri_v")); + if(!GetIntegeri_v) ++numFailed; + GetRenderbufferParameteriv = reinterpret_cast(IntGetProcAddress("glGetRenderbufferParameteriv")); + if(!GetRenderbufferParameteriv) ++numFailed; + GetStringi = reinterpret_cast(IntGetProcAddress("glGetStringi")); + if(!GetStringi) ++numFailed; + GetTexParameterIiv = reinterpret_cast(IntGetProcAddress("glGetTexParameterIiv")); + if(!GetTexParameterIiv) ++numFailed; + GetTexParameterIuiv = reinterpret_cast(IntGetProcAddress("glGetTexParameterIuiv")); + if(!GetTexParameterIuiv) ++numFailed; + GetTransformFeedbackVarying = reinterpret_cast(IntGetProcAddress("glGetTransformFeedbackVarying")); + if(!GetTransformFeedbackVarying) ++numFailed; + GetUniformuiv = reinterpret_cast(IntGetProcAddress("glGetUniformuiv")); + if(!GetUniformuiv) ++numFailed; + GetVertexAttribIiv = reinterpret_cast(IntGetProcAddress("glGetVertexAttribIiv")); + if(!GetVertexAttribIiv) ++numFailed; + GetVertexAttribIuiv = reinterpret_cast(IntGetProcAddress("glGetVertexAttribIuiv")); + if(!GetVertexAttribIuiv) ++numFailed; + IsEnabledi = reinterpret_cast(IntGetProcAddress("glIsEnabledi")); + if(!IsEnabledi) ++numFailed; + IsFramebuffer = reinterpret_cast(IntGetProcAddress("glIsFramebuffer")); + if(!IsFramebuffer) ++numFailed; + IsRenderbuffer = reinterpret_cast(IntGetProcAddress("glIsRenderbuffer")); + if(!IsRenderbuffer) ++numFailed; + IsVertexArray = reinterpret_cast(IntGetProcAddress("glIsVertexArray")); + if(!IsVertexArray) ++numFailed; + MapBufferRange = reinterpret_cast(IntGetProcAddress("glMapBufferRange")); + if(!MapBufferRange) ++numFailed; + RenderbufferStorage = reinterpret_cast(IntGetProcAddress("glRenderbufferStorage")); + if(!RenderbufferStorage) ++numFailed; + RenderbufferStorageMultisample = reinterpret_cast(IntGetProcAddress("glRenderbufferStorageMultisample")); + if(!RenderbufferStorageMultisample) ++numFailed; + TexParameterIiv = reinterpret_cast(IntGetProcAddress("glTexParameterIiv")); + if(!TexParameterIiv) ++numFailed; + TexParameterIuiv = reinterpret_cast(IntGetProcAddress("glTexParameterIuiv")); + if(!TexParameterIuiv) ++numFailed; + TransformFeedbackVaryings = reinterpret_cast(IntGetProcAddress("glTransformFeedbackVaryings")); + if(!TransformFeedbackVaryings) ++numFailed; + Uniform1ui = reinterpret_cast(IntGetProcAddress("glUniform1ui")); + if(!Uniform1ui) ++numFailed; + Uniform1uiv = reinterpret_cast(IntGetProcAddress("glUniform1uiv")); + if(!Uniform1uiv) ++numFailed; + Uniform2ui = reinterpret_cast(IntGetProcAddress("glUniform2ui")); + if(!Uniform2ui) ++numFailed; + Uniform2uiv = reinterpret_cast(IntGetProcAddress("glUniform2uiv")); + if(!Uniform2uiv) ++numFailed; + Uniform3ui = reinterpret_cast(IntGetProcAddress("glUniform3ui")); + if(!Uniform3ui) ++numFailed; + Uniform3uiv = reinterpret_cast(IntGetProcAddress("glUniform3uiv")); + if(!Uniform3uiv) ++numFailed; + Uniform4ui = reinterpret_cast(IntGetProcAddress("glUniform4ui")); + if(!Uniform4ui) ++numFailed; + Uniform4uiv = reinterpret_cast(IntGetProcAddress("glUniform4uiv")); + if(!Uniform4uiv) ++numFailed; + VertexAttribI1i = reinterpret_cast(IntGetProcAddress("glVertexAttribI1i")); + if(!VertexAttribI1i) ++numFailed; + VertexAttribI1iv = reinterpret_cast(IntGetProcAddress("glVertexAttribI1iv")); + if(!VertexAttribI1iv) ++numFailed; + VertexAttribI1ui = reinterpret_cast(IntGetProcAddress("glVertexAttribI1ui")); + if(!VertexAttribI1ui) ++numFailed; + VertexAttribI1uiv = reinterpret_cast(IntGetProcAddress("glVertexAttribI1uiv")); + if(!VertexAttribI1uiv) ++numFailed; + VertexAttribI2i = reinterpret_cast(IntGetProcAddress("glVertexAttribI2i")); + if(!VertexAttribI2i) ++numFailed; + VertexAttribI2iv = reinterpret_cast(IntGetProcAddress("glVertexAttribI2iv")); + if(!VertexAttribI2iv) ++numFailed; + VertexAttribI2ui = reinterpret_cast(IntGetProcAddress("glVertexAttribI2ui")); + if(!VertexAttribI2ui) ++numFailed; + VertexAttribI2uiv = reinterpret_cast(IntGetProcAddress("glVertexAttribI2uiv")); + if(!VertexAttribI2uiv) ++numFailed; + VertexAttribI3i = reinterpret_cast(IntGetProcAddress("glVertexAttribI3i")); + if(!VertexAttribI3i) ++numFailed; + VertexAttribI3iv = reinterpret_cast(IntGetProcAddress("glVertexAttribI3iv")); + if(!VertexAttribI3iv) ++numFailed; + VertexAttribI3ui = reinterpret_cast(IntGetProcAddress("glVertexAttribI3ui")); + if(!VertexAttribI3ui) ++numFailed; + VertexAttribI3uiv = reinterpret_cast(IntGetProcAddress("glVertexAttribI3uiv")); + if(!VertexAttribI3uiv) ++numFailed; + VertexAttribI4bv = reinterpret_cast(IntGetProcAddress("glVertexAttribI4bv")); + if(!VertexAttribI4bv) ++numFailed; + VertexAttribI4i = reinterpret_cast(IntGetProcAddress("glVertexAttribI4i")); + if(!VertexAttribI4i) ++numFailed; + VertexAttribI4iv = reinterpret_cast(IntGetProcAddress("glVertexAttribI4iv")); + if(!VertexAttribI4iv) ++numFailed; + VertexAttribI4sv = reinterpret_cast(IntGetProcAddress("glVertexAttribI4sv")); + if(!VertexAttribI4sv) ++numFailed; + VertexAttribI4ubv = reinterpret_cast(IntGetProcAddress("glVertexAttribI4ubv")); + if(!VertexAttribI4ubv) ++numFailed; + VertexAttribI4ui = reinterpret_cast(IntGetProcAddress("glVertexAttribI4ui")); + if(!VertexAttribI4ui) ++numFailed; + VertexAttribI4uiv = reinterpret_cast(IntGetProcAddress("glVertexAttribI4uiv")); + if(!VertexAttribI4uiv) ++numFailed; + VertexAttribI4usv = reinterpret_cast(IntGetProcAddress("glVertexAttribI4usv")); + if(!VertexAttribI4usv) ++numFailed; + VertexAttribIPointer = reinterpret_cast(IntGetProcAddress("glVertexAttribIPointer")); + if(!VertexAttribIPointer) ++numFailed; + CopyBufferSubData = reinterpret_cast(IntGetProcAddress("glCopyBufferSubData")); + if(!CopyBufferSubData) ++numFailed; + DrawArraysInstanced = reinterpret_cast(IntGetProcAddress("glDrawArraysInstanced")); + if(!DrawArraysInstanced) ++numFailed; + DrawElementsInstanced = reinterpret_cast(IntGetProcAddress("glDrawElementsInstanced")); + if(!DrawElementsInstanced) ++numFailed; + GetActiveUniformBlockName = reinterpret_cast(IntGetProcAddress("glGetActiveUniformBlockName")); + if(!GetActiveUniformBlockName) ++numFailed; + GetActiveUniformBlockiv = reinterpret_cast(IntGetProcAddress("glGetActiveUniformBlockiv")); + if(!GetActiveUniformBlockiv) ++numFailed; + GetActiveUniformName = reinterpret_cast(IntGetProcAddress("glGetActiveUniformName")); + if(!GetActiveUniformName) ++numFailed; + GetActiveUniformsiv = reinterpret_cast(IntGetProcAddress("glGetActiveUniformsiv")); + if(!GetActiveUniformsiv) ++numFailed; + GetUniformBlockIndex = reinterpret_cast(IntGetProcAddress("glGetUniformBlockIndex")); + if(!GetUniformBlockIndex) ++numFailed; + GetUniformIndices = reinterpret_cast(IntGetProcAddress("glGetUniformIndices")); + if(!GetUniformIndices) ++numFailed; + PrimitiveRestartIndex = reinterpret_cast(IntGetProcAddress("glPrimitiveRestartIndex")); + if(!PrimitiveRestartIndex) ++numFailed; + TexBuffer = reinterpret_cast(IntGetProcAddress("glTexBuffer")); + if(!TexBuffer) ++numFailed; + UniformBlockBinding = reinterpret_cast(IntGetProcAddress("glUniformBlockBinding")); + if(!UniformBlockBinding) ++numFailed; + ClientWaitSync = reinterpret_cast(IntGetProcAddress("glClientWaitSync")); + if(!ClientWaitSync) ++numFailed; + DeleteSync = reinterpret_cast(IntGetProcAddress("glDeleteSync")); + if(!DeleteSync) ++numFailed; + DrawElementsBaseVertex = reinterpret_cast(IntGetProcAddress("glDrawElementsBaseVertex")); + if(!DrawElementsBaseVertex) ++numFailed; + DrawElementsInstancedBaseVertex = reinterpret_cast(IntGetProcAddress("glDrawElementsInstancedBaseVertex")); + if(!DrawElementsInstancedBaseVertex) ++numFailed; + DrawRangeElementsBaseVertex = reinterpret_cast(IntGetProcAddress("glDrawRangeElementsBaseVertex")); + if(!DrawRangeElementsBaseVertex) ++numFailed; + FenceSync = reinterpret_cast(IntGetProcAddress("glFenceSync")); + if(!FenceSync) ++numFailed; + FramebufferTexture = reinterpret_cast(IntGetProcAddress("glFramebufferTexture")); + if(!FramebufferTexture) ++numFailed; + GetBufferParameteri64v = reinterpret_cast(IntGetProcAddress("glGetBufferParameteri64v")); + if(!GetBufferParameteri64v) ++numFailed; + GetInteger64i_v = reinterpret_cast(IntGetProcAddress("glGetInteger64i_v")); + if(!GetInteger64i_v) ++numFailed; + GetInteger64v = reinterpret_cast(IntGetProcAddress("glGetInteger64v")); + if(!GetInteger64v) ++numFailed; + GetMultisamplefv = reinterpret_cast(IntGetProcAddress("glGetMultisamplefv")); + if(!GetMultisamplefv) ++numFailed; + GetSynciv = reinterpret_cast(IntGetProcAddress("glGetSynciv")); + if(!GetSynciv) ++numFailed; + IsSync = reinterpret_cast(IntGetProcAddress("glIsSync")); + if(!IsSync) ++numFailed; + MultiDrawElementsBaseVertex = reinterpret_cast(IntGetProcAddress("glMultiDrawElementsBaseVertex")); + if(!MultiDrawElementsBaseVertex) ++numFailed; + ProvokingVertex = reinterpret_cast(IntGetProcAddress("glProvokingVertex")); + if(!ProvokingVertex) ++numFailed; + SampleMaski = reinterpret_cast(IntGetProcAddress("glSampleMaski")); + if(!SampleMaski) ++numFailed; + TexImage2DMultisample = reinterpret_cast(IntGetProcAddress("glTexImage2DMultisample")); + if(!TexImage2DMultisample) ++numFailed; + TexImage3DMultisample = reinterpret_cast(IntGetProcAddress("glTexImage3DMultisample")); + if(!TexImage3DMultisample) ++numFailed; + WaitSync = reinterpret_cast(IntGetProcAddress("glWaitSync")); + if(!WaitSync) ++numFailed; + BindFragDataLocationIndexed = reinterpret_cast(IntGetProcAddress("glBindFragDataLocationIndexed")); + if(!BindFragDataLocationIndexed) ++numFailed; + BindSampler = reinterpret_cast(IntGetProcAddress("glBindSampler")); + if(!BindSampler) ++numFailed; + DeleteSamplers = reinterpret_cast(IntGetProcAddress("glDeleteSamplers")); + if(!DeleteSamplers) ++numFailed; + GenSamplers = reinterpret_cast(IntGetProcAddress("glGenSamplers")); + if(!GenSamplers) ++numFailed; + GetFragDataIndex = reinterpret_cast(IntGetProcAddress("glGetFragDataIndex")); + if(!GetFragDataIndex) ++numFailed; + GetQueryObjecti64v = reinterpret_cast(IntGetProcAddress("glGetQueryObjecti64v")); + if(!GetQueryObjecti64v) ++numFailed; + GetQueryObjectui64v = reinterpret_cast(IntGetProcAddress("glGetQueryObjectui64v")); + if(!GetQueryObjectui64v) ++numFailed; + GetSamplerParameterIiv = reinterpret_cast(IntGetProcAddress("glGetSamplerParameterIiv")); + if(!GetSamplerParameterIiv) ++numFailed; + GetSamplerParameterIuiv = reinterpret_cast(IntGetProcAddress("glGetSamplerParameterIuiv")); + if(!GetSamplerParameterIuiv) ++numFailed; + GetSamplerParameterfv = reinterpret_cast(IntGetProcAddress("glGetSamplerParameterfv")); + if(!GetSamplerParameterfv) ++numFailed; + GetSamplerParameteriv = reinterpret_cast(IntGetProcAddress("glGetSamplerParameteriv")); + if(!GetSamplerParameteriv) ++numFailed; + IsSampler = reinterpret_cast(IntGetProcAddress("glIsSampler")); + if(!IsSampler) ++numFailed; + QueryCounter = reinterpret_cast(IntGetProcAddress("glQueryCounter")); + if(!QueryCounter) ++numFailed; + SamplerParameterIiv = reinterpret_cast(IntGetProcAddress("glSamplerParameterIiv")); + if(!SamplerParameterIiv) ++numFailed; + SamplerParameterIuiv = reinterpret_cast(IntGetProcAddress("glSamplerParameterIuiv")); + if(!SamplerParameterIuiv) ++numFailed; + SamplerParameterf = reinterpret_cast(IntGetProcAddress("glSamplerParameterf")); + if(!SamplerParameterf) ++numFailed; + SamplerParameterfv = reinterpret_cast(IntGetProcAddress("glSamplerParameterfv")); + if(!SamplerParameterfv) ++numFailed; + SamplerParameteri = reinterpret_cast(IntGetProcAddress("glSamplerParameteri")); + if(!SamplerParameteri) ++numFailed; + SamplerParameteriv = reinterpret_cast(IntGetProcAddress("glSamplerParameteriv")); + if(!SamplerParameteriv) ++numFailed; + VertexAttribDivisor = reinterpret_cast(IntGetProcAddress("glVertexAttribDivisor")); + if(!VertexAttribDivisor) ++numFailed; + VertexAttribP1ui = reinterpret_cast(IntGetProcAddress("glVertexAttribP1ui")); + if(!VertexAttribP1ui) ++numFailed; + VertexAttribP1uiv = reinterpret_cast(IntGetProcAddress("glVertexAttribP1uiv")); + if(!VertexAttribP1uiv) ++numFailed; + VertexAttribP2ui = reinterpret_cast(IntGetProcAddress("glVertexAttribP2ui")); + if(!VertexAttribP2ui) ++numFailed; + VertexAttribP2uiv = reinterpret_cast(IntGetProcAddress("glVertexAttribP2uiv")); + if(!VertexAttribP2uiv) ++numFailed; + VertexAttribP3ui = reinterpret_cast(IntGetProcAddress("glVertexAttribP3ui")); + if(!VertexAttribP3ui) ++numFailed; + VertexAttribP3uiv = reinterpret_cast(IntGetProcAddress("glVertexAttribP3uiv")); + if(!VertexAttribP3uiv) ++numFailed; + VertexAttribP4ui = reinterpret_cast(IntGetProcAddress("glVertexAttribP4ui")); + if(!VertexAttribP4ui) ++numFailed; + VertexAttribP4uiv = reinterpret_cast(IntGetProcAddress("glVertexAttribP4uiv")); + if(!VertexAttribP4uiv) ++numFailed; + return numFailed; + } + + } //namespace _detail + + namespace sys + { + namespace + { + typedef int (*PFN_LOADEXTENSION)(); + struct MapEntry + { + MapEntry(const char *_extName, exts::LoadTest *_extVariable) + : extName(_extName) + , extVariable(_extVariable) + , loaderFunc(0) + {} + + MapEntry(const char *_extName, exts::LoadTest *_extVariable, PFN_LOADEXTENSION _loaderFunc) + : extName(_extName) + , extVariable(_extVariable) + , loaderFunc(_loaderFunc) + {} + + const char *extName; + exts::LoadTest *extVariable; + PFN_LOADEXTENSION loaderFunc; + }; + + struct MapCompare + { + MapCompare(const char *test_) : test(test_) {} + bool operator()(const MapEntry &other) { return strcmp(test, other.extName) == 0; } + const char *test; + }; + + void InitializeMappingTable(std::vector &table) + { + table.reserve(0); + } + + void ClearExtensionVars() + { + } + + void LoadExtByName(std::vector &table, const char *extensionName) + { + std::vector::iterator entry = std::find_if(table.begin(), table.end(), MapCompare(extensionName)); + + if(entry != table.end()) + { + if(entry->loaderFunc) + (*entry->extVariable) = exts::LoadTest(true, entry->loaderFunc()); + else + (*entry->extVariable) = exts::LoadTest(true, 0); + } + } + } //namespace + + + namespace + { + static void ProcExtsFromExtList(std::vector &table) + { + GLint iLoop; + GLint iNumExtensions = 0; + gl::_detail::GetIntegerv(gl::NUM_EXTENSIONS, &iNumExtensions); + + for(iLoop = 0; iLoop < iNumExtensions; iLoop++) + { + const char *strExtensionName = (const char *)gl::_detail::GetStringi(gl::EXTENSIONS, iLoop); + LoadExtByName(table, strExtensionName); + } + } + + } //namespace + + exts::LoadTest LoadFunctions() + { + ClearExtensionVars(); + std::vector table; + InitializeMappingTable(table); + + _detail::GetIntegerv = reinterpret_cast<_detail::PFNGETINTEGERV>(IntGetProcAddress("glGetIntegerv")); + if(!_detail::GetIntegerv) return exts::LoadTest(); + _detail::GetStringi = reinterpret_cast<_detail::PFNGETSTRINGI>(IntGetProcAddress("glGetStringi")); + if(!_detail::GetStringi) return exts::LoadTest(); + + ProcExtsFromExtList(table); + + int numFailed = _detail::LoadCoreFunctions(); + return exts::LoadTest(true, numFailed); + } + + static int g_major_version = 0; + static int g_minor_version = 0; + + static void GetGLVersion() + { + _detail::GetIntegerv(MAJOR_VERSION, &g_major_version); + _detail::GetIntegerv(MINOR_VERSION, &g_minor_version); + } + + int GetMajorVersion() + { + if(g_major_version == 0) + GetGLVersion(); + return g_major_version; + } + + int GetMinorVersion() + { + if(g_major_version == 0) //Yes, check the major version to get the minor one. + GetGLVersion(); + return g_minor_version; + } + + bool IsVersionGEQ(int majorVersion, int minorVersion) + { + if(g_major_version == 0) + GetGLVersion(); + + if(majorVersion < g_major_version) return true; + if(majorVersion > g_major_version) return false; + if(minorVersion <= g_minor_version) return true; + return false; + } + + } //namespace sys +} //namespace gl diff --git a/libs/gfx/source/gfx/mesh.cpp b/libs/gfx/source/gfx/mesh.cpp new file mode 100644 index 00000000..15676c4f --- /dev/null +++ b/libs/gfx/source/gfx/mesh.cpp @@ -0,0 +1,129 @@ +#include + +namespace psemek::gfx +{ + + mesh mesh::null() + { + return mesh(0); + } + + mesh::mesh() + { + gl::GenVertexArrays(1, &array_); + gl::GenBuffers(1, &buffer_); + } + + mesh::mesh(mesh && other) + { + array_ = other.array_; + buffer_ = other.buffer_; + count_ = other.count_; + + other.array_ = 0; + other.buffer_ = 0; + other.count_ = 0; + } + + mesh & mesh::operator =(mesh && other) + { + if (this == &other) return *this; + + if (array_) + { + gl::DeleteVertexArrays(1, &array_); + gl::DeleteBuffers(1, &buffer_); + } + + array_ = other.array_; + buffer_ = other.buffer_; + count_ = other.count_; + + other.array_ = 0; + other.buffer_ = 0; + other.count_ = 0; + + return *this; + } + + mesh::~mesh() + { + gl::DeleteVertexArrays(1, &array_); + gl::DeleteBuffers(1, &buffer_); + } + + mesh::mesh(int) + { + array_ = 0; + buffer_ = 0; + } + + indexed_mesh indexed_mesh::null() + { + return indexed_mesh(0); + } + + indexed_mesh::indexed_mesh() + { + gl::GenVertexArrays(1, &array_); + gl::GenBuffers(1, &buffer_); + gl::GenBuffers(1, &index_buffer_); + } + + indexed_mesh::indexed_mesh(indexed_mesh && other) + { + array_ = other.array_; + buffer_ = other.buffer_; + index_buffer_ = other.index_buffer_; + count_ = other.count_; + index_type_ = other.index_type_; + + other.array_ = 0; + other.buffer_ = 0; + other.index_buffer_ = 0; + other.count_ = 0; + other.index_type_ = 0; + } + + indexed_mesh & indexed_mesh::operator =(indexed_mesh && other) + { + if (this == &other) return *this; + + if (array_) + { + gl::DeleteVertexArrays(1, &array_); + gl::DeleteBuffers(1, &buffer_); + gl::DeleteBuffers(1, &index_buffer_); + } + + array_ = other.array_; + buffer_ = other.buffer_; + index_buffer_ = other.index_buffer_; + count_ = other.count_; + index_type_ = other.index_type_; + + other.array_ = 0; + other.buffer_ = 0; + other.index_buffer_ = 0; + other.count_ = 0; + other.index_type_ = 0; + + return *this; + } + + indexed_mesh::~indexed_mesh() + { + gl::DeleteVertexArrays(1, &array_); + gl::DeleteBuffers(1, &buffer_); + gl::DeleteBuffers(1, &index_buffer_); + } + + indexed_mesh::indexed_mesh(int) + { + array_ = 0; + buffer_ = 0; + index_buffer_ = 0; + } + + +} diff --git a/libs/gfx/source/gfx/program.cpp b/libs/gfx/source/gfx/program.cpp new file mode 100644 index 00000000..7c8a344f --- /dev/null +++ b/libs/gfx/source/gfx/program.cpp @@ -0,0 +1,300 @@ +#include + +#include + +#include + +namespace psemek::gfx +{ + + void program::uniform_proxy::operator = (int i) + { + gl::Uniform1i(location_, i); + } + + void program::uniform_proxy::operator = (unsigned int u) + { + gl::Uniform1ui(location_, u); + } + + void program::uniform_proxy::operator = (float f) + { + gl::Uniform1f(location_, f); + } + + void program::uniform_proxy::operator = (geom::vector const & v) + { + gl::Uniform1i(location_, v[0]); + } + + void program::uniform_proxy::operator = (geom::vector const & v) + { + gl::Uniform2i(location_, v[0], v[1]); + } + + void program::uniform_proxy::operator = (geom::vector const & v) + { + gl::Uniform3i(location_, v[0], v[1], v[2]); + } + + void program::uniform_proxy::operator = (geom::vector const & v) + { + gl::Uniform4i(location_, v[0], v[1], v[2], v[3]); + } + + void program::uniform_proxy::operator = (geom::vector const & v) + { + gl::Uniform1ui(location_, v[0]); + } + + void program::uniform_proxy::operator = (geom::vector const & v) + { + gl::Uniform2ui(location_, v[0], v[1]); + } + + void program::uniform_proxy::operator = (geom::vector const & v) + { + gl::Uniform3ui(location_, v[0], v[1], v[2]); + } + + void program::uniform_proxy::operator = (geom::vector const & v) + { + gl::Uniform4ui(location_, v[0], v[1], v[2], v[3]); + } + + void program::uniform_proxy::operator = (geom::vector const & v) + { + gl::Uniform1f(location_, v[0]); + } + + void program::uniform_proxy::operator = (geom::vector const & v) + { + gl::Uniform2f(location_, v[0], v[1]); + } + + void program::uniform_proxy::operator = (geom::vector const & v) + { + gl::Uniform3f(location_, v[0], v[1], v[2]); + } + + void program::uniform_proxy::operator = (geom::vector const & v) + { + gl::Uniform4f(location_, v[0], v[1], v[2], v[3]); + } + + void program::uniform_proxy::operator = (geom::point const & v) + { + gl::Uniform1i(location_, v[0]); + } + + void program::uniform_proxy::operator = (geom::point const & v) + { + gl::Uniform2i(location_, v[0], v[1]); + } + + void program::uniform_proxy::operator = (geom::point const & v) + { + gl::Uniform3i(location_, v[0], v[1], v[2]); + } + + void program::uniform_proxy::operator = (geom::point const & v) + { + gl::Uniform4i(location_, v[0], v[1], v[2], v[3]); + } + + void program::uniform_proxy::operator = (geom::point const & v) + { + gl::Uniform1ui(location_, v[0]); + } + + void program::uniform_proxy::operator = (geom::point const & v) + { + gl::Uniform2ui(location_, v[0], v[1]); + } + + void program::uniform_proxy::operator = (geom::point const & v) + { + gl::Uniform3ui(location_, v[0], v[1], v[2]); + } + + void program::uniform_proxy::operator = (geom::point const & v) + { + gl::Uniform4ui(location_, v[0], v[1], v[2], v[3]); + } + + void program::uniform_proxy::operator = (geom::point const & v) + { + gl::Uniform1f(location_, v[0]); + } + + void program::uniform_proxy::operator = (geom::point const & v) + { + gl::Uniform2f(location_, v[0], v[1]); + } + + void program::uniform_proxy::operator = (geom::point const & v) + { + gl::Uniform3f(location_, v[0], v[1], v[2]); + } + + void program::uniform_proxy::operator = (geom::point const & v) + { + gl::Uniform4f(location_, v[0], v[1], v[2], v[3]); + } + + void program::uniform_proxy::operator = (geom::matrix const & m) + { + gl::UniformMatrix2fv(location_, 1, gl::TRUE_, m.coords); + } + + void program::uniform_proxy::operator = (geom::matrix const & m) + { + gl::UniformMatrix2x3fv(location_, 1, gl::TRUE_, m.coords); + } + + void program::uniform_proxy::operator = (geom::matrix const & m) + { + gl::UniformMatrix2x4fv(location_, 1, gl::TRUE_, m.coords); + } + + void program::uniform_proxy::operator = (geom::matrix const & m) + { + gl::UniformMatrix3x2fv(location_, 1, gl::TRUE_, m.coords); + } + + void program::uniform_proxy::operator = (geom::matrix const & m) + { + gl::UniformMatrix3fv(location_, 1, gl::TRUE_, m.coords); + } + + void program::uniform_proxy::operator = (geom::matrix const & m) + { + gl::UniformMatrix3x4fv(location_, 1, gl::TRUE_, m.coords); + } + + void program::uniform_proxy::operator = (geom::matrix const & m) + { + gl::UniformMatrix4x2fv(location_, 1, gl::TRUE_, m.coords); + } + + void program::uniform_proxy::operator = (geom::matrix const & m) + { + gl::UniformMatrix4x3fv(location_, 1, gl::TRUE_, m.coords); + } + + void program::uniform_proxy::operator = (geom::matrix const & m) + { + gl::UniformMatrix4fv(location_, 1, gl::TRUE_, m.coords); + } + + void program::uniform_proxy::operator = (geom::interval const & i) + { + gl::Uniform2i(location_, i.min, i.max); + } + + void program::uniform_proxy::operator = (geom::interval const & i) + { + gl::Uniform2ui(location_, i.min, i.max); + } + + void program::uniform_proxy::operator = (geom::interval const & i) + { + gl::Uniform2f(location_, i.min, i.max); + } + + static void load_shader(GLuint shader, std::string_view source) + { + char const * vert_sources[1] { source.data() }; + GLint vert_sources_len[1] { static_cast(source.size()) }; + gl::ShaderSource(shader, 1, vert_sources, vert_sources_len); + gl::CompileShader(shader); + + GLint status; + gl::GetShaderiv(shader, gl::COMPILE_STATUS, &status); + if (status != gl::TRUE_) + { + GLint log_len; + gl::GetShaderiv(shader, gl::INFO_LOG_LENGTH, &log_len); + std::unique_ptr log(new char [log_len]); + gl::GetShaderInfoLog(shader, log_len, nullptr, log.get()); + throw std::runtime_error(util::to_string("Shader compilation failed: ", log.get())); + } + } + + static void load_program(GLuint program, std::vector const & shaders) + { + for (auto s : shaders) + gl::AttachShader(program, s); + gl::LinkProgram(program); + + GLint status; + gl::GetProgramiv(program, gl::LINK_STATUS, &status); + if (status != gl::TRUE_) + { + GLint log_len; + gl::GetProgramiv(program, gl::INFO_LOG_LENGTH, &log_len); + std::unique_ptr log(new char [log_len]); + gl::GetProgramInfoLog(program, log_len, nullptr, log.get()); + throw std::runtime_error(util::to_string("Program link failed: ", log.get())); + } + + for (auto s : shaders) + gl::DetachShader(program, s); + } + + static GLuint create_program(std::vector> const & sources) + { + std::vector shaders; + for (auto const & p : sources) + { + GLuint sh = gl::CreateShader(p.first); + load_shader(sh, p.second); + } + + GLuint program = gl::CreateProgram(); + load_program(program, shaders); + + for (auto s : shaders) + gl::DeleteShader(s); + + return program; + } + + program::program(std::string_view vertex_source, std::string_view fragment_source) + { + program_ = create_program({{gl::VERTEX_SHADER, vertex_source}, {gl::FRAGMENT_SHADER, fragment_source}}); + } + + program::program(std::string_view vertex_source, std::string_view geometry_source, std::string_view fragment_source) + { + program_ = create_program({{gl::VERTEX_SHADER, vertex_source}, {gl::GEOMETRY_SHADER, geometry_source}, {gl::FRAGMENT_SHADER, fragment_source}}); + } + + GLuint program::id() const + { + return program_; + } + + void program::bind() const + { + gl::UseProgram(program_); + } + + GLint program::location(char const * name) const + { + auto it = uniforms_.find(name); + if (it == uniforms_.end()) + { + auto l = gl::GetUniformLocation(program_, name); + uniforms_[name] = l; + return l; + } + return it->second; + } + + program::uniform_proxy program::operator[] (char const * name) const + { + return {location(name)}; + } + +} diff --git a/libs/gfx/source/gfx/renderbuffer.cpp b/libs/gfx/source/gfx/renderbuffer.cpp new file mode 100644 index 00000000..9d76edd3 --- /dev/null +++ b/libs/gfx/source/gfx/renderbuffer.cpp @@ -0,0 +1,52 @@ +#include + +namespace psemek::gfx +{ + + renderbuffer::renderbuffer() + { + gl::GenRenderbuffers(1, &id_); + } + + renderbuffer::renderbuffer(renderbuffer && other) + { + id_ = other.id_; + other.id_ = 0; + } + + renderbuffer & renderbuffer::operator = (renderbuffer && other) + { + if (this == &other) return *this; + + gl::DeleteRenderbuffers(1, &id_); + id_ = other.id_; + other.id_ = 0; + return *this; + } + + renderbuffer::~renderbuffer() + { + gl::DeleteRenderbuffers(1, &id_); + } + + renderbuffer renderbuffer::null() + { + return renderbuffer(0); + } + + void renderbuffer::bind() const + { + gl::BindRenderbuffer(gl::RENDERBUFFER, id_); + } + + void renderbuffer::storage(GLenum internal_format, GLsizei width, GLsizei height) + { + bind(); + gl::RenderbufferStorage(gl::RENDERBUFFER, internal_format, width, height); + } + + renderbuffer::renderbuffer(GLuint id) + : id_(id) + {} + +} diff --git a/libs/gfx/source/gfx/texture.cpp b/libs/gfx/source/gfx/texture.cpp new file mode 100644 index 00000000..73764789 --- /dev/null +++ b/libs/gfx/source/gfx/texture.cpp @@ -0,0 +1,84 @@ +#include + +namespace psemek::gfx +{ + + texture_2d::texture_2d() + { + gl::GenTextures(1, &id_); + } + + texture_2d::texture_2d(GLuint id) + : id_(id) + {} + + texture_2d texture_2d::null() + { + return texture_2d(0); + } + + void texture_2d::bind() const + { + gl::BindTexture(gl::TEXTURE_2D, id_); + } + + texture_2d::texture_2d(texture_2d && other) + : id_(other.id_) + , width_(other.width_) + , height_(other.height_) + { + other.id_ = 0; + other.width_ = 0; + other.height_ = 0; + } + + texture_2d & texture_2d::operator = (texture_2d && other) + { + if (this == &other) return *this; + + gl::DeleteTextures(1, &id_); + id_ = other.id_; + width_ = other.width_; + height_ = other.height_; + other.id_ = 0; + other.width_ = 0; + other.height_ = 0; + + return *this; + } + + texture_2d::~texture_2d() + { + gl::DeleteTextures(1, &id_); + } + + void texture_2d::load(GLint internal_format, std::size_t width, std::size_t height, GLenum format, GLenum type, const void * data) + { + bind(); + gl::TexImage2D(gl::TEXTURE_2D, 0, internal_format, width, height, 0, format, type, data); + gl::GenerateMipmap(gl::TEXTURE_2D); + + width_ = width; + height_ = height; + } + + void texture_2d::pixels(GLenum format, GLenum type, void * data) const + { + bind(); + gl::GetTexImage(gl::TEXTURE_2D, 0, format, type, data); + } + + texture_2d texture_2d::from_data(GLint internal_format, std::size_t width, std::size_t height, GLenum format, GLenum type, const void * data) + { + texture_2d tex; + tex.load(internal_format, width, height, format, type, data); + return tex; + } + + void texture_2d::generate_mipmap() + { + bind(); + gl::GenerateMipmap(gl::TEXTURE_2D); + } + +} diff --git a/libs/pcg/CMakeLists.txt b/libs/pcg/CMakeLists.txt new file mode 100644 index 00000000..e051af16 --- /dev/null +++ b/libs/pcg/CMakeLists.txt @@ -0,0 +1,6 @@ +file(GLOB_RECURSE PSEMEK_PCG_HEADERS RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "include/*.hpp") +file(GLOB_RECURSE PSEMEK_PCG_SOURCES RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "source/*.cpp") + +add_library(pcg ${PSEMEK_PCG_HEADERS} ${PSEMEK_PCG_SOURCES}) +target_include_directories(pcg PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include") +target_link_libraries(pcg PUBLIC util geom) diff --git a/libs/pcg/include/psemek/pcg/perlin.hpp b/libs/pcg/include/psemek/pcg/perlin.hpp new file mode 100644 index 00000000..12ac55e5 --- /dev/null +++ b/libs/pcg/include/psemek/pcg/perlin.hpp @@ -0,0 +1,35 @@ +#pragma once + +#include +#include + +namespace psemek::pcg +{ + + struct perlin + { + perlin() = default; + perlin(util::basic_pixmap> grad_map); + perlin(perlin &&) = default; + + perlin & operator= (perlin &&) = default; + + std::size_t width() const + { + return grad_map_.width() - 1; + } + + std::size_t height() const + { + return grad_map_.height() - 1; + } + + // x \in [0.0 .. 1.0] + // y \in [0.0 .. 1.0] + float operator() (float x, float y) const; + + private: + util::basic_pixmap> grad_map_; + }; + +} diff --git a/libs/pcg/source/perlin.cpp b/libs/pcg/source/perlin.cpp new file mode 100644 index 00000000..0cfedda2 --- /dev/null +++ b/libs/pcg/source/perlin.cpp @@ -0,0 +1,50 @@ +#include + +#include + +#include + +namespace psemek::pcg +{ + + perlin::perlin(util::basic_pixmap> grad_map) + : grad_map_(std::move(grad_map)) + {} + + static float step(float x0, float x1, float t) + { + return x0 * (1.f - t) + x1 * t; + } + + static float smoothstep(float x0, float x1, float t) + { + float const s = t * t * (3.f - 2.f * t); + return step(x0, x1, s); + } + + float perlin::operator() (float x, float y) const + { + assert(x >= 0.f); + assert(y >= 0.f); + + assert(x <= 1.f); + assert(y <= 1.f); + + x *= width(); + y *= height(); + + int const ix = geom::clamp(std::floor(x), {0, static_cast(width()) - 1}); + int const iy = geom::clamp(std::floor(y), {0, static_cast(height()) - 1}); + + float const tx = x - ix; + float const ty = y - iy; + + float const d00 = tx * grad_map_(ix, iy)[0] + ty * grad_map_(ix, iy)[1]; + float const d10 = (tx-1.f) * grad_map_(ix+1, iy)[0] + ty * grad_map_(ix+1, iy)[1]; + float const d01 = tx * grad_map_(ix, iy+1)[0] + (ty-1.f) * grad_map_(ix, iy+1)[1]; + float const d11 = (tx-1.f) * grad_map_(ix+1, iy+1)[0] + (ty-1.f) * grad_map_(ix+1, iy+1)[1]; + + return smoothstep(smoothstep(d00, d10, tx), smoothstep(d01, d11, tx), ty); + } + +} diff --git a/libs/util/CMakeLists.txt b/libs/util/CMakeLists.txt new file mode 100644 index 00000000..43349710 --- /dev/null +++ b/libs/util/CMakeLists.txt @@ -0,0 +1,8 @@ +find_package(Threads) + +file(GLOB_RECURSE PSEMEK_UTIL_HEADERS RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "include/*.hpp") +file(GLOB_RECURSE PSEMEK_UTIL_SOURCES RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "source/*.cpp") + +add_library(util ${PSEMEK_UTIL_HEADERS} ${PSEMEK_UTIL_SOURCES}) +target_include_directories(util PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include") +target_link_libraries(util PUBLIC ${CMAKE_THREAD_LIBS_INIT}) diff --git a/libs/util/include/psemek/util/assert.hpp b/libs/util/include/psemek/util/assert.hpp new file mode 100644 index 00000000..d4c43f96 --- /dev/null +++ b/libs/util/include/psemek/util/assert.hpp @@ -0,0 +1,18 @@ +#pragma once + +#include + +#undef assert + +#ifdef PSEMEK_DEBUG +#define assert(x) ((void)(!(x) && ::psemek::util::assert_handler(#x, __FILE__, __LINE__))) +#else +#define assert(x) ((void)sizeof(x)) +#endif + +namespace psemek::util +{ + + [[noreturn]] bool assert_handler (char const * expression, char const * file, int line); + +} diff --git a/libs/util/include/psemek/util/at_scope_exit.hpp b/libs/util/include/psemek/util/at_scope_exit.hpp new file mode 100644 index 00000000..ea067679 --- /dev/null +++ b/libs/util/include/psemek/util/at_scope_exit.hpp @@ -0,0 +1,21 @@ +#pragma once + +namespace psemek::util +{ + + template + struct at_scope_exit + { + F f; + + at_scope_exit(F f) + : f(f) + {} + + ~at_scope_exit() + { + f(); + } + }; + +} diff --git a/libs/util/include/psemek/util/autoname.hpp b/libs/util/include/psemek/util/autoname.hpp new file mode 100644 index 00000000..5cf6c1d6 --- /dev/null +++ b/libs/util/include/psemek/util/autoname.hpp @@ -0,0 +1,5 @@ +#pragma once + +#define _UTIL_CAT2(x,y) x##y +#define _UTIL_CAT(x,y) _UTIL_CAT2(x,y) +#define autoname _UTIL_CAT(autonamed_,__COUNTER__) diff --git a/libs/util/include/psemek/util/blob.hpp b/libs/util/include/psemek/util/blob.hpp new file mode 100644 index 00000000..b27f12c1 --- /dev/null +++ b/libs/util/include/psemek/util/blob.hpp @@ -0,0 +1,121 @@ +#pragma once + +#include +#include +#include + +namespace psemek::util +{ + + struct blob + { + blob() = default; + blob(blob const & other); + blob(blob && other); + + blob(std::size_t size); + blob(std::size_t size, std::unique_ptr data); + blob(std::size_t size, char * data); + + blob & operator = (blob const & other); + blob & operator = (blob && other); + + ~ blob() = default; + + char * data() { return data_.get(); } + char const * data() const { return data_.get(); } + + std::size_t size() const { return size_; } + + void reset(); + std::unique_ptr release(); + + using iterator = char *; + using const_iterator = char const *; + + char * begin() { return data(); } + char const * begin() const { return data(); } + + char * end() { return data() + size(); } + char const * end() const { return data() + size(); } + + char & operator[] (std::size_t i) { return data()[i]; } + char const & operator[] (std::size_t i) const { return data()[i]; } + + std::string string() const; + std::string_view string_view() const; + + private: + std::unique_ptr data_; + std::size_t size_ = 0; + }; + + inline blob::blob(blob const & other) + { + *this = other; + } + + inline blob::blob(blob && other) + { + *this = std::move(other); + } + + inline blob::blob(std::size_t size) + : data_{new char [size]} + , size_{size} + {} + + inline blob::blob(std::size_t size, std::unique_ptr data) + : data_{std::move(data)} + , size_{size} + {} + + inline blob::blob(std::size_t size, char * data) + : data_{data} + , size_{size} + {} + + inline blob & blob::operator=(blob const & other) + { + if (this != &other) + { + data_.reset(new char [other.size()]); + std::copy(other.begin(), other.end(), begin()); + size_ = other.size(); + } + return *this; + } + + inline blob & blob::operator=(blob && other) + { + if (this != &other) + { + data_ = std::move(other.data_); + size_ = other.size(); + other.size_ = 0; + } + return *this; + } + + inline void blob::reset() + { + data_.reset(); + size_ = 0; + } + + inline std::unique_ptr blob::release() + { + size_ = 0; + return std::move(data_); + } + + inline std::string blob::string() const + { + return std::string(data_.get(), data_.get() + size_); + } + + inline std::string_view blob::string_view() const + { + return std::string_view(data_.get(), size_); + } +} diff --git a/libs/util/include/psemek/util/clock.hpp b/libs/util/include/psemek/util/clock.hpp new file mode 100644 index 00000000..2ba74f2f --- /dev/null +++ b/libs/util/include/psemek/util/clock.hpp @@ -0,0 +1,49 @@ +#pragma once + +#include + +namespace psemek::util +{ + + template , typename Clock = std::chrono::system_clock> + struct clock + { + typedef Duration duration_type; + typedef typename duration_type::rep rep_type; + + typedef Clock clock_type; + typedef typename clock_type::time_point time_point_type; + + clock ( ) + { + restart(); + } + + time_point_type now ( ) const + { + return clock_type::now(); + } + + duration_type restart ( ) + { + auto t = now(); + auto delta = t - start_; + start_ = t; + return std::chrono::duration_cast(delta); + } + + duration_type duration ( ) const + { + return std::chrono::duration_cast(now() - start_); + } + + rep_type count ( ) const + { + return duration().count(); + } + + private: + time_point_type start_; + }; + +} diff --git a/libs/util/include/psemek/util/flat_list.hpp b/libs/util/include/psemek/util/flat_list.hpp new file mode 100644 index 00000000..8c00093d --- /dev/null +++ b/libs/util/include/psemek/util/flat_list.hpp @@ -0,0 +1,77 @@ +#pragma once + +#include +#include +#include + +namespace psemek::util +{ + + template + struct flat_list + { + flat_list ( ); + explicit flat_list (std::size_t count); + flat_list (std::size_t count, T const & value); + flat_list (flat_list const &); + flat_list (flat_list &&); + flat_list (std::initializer_list init); + + ~ flat_list ( ); + + std::size_t size ( ) const; + + private: + using item = std::aligned_storage_t; + + static constexpr std::size_t nil = static_cast(-1); + + // Invariant: data_.size() >= size_ + std::vector data_; + std::size_t size_ = 0; + std::size_t first_free_ = nil; + }; + + template + flat_list::flat_list ( ) = default; + + template + flat_list::flat_list (std::size_t count) + : data_(count) + , size_(count) + { } + + template + flat_list::flat_list (std::size_t count, T const & value) + : data_(count, value) + , size_(count) + { } + + template + flat_list::flat_list (flat_list const & other) = default; + + template + flat_list::flat_list (flat_list && other) + : data_(std::move(other.data_)) + , size_(other.size_) + , first_free_(other.first_free_) + { + other.size_ = 0; + other.first_free_ = nil; + } + + template + flat_list::flat_list (std::initializer_list init) + : data_(std::move(init)) + , size_(data_.size()) + { } + + template + flat_list::~flat_list ( ) = default; + + template + std::size_t flat_list::size ( ) const + { + return size_; + } +} diff --git a/libs/util/include/psemek/util/fmap.hpp b/libs/util/include/psemek/util/fmap.hpp new file mode 100644 index 00000000..73d81957 --- /dev/null +++ b/libs/util/include/psemek/util/fmap.hpp @@ -0,0 +1,38 @@ +#pragma once + +#include + +#include + +namespace psemek::util +{ + + namespace detail + { + + template + struct fmap + { + F f; + + template + auto operator() (std::optional && x) + { + using R = decltype(f(*x)); + + if (x) + return std::optional(f(*x)); + else + return std::optional(); + } + }; + + } + + template + auto fmap (F f) + { + return detail::fmap{std::move(f)}; + } + +} diff --git a/libs/util/include/psemek/util/functional.hpp b/libs/util/include/psemek/util/functional.hpp new file mode 100644 index 00000000..e0ebb61e --- /dev/null +++ b/libs/util/include/psemek/util/functional.hpp @@ -0,0 +1,24 @@ +#pragma once + +namespace psemek::util +{ + + constexpr auto nop = [](auto const & ...){}; + + constexpr auto id = [](auto && x) -> decltype(auto) { return x; }; + + template + auto constant (T const & x) + { + return [x](auto const & ...){ return x; }; + } + + template + auto bind_and (F1 && f1, F2 && f2) + { + return [=](auto const &... args){ + return f1(args...) && f2(args...); + }; + } + +} diff --git a/libs/util/include/psemek/util/lazy_range.hpp b/libs/util/include/psemek/util/lazy_range.hpp new file mode 100644 index 00000000..89f02646 --- /dev/null +++ b/libs/util/include/psemek/util/lazy_range.hpp @@ -0,0 +1,65 @@ +#pragma once + +#include + +namespace psemek::util +{ + + template + struct lazy_range + { + Gen generator; + + lazy_range (Gen gen) + : generator(std::move(gen)) + { } + + using value_type = decltype(generator()); + + struct iterator + { + using iterator_category = std::input_iterator_tag; + + lazy_range & range; + + value_type value; + + value_type const & operator * () + { + return value; + } + + iterator & operator ++ () + { + value = range.generator(); + return *this; + } + }; + + iterator begin ( ) + { + return { *this, generator() }; + } + + struct sentinel + { + using iterator_category = std::input_iterator_tag; + }; + + sentinel end ( ) + { + return {}; + } + + friend bool operator == (iterator const &, sentinel) + { + return false; + } + + friend bool operator != (iterator const &, sentinel) + { + return true; + } + }; + +} diff --git a/libs/util/include/psemek/util/movable_function.hpp b/libs/util/include/psemek/util/movable_function.hpp new file mode 100644 index 00000000..43b8eeca --- /dev/null +++ b/libs/util/include/psemek/util/movable_function.hpp @@ -0,0 +1,84 @@ +#pragma once + +#include + +namespace psemek::util +{ + + namespace detail + { + + template + struct movable_function_node_base; + + template + struct movable_function_node_base + { + virtual R call (Args ...) = 0; + + virtual ~ movable_function_node_base ( ) = default; + }; + + template + struct movable_function_node; + + template + struct movable_function_node + : movable_function_node_base + { + F f; + + movable_function_node (F && f) + : f(std::move(f)) + { } + + R call (Args ... args) override + { + return f(args...); + } + }; + + // Implemented in cpp to prevent dependency on + [[noreturn]] void bad_function_call ( ); + + } + + template + struct movable_function; + + template + struct movable_function + { + using signature = R(Args...); + + movable_function ( ) = default; + + template + movable_function (F f) + : p { std::make_unique>>(std::move(f)) } + { } + + movable_function (movable_function &&) = default; + movable_function & operator = (movable_function &&) = default; + + movable_function (movable_function const &) = delete; + movable_function & operator = (movable_function const &) = delete; + + explicit operator bool ( ) const + { + return static_cast(p); + } + + R operator() (Args ... args) const + { + if (!p) + detail::bad_function_call(); + + return p->call(args...); + } + + private: + std::unique_ptr> p; + }; + +} diff --git a/libs/util/include/psemek/util/moving_average.hpp b/libs/util/include/psemek/util/moving_average.hpp new file mode 100644 index 00000000..e3e62fcf --- /dev/null +++ b/libs/util/include/psemek/util/moving_average.hpp @@ -0,0 +1,62 @@ +#pragma once + +#include + +namespace psemek::util +{ + + template + struct moving_average + { + moving_average (std::size_t max) + : data_(max, T()) + , begin_(0) + , size_(0) + , sum_(T()) + { } + + void clear ( ) + { + begin_ = 0; + size_ = 0; + sum_ = T(0); + } + + void push (T x) + { + if (size_ >= data_.size()) + { + sum_ -= data_[begin_]; + } + else + size_++; + + data_[begin_++] = x; + sum_ += x; + + if (begin_ == data_.size()) + begin_ = 0; + } + + T sum ( ) const + { + return sum_; + } + + std::size_t count ( ) const + { + return size_; + } + + T average ( ) const + { + return sum() / count(); + } + + private: + std::vector data_; + std::size_t begin_, size_; + T sum_; + }; + +} diff --git a/libs/util/include/psemek/util/multidimensional_array.hpp b/libs/util/include/psemek/util/multidimensional_array.hpp new file mode 100644 index 00000000..dcbf4b7b --- /dev/null +++ b/libs/util/include/psemek/util/multidimensional_array.hpp @@ -0,0 +1,29 @@ +#pragma once + +#include + +namespace psemek::util +{ + + namespace detail + { + template + struct multidimentional_array_impl; + + template + struct multidimentional_array_impl + { + typedef std::array::type, FirstSize> type; + }; + + template + struct multidimentional_array_impl + { + typedef Type type; + }; + } + + template + using multidimentional_array = typename detail::multidimentional_array_impl::type; + +} diff --git a/libs/util/include/psemek/util/noncopyable.hpp b/libs/util/include/psemek/util/noncopyable.hpp new file mode 100644 index 00000000..cfd90573 --- /dev/null +++ b/libs/util/include/psemek/util/noncopyable.hpp @@ -0,0 +1,16 @@ +#pragma once + +namespace psemek::util +{ + + struct noncopyable + { + noncopyable (noncopyable const &) = delete; + noncopyable & operator = (noncopyable const &) = delete; + + noncopyable ( ) = default; + noncopyable (noncopyable &&) = default; + noncopyable & operator = (noncopyable &&) = default; + }; + +} diff --git a/libs/util/include/psemek/util/not_implemented.hpp b/libs/util/include/psemek/util/not_implemented.hpp new file mode 100644 index 00000000..530ef7ba --- /dev/null +++ b/libs/util/include/psemek/util/not_implemented.hpp @@ -0,0 +1,8 @@ +#pragma once + +namespace psemek::util +{ + + void not_implemented ( ); + +} diff --git a/libs/util/include/psemek/util/overload.hpp b/libs/util/include/psemek/util/overload.hpp new file mode 100644 index 00000000..c5b29b4b --- /dev/null +++ b/libs/util/include/psemek/util/overload.hpp @@ -0,0 +1,30 @@ +#pragma once + +#include + +namespace psemek::util +{ + + namespace detail + { + + template + struct overload_impl + : Fs... + { + overload_impl (Fs ... fs) + : Fs(fs)... + { } + + using Fs::operator()...; + }; + + } + + template + auto overload (Fs ... fs) + { + return detail::overload_impl{std::move(fs)...}; + } + +} diff --git a/libs/util/include/psemek/util/pimpl.hpp b/libs/util/include/psemek/util/pimpl.hpp new file mode 100644 index 00000000..e18ee25d --- /dev/null +++ b/libs/util/include/psemek/util/pimpl.hpp @@ -0,0 +1,68 @@ +#pragma once + +#include +#include + +namespace psemek::util::pimpl +{ + + template + struct impl; + + template + struct in_place + { + protected: + + using impl_type = ::util::pimpl::impl; + + impl_type * pimpl ( ) { return reinterpret_cast(std::addressof(storage_)); } + impl_type & impl ( ) { return *pimpl(); } + + impl_type const * pimpl ( ) const { return reinterpret_cast(std::addressof(storage_)); } + impl_type const & impl ( ) const { return *pimpl(); } + + template + in_place (Args && ... args) + { + static_assert(sizeof(impl_type) <= Size, "impl storage size too small"); + new (pimpl()) impl_type (std::forward(args)...); + } + + ~ in_place ( ) + { + impl().~impl_type(); + } + + private: + + typename std::aligned_storage::type storage_; + }; + + template + struct dynamic + { + protected: + + using impl_type = ::util::pimpl::impl; + + impl_type * pimpl ( ) { return pointer_.get(); } + impl_type & impl ( ) { return *pimpl(); } + + impl_type const * pimpl ( ) const { return pointer_.get(); } + impl_type const & impl ( ) const { return *pimpl(); } + + template + dynamic (Args && ... args) + { + pointer_.reset(new impl_type(std::forward(args)...)); + } + + ~ dynamic ( ) = default; + + private: + + std::unique_ptr pointer_; + }; + +} diff --git a/libs/util/include/psemek/util/pixmap.hpp b/libs/util/include/psemek/util/pixmap.hpp new file mode 100644 index 00000000..ac95eba8 --- /dev/null +++ b/libs/util/include/psemek/util/pixmap.hpp @@ -0,0 +1,201 @@ +#pragma once + +#include +#include + +namespace psemek::util +{ + + template + struct basic_pixmap + { + using pixel_type = Pixel; + + basic_pixmap() = default; + basic_pixmap(std::size_t width, std::size_t height); + basic_pixmap(std::size_t width, std::size_t height, Pixel value); + basic_pixmap(std::size_t width, std::size_t height, std::unique_ptr data); + basic_pixmap(basic_pixmap &&); + + basic_pixmap(basic_pixmap const &) = delete; + + basic_pixmap & operator = (basic_pixmap &&); + basic_pixmap & operator = (basic_pixmap const &) = delete; + + std::size_t width() const { return width_; } + std::size_t height() const { return height_; } + + void resize(std::size_t width, std::size_t height); + void resize(std::size_t width, std::size_t height, Pixel value); + + Pixel * operator[] (std::size_t row); + Pixel const * operator[] (std::size_t row) const; + + Pixel * data() { return data_.get(); } + Pixel const * data() const { return data_.get(); } + + Pixel & operator()(std::size_t column, std::size_t row); + Pixel const & operator()(std::size_t column, std::size_t row) const; + + std::unique_ptr release(); + void reset(std::size_t width, std::size_t height, std::unique_ptr data); + + bool empty() const; + + void clear(); + + void fill(Pixel value); + + private: + std::size_t width_ = 0; + std::size_t height_ = 0; + std::unique_ptr data_; + }; + + using pixmap_monochrome = basic_pixmap; + using pixmap_rgb = basic_pixmap>; + using pixmap_rgba = basic_pixmap>; + using pixmap_float = basic_pixmap; + + pixmap_monochrome read_pgm(std::istream & is); + pixmap_rgb read_ppm(std::istream & is); + + void write_pgm(pixmap_monochrome const & p, std::ostream & os); + void write_ppm(pixmap_rgb const & p, std::ostream & os); + + template + basic_pixmap::basic_pixmap(std::size_t width, std::size_t height) + : width_(width) + , height_(height) + { + data_.reset(new Pixel [width_ * height_]); + } + + template + basic_pixmap::basic_pixmap(std::size_t width, std::size_t height, Pixel value) + : width_(width) + , height_(height) + { + data_.reset(new Pixel [width_ * height_]); + fill(value); + } + + template + basic_pixmap::basic_pixmap(std::size_t width, std::size_t height, std::unique_ptr data) + : width_(width) + , height_(height) + , data_(std::move(data)) + {} + + template + basic_pixmap::basic_pixmap(basic_pixmap && other) + : width_(other.width_) + , height_(other.height_) + , data_(other.release()) + {} + + template + basic_pixmap & basic_pixmap::operator = (basic_pixmap && other) + { + if (this == &other) return *this; + + width_ = other.width_; + height_ = other.height_; + data_ = other.release(); + + return *this; + } + + template + void basic_pixmap::resize(std::size_t width, std::size_t height) + { + data_.reset(new Pixel[width * height]); + width_ = width; + height_ = height; + } + + template + void basic_pixmap::resize(std::size_t width, std::size_t height, Pixel value) + { + data_.reset(new Pixel[width * height]); + width_ = width; + height_ = height; + fill(value); + } + + template + Pixel * basic_pixmap::operator[] (std::size_t row) + { + return data() + row * width(); + } + + template + Pixel const * basic_pixmap::operator[] (std::size_t row) const + { + return data() + row * width(); + } + + template + Pixel & basic_pixmap::operator()(std::size_t column, std::size_t row) + { + return (*this)[row][column]; + } + + template + Pixel const & basic_pixmap::operator()(std::size_t column, std::size_t row) const + { + return (*this)[row][column]; + } + + template + std::unique_ptr basic_pixmap::release() + { + auto data = std::move(data_); + width_ = 0; + height_ = 0; + return data; + } + + template + void basic_pixmap::reset(std::size_t width, std::size_t height, std::unique_ptr data) + { + width_ = width; + height_ = height; + data_ = std::move(data); + } + + template + bool basic_pixmap::empty() const + { + return width() == 0 || height() == 0; + } + + template + void basic_pixmap::clear() + { + release(); + } + + template + void basic_pixmap::fill(Pixel value) + { + std::fill(data_.get(), data_.get() + width_ * height_, value); + } + + template + void mirror_x(basic_pixmap & p) + { + for (std::size_t y = 0; y < p.height(); ++y) + for (std::size_t x = 0; x < p.width() / 2; ++x) + std::swap(p(x, y), p(p.width() - x - 1, y)); + } + + template + void mirror_y(basic_pixmap & p) + { + for (std::size_t y = 0; y < p.height() / 2; ++y) + for (std::size_t x = 0; x < p.width(); ++x) + std::swap(p(x, y), p(x, p.height() - y - 1)); + } + +} diff --git a/libs/util/include/psemek/util/pretty_print.hpp b/libs/util/include/psemek/util/pretty_print.hpp new file mode 100644 index 00000000..9708f625 --- /dev/null +++ b/libs/util/include/psemek/util/pretty_print.hpp @@ -0,0 +1,44 @@ +#pragma once + +#include +#include + +namespace psemek::util +{ + + namespace detail + { + + template + struct pretty_print_time_wrapper + { + Duration d; + UpTo up_to; + }; + + void pretty_print_time (std::ostream & o, std::int64_t d, std::int64_t up_to); + + template + std::ostream & operator << (std::ostream & o, pretty_print_time_wrapper t) + { + std::int64_t const d = std::chrono::duration_cast(t.d).count(); + std::int64_t const up_to = std::chrono::duration_cast(t.up_to).count(); + pretty_print_time(o, d, up_to); + return o; + } + + } + + template + auto pretty (std::chrono::duration d, UpTo up_to) + { + return detail::pretty_print_time_wrapper, UpTo>{d, up_to}; + } + + template + auto pretty (std::chrono::duration d) + { + return pretty(d, std::chrono::seconds{1}); + } + +} diff --git a/libs/util/include/psemek/util/profiler.hpp b/libs/util/include/psemek/util/profiler.hpp new file mode 100644 index 00000000..2cf28c03 --- /dev/null +++ b/libs/util/include/psemek/util/profiler.hpp @@ -0,0 +1,27 @@ +#pragma once + +#include +#include + +#include + +namespace psemek::util +{ + + struct profiler + { + profiler (std::string name) + : name_(std::move(name)) + { } + + ~ profiler ( ) + { + std::cout << name_ << ": " << util::pretty(clock_.duration(), std::chrono::microseconds{1}) << "\n"; + } + + private: + std::string const name_; + util::clock<> clock_; + }; + +} diff --git a/libs/util/include/psemek/util/range.hpp b/libs/util/include/psemek/util/range.hpp new file mode 100644 index 00000000..7dd9f56a --- /dev/null +++ b/libs/util/include/psemek/util/range.hpp @@ -0,0 +1,80 @@ +#pragma once + +#include +#include + +namespace psemek::util +{ + + namespace detail + { + + template + auto begin_helper (Container & x) + { + using std::begin; + return begin(x); + } + + template + auto end_helper (Container & x) + { + using std::end; + return end(x); + } + + } + + template + auto begin (Container & x) + { + return detail::begin_helper(x); + } + + template + auto end (Container & x) + { + return detail::end_helper(x); + } + + template + struct range_traits + { + using iterator = decltype(begin(std::declval())); + using iterator_traits = std::iterator_traits; + + using iterator_category = typename iterator_traits::iterator_category; + using value_type = typename iterator_traits::value_type ; + using difference = typename iterator_traits::difference ; + using pointer = typename iterator_traits::pointer ; + using reference = typename iterator_traits::reference ; + }; + + template + struct range + { + Iterator it_begin; + Iterator it_end; + + Iterator begin() const + { + return it_begin; + } + + Iterator end() const + { + return it_end; + } + }; + + template + auto reversed (Range const & r) + { + auto it1 = begin(r); + auto it2 = end(r); + + using ReverseIterator = std::reverse_iterator; + return range{ std::make_reverse_iterator(it2), std::make_reverse_iterator(it1) }; + } + +} diff --git a/libs/util/include/psemek/util/recursive.hpp b/libs/util/include/psemek/util/recursive.hpp new file mode 100644 index 00000000..d7e47fa9 --- /dev/null +++ b/libs/util/include/psemek/util/recursive.hpp @@ -0,0 +1,29 @@ +#pragma once + +namespace psemek::util +{ + + namespace detail + { + + template + struct recursive_impl + { + F f; + + template + auto operator() (Args && ... args) -> decltype(auto) + { + return f(*this, std::forward(args)...); + } + }; + + } + + template + auto recursive (F f) + { + return detail::recursive_impl{std::move(f)}; + } + +} diff --git a/libs/util/include/psemek/util/shared_blob.hpp b/libs/util/include/psemek/util/shared_blob.hpp new file mode 100644 index 00000000..3670ca99 --- /dev/null +++ b/libs/util/include/psemek/util/shared_blob.hpp @@ -0,0 +1,129 @@ +#pragma once + +#include + +#include +#include +#include + +namespace psemek::util +{ + + struct shared_blob + { + shared_blob() = default; + shared_blob(shared_blob const & other); + shared_blob(shared_blob && other); + shared_blob(blob && other); + + shared_blob(std::size_t size); + shared_blob(std::size_t size, std::shared_ptr data); + shared_blob(std::size_t size, char * data); + + shared_blob & operator = (shared_blob const & other); + shared_blob & operator = (shared_blob && other); + shared_blob & operator = (blob && other); + + ~ shared_blob() = default; + + char * data() { return data_.get(); } + char const * data() const { return data_.get(); } + + std::size_t size() const { return size_; } + + void reset(); + + using iterator = char *; + using const_iterator = char const *; + + char * begin() { return data(); } + char const * begin() const { return data(); } + + char * end() { return data() + size(); } + char const * end() const { return data() + size(); } + + char & operator[] (std::size_t i) { return data()[i]; } + char const & operator[] (std::size_t i) const { return data()[i]; } + + std::string string() const; + std::string_view string_view() const; + + private: + std::shared_ptr data_; + std::size_t size_ = 0; + }; + + inline shared_blob::shared_blob(shared_blob const & other) + { + *this = other; + } + + inline shared_blob::shared_blob(shared_blob && other) + { + *this = std::move(other); + } + + inline shared_blob::shared_blob(blob && other) + { + *this = std::move(other); + } + + inline shared_blob::shared_blob(std::size_t size) + : data_{new char [size]} + , size_{size} + {} + + inline shared_blob::shared_blob(std::size_t size, std::shared_ptr data) + : data_{std::move(data)} + , size_{size} + {} + + inline shared_blob::shared_blob(std::size_t size, char * data) + : data_{data} + , size_{size} + {} + + inline shared_blob & shared_blob::operator=(shared_blob const & other) + { + if (this != &other) + { + data_ = other.data_; + size_ = other.size(); + } + return *this; + } + + inline shared_blob & shared_blob::operator=(shared_blob && other) + { + if (this != &other) + { + data_ = std::move(other.data_); + size_ = other.size(); + other.size_ = 0; + } + return *this; + } + + inline shared_blob & shared_blob::operator=(blob && other) + { + size_ = other.size(); + data_ = other.release(); + return *this; + } + + inline void shared_blob::reset() + { + data_.reset(); + size_ = 0; + } + + inline std::string shared_blob::string() const + { + return std::string(data_.get(), data_.get() + size_); + } + + inline std::string_view shared_blob::string_view() const + { + return std::string_view(data_.get(), size_); + } +} diff --git a/libs/util/include/psemek/util/synchronyzed_queue.hpp b/libs/util/include/psemek/util/synchronyzed_queue.hpp new file mode 100644 index 00000000..0d1b9876 --- /dev/null +++ b/libs/util/include/psemek/util/synchronyzed_queue.hpp @@ -0,0 +1,147 @@ +#pragma once + +#include +#include +#include +#include +#include +#include + +namespace psemek::util +{ + + template + struct synchronized_queue + { + synchronized_queue (std::size_t max_size = std::numeric_limits::max()) noexcept + : max_size_(max_size) + { } + + std::size_t max_size ( ) const noexcept + { + return max_size_; + } + + void push (T const & x); + void push (T && x); + T pop ( ); + + bool try_push (T const & x); + template + bool try_push (T const & x, std::chrono::duration const & timeout); + + std::optional try_pop ( ); + template + std::optional try_pop (std::chrono::duration const & timeout); + + void clear ( ); + + // Wait for the queue to become empty + // e.g. when no new items are going to be pushed + void wait ( ); + + private: + std::mutex mutex; + std::condition_variable push_cv, pop_cv; + std::deque queue; + std::size_t const max_size_; + }; + + template + void synchronized_queue::push (T const & x) + { + std::unique_lock lock { mutex }; + push_cv.wait(lock, [this]{ return queue.size() < max_size(); }); + queue.push_back(x); + pop_cv.notify_one(); + } + + template + void synchronized_queue::push (T && x) + { + std::unique_lock lock { mutex }; + push_cv.wait(lock, [this]{ return queue.size() < max_size(); }); + queue.push_back(std::move(x)); + pop_cv.notify_one(); + } + + template + T synchronized_queue::pop ( ) + { + std::unique_lock lock { mutex }; + pop_cv.wait(lock, [this]{ return !queue.empty(); }); + T x = std::move(queue.front()); + queue.pop_front(); + push_cv.notify_one(); + return x; + } + + template + bool synchronized_queue::try_push (T const & x) + { + std::lock_guard lock { mutex }; + if (queue.size() >= max_size()) + return false; + + queue.push_back(x); + pop_cv.notify_one(); + return true; + } + + template + template + bool synchronized_queue::try_push (T const & x, std::chrono::duration const & timeout) + { + std::unique_lock lock { mutex }; + if (push_cv.wait_for(lock, timeout, [this]{ return queue.size() < max_size(); })) + { + queue.push_back(std::move(x)); + pop_cv.notify_one(); + return true; + } + return false; + } + + template + std::optional synchronized_queue::try_pop ( ) + { + std::lock_guard lock { mutex }; + if (queue.empty()) + return std::nullopt; + T x = std::move(queue.front()); + queue.pop_front(); + push_cv.notify_one(); + return { std::move(x) }; + } + + template + template + std::optional synchronized_queue::try_pop (std::chrono::duration const & timeout) + { + std::unique_lock lock { mutex }; + if (pop_cv.wait_for(lock, timeout, [this]{ return !queue.empty(); })) + { + T x = std::move(queue.front()); + queue.pop_front(); + push_cv.notify_one(); + return { std::move(x) }; + } + return std::nullopt; + } + + template + void synchronized_queue::clear ( ) + { + std::lock_guard lock { mutex }; + queue.clear(); + push_cv.notify_all(); + } + + template + void synchronized_queue::wait ( ) + { + std::unique_lock lock { mutex }; + push_cv.wait(lock, [this]{ return queue.empty(); }); + } + +} diff --git a/libs/util/include/psemek/util/thread.hpp b/libs/util/include/psemek/util/thread.hpp new file mode 100644 index 00000000..1082d064 --- /dev/null +++ b/libs/util/include/psemek/util/thread.hpp @@ -0,0 +1,25 @@ +#pragma once + +#include + +namespace psemek::util +{ + + struct thread + : std::thread + { + template + thread (Args && ... args) + : std::thread(std::forward(args)...) + { } + + thread (thread &&) = default; + + ~ thread ( ) + { + if (joinable()) + join(); + } + }; + +} diff --git a/libs/util/include/psemek/util/threadpool.hpp b/libs/util/include/psemek/util/threadpool.hpp new file mode 100644 index 00000000..b33b4eb0 --- /dev/null +++ b/libs/util/include/psemek/util/threadpool.hpp @@ -0,0 +1,57 @@ +#pragma once + +#include +#include +#include + +#include +#include + +namespace psemek::util +{ + + struct threadpool + { + threadpool ( ) + : threadpool(std::max(1u, std::thread::hardware_concurrency())) + { } + + threadpool (std::size_t thread_count) + { + start(thread_count); + } + + ~ threadpool ( ) + { + stop(); + } + + template + auto dispatch (F && f) + { + using R = decltype(f()); + + std::packaged_task task { std::forward(f) }; + + auto result = task.get_future(); + + tasks_queue.push(std::move(task)); + + return result; + } + + void start (std::size_t thread_count); + + void stop ( ); + + void wait ( ) + { + tasks_queue.wait(); + } + + private: + std::vector threads; + util::synchronized_queue> tasks_queue; + }; + +} diff --git a/libs/util/include/psemek/util/timer.hpp b/libs/util/include/psemek/util/timer.hpp new file mode 100644 index 00000000..36f89ec4 --- /dev/null +++ b/libs/util/include/psemek/util/timer.hpp @@ -0,0 +1,31 @@ +#pragma once + +#include + +namespace psemek::util +{ + + template , typename Clock = std::chrono::system_clock> + struct timer + : clock + { + timer (Duration duration) + : duration_(duration) + { } + + explicit operator bool ( ) + { + if (this->duration() >= duration_) + { + this->restart(); + return true; + } + + return false; + } + + private: + Duration duration_; + }; + +} diff --git a/libs/util/include/psemek/util/to_string.hpp b/libs/util/include/psemek/util/to_string.hpp new file mode 100644 index 00000000..42699fb8 --- /dev/null +++ b/libs/util/include/psemek/util/to_string.hpp @@ -0,0 +1,59 @@ +#pragma once + +#include +#include + +namespace psemek::util +{ + + namespace detail + { + + template , typename ... Args> + std::basic_string to_string (Args const & ... args) + { + std::basic_ostringstream oss; + + ((oss << args), ...); + + return oss.str(); + } + + } + + template + std::string to_string (Args const & ... args) + { + return detail::to_string(args...); + } + + template + std::wstring to_wstring (Args const & ... args) + { + return detail::to_string(args...); + } + + template + std::u32string to_u32string (Args const & ... args) + { + return detail::to_string(args...); + } + + template + T from_string (std::basic_string const & s) + { + std::basic_istringstream iss(s); + T x; + iss >> x; + if (!iss) + throw std::invalid_argument("failed to parse from string"); + return x; + } + + template + T from_string (Char const * s) + { + return from_string>(s); + } + +} diff --git a/libs/util/include/psemek/util/unicode.hpp b/libs/util/include/psemek/util/unicode.hpp new file mode 100644 index 00000000..93f3f394 --- /dev/null +++ b/libs/util/include/psemek/util/unicode.hpp @@ -0,0 +1,11 @@ +#pragma once + +#include + +namespace psemek::util +{ + + std::string to_utf8 (std::u32string const & str); + std::u32string from_utf8 (std::string const & str); + +} diff --git a/libs/util/source/assert.cpp b/libs/util/source/assert.cpp new file mode 100644 index 00000000..84d3967c --- /dev/null +++ b/libs/util/source/assert.cpp @@ -0,0 +1,14 @@ +#include +#include + +#include + +namespace psemek::util +{ + + [[noreturn]] bool assert_handler (char const * expression, char const * file, int line) + { + throw std::runtime_error(to_string(file, ":", line, " Assertion failed: ", expression)); + } + +} diff --git a/libs/util/source/movable_function.cpp b/libs/util/source/movable_function.cpp new file mode 100644 index 00000000..0f4dc69f --- /dev/null +++ b/libs/util/source/movable_function.cpp @@ -0,0 +1,18 @@ +#include + +#include + +namespace psemek::util +{ + + namespace detail + { + + void bad_function_call ( ) + { + throw std::bad_function_call(); + } + + } + +} diff --git a/libs/util/source/not_implemented.cpp b/libs/util/source/not_implemented.cpp new file mode 100644 index 00000000..f9a73a13 --- /dev/null +++ b/libs/util/source/not_implemented.cpp @@ -0,0 +1,13 @@ +#include + +#include + +namespace psemek::util +{ + + void not_implemented ( ) + { + throw std::runtime_error("Not implemented"); + } + +} diff --git a/libs/util/source/pixmap.cpp b/libs/util/source/pixmap.cpp new file mode 100644 index 00000000..05c14267 --- /dev/null +++ b/libs/util/source/pixmap.cpp @@ -0,0 +1,110 @@ +#include + +#include + +namespace psemek::util +{ + + pixmap_monochrome read_pgm(std::istream & is) + { + auto fail = [](std::string str) + { + throw std::runtime_error("Error loading PGM image: " + str); + }; + + std::string line; + std::getline(is, line); + + bool binary = true; + + if (line == "P2") + { + binary = false; + } + else if (line == "P5") + { + binary = true; + } + else + fail("unknown format " + line); + + std::size_t width, height; + std::size_t max; + pixmap_monochrome pixmap; + + is >> width >> height >> max; + + if (max != 255) + fail("max value " + std::to_string(max) + " is not supported"); + + pixmap.resize(width, height); + + if (binary) + is.read(reinterpret_cast(pixmap.data()), width * height * sizeof(pixmap.data()[0])); + else + fail("P2 format is not supported"); + + if (!is) + fail("stream error"); + + return pixmap; + } + + pixmap_rgb load_ppm(std::istream & is) + { + auto fail = [](std::string str) + { + throw std::runtime_error("Error loading PPM image: " + str); + }; + + std::string line; + std::getline(is, line); + + bool binary = true; + + if (line == "P3") + { + binary = false; + } + else if (line == "P6") + { + binary = true; + } + else + fail("unknown format " + line); + + std::size_t width, height; + std::size_t max; + pixmap_rgb pixmap; + + is >> width >> height >> max; + + if (max != 255) + fail("max value " + std::to_string(max) + " is not supported"); + + pixmap.resize(width, height); + + if (binary) + is.read(reinterpret_cast(pixmap.data()), width * height * sizeof(pixmap.data()[0])); + else + fail("P3 format is not supported"); + + if (!is) + fail("stream error"); + + return pixmap; + } + + void write_pgm(pixmap_monochrome const & p, std::ostream & os) + { + os << "P5\n" << p.width() << " " << p.height() << "\n255\n"; + os.write(reinterpret_cast(p.data()), p.width() * p.height() * sizeof(p.data()[0])); + } + + void write_ppm(pixmap_rgb const & p, std::ostream & os) + { + os << "P6\n" << p.width() << " " << p.height() << "\n255\n"; + os.write(reinterpret_cast(p.data()), p.width() * p.height() * sizeof(p.data()[0])); + } + +} diff --git a/libs/util/source/pretty_print_time.cpp b/libs/util/source/pretty_print_time.cpp new file mode 100644 index 00000000..99de1cc1 --- /dev/null +++ b/libs/util/source/pretty_print_time.cpp @@ -0,0 +1,66 @@ +#include + +namespace psemek::util +{ + + namespace detail + { + + void pretty_print_time (std::ostream & o, std::int64_t d, std::int64_t up_to) + { + static constexpr const std::int64_t durations[8] = { + 604800 * 1000000000ull, + 86400 * 1000000000ull, + 3600 * 1000000000ull, + 60 * 1000000000ull, + 1000000000ull, + 1000000ull, + 1000ull, + 1ull + }; + + static const std::string_view suffixes[8] = { + "w", + "d", + "h", + "m", + "s", + "ms", + "us", + "ns" + }; + + bool first = true; + + for (std::size_t i = 0; i < 8; ++i) + { + if (up_to > durations[i]) break; + + std::int64_t value = d / durations[i]; + d %= durations[i]; + + if (value == 0) continue; + + if (first) + first = false; + else + o << ' '; + + o << value << suffixes[i]; + } + + // [ first == true ] means no output was generated + // Find first matching suffix and output zero + if (first) for (std::size_t i = 0; i < 8; ++i) + { + if (up_to >= durations[i]) + { + o << 0 << suffixes[i]; + break; + } + } + } + + } + +} diff --git a/libs/util/source/threadpool.cpp b/libs/util/source/threadpool.cpp new file mode 100644 index 00000000..72c67a78 --- /dev/null +++ b/libs/util/source/threadpool.cpp @@ -0,0 +1,35 @@ +#include + +namespace psemek::util +{ + + void threadpool::start (std::size_t thread_count) + { + for (std::size_t th = 0; th < thread_count; ++th) + { + threads.emplace_back([this] + { + while (true) + { + auto task = tasks_queue.pop(); + + if (!task) + break; + + task(); + } + }); + } + } + + void threadpool::stop ( ) + { + tasks_queue.clear(); + for (auto const & thread: threads) + { + tasks_queue.push({}); + } + threads.clear(); + } + +} diff --git a/libs/util/source/unicode.cpp b/libs/util/source/unicode.cpp new file mode 100644 index 00000000..1a503195 --- /dev/null +++ b/libs/util/source/unicode.cpp @@ -0,0 +1,21 @@ +#include + +#include +#include + +namespace psemek::util +{ + + using converter = std::wstring_convert, char32_t>; + + std::string to_utf8 (std::u32string const & str) + { + return converter().to_bytes(str); + } + + std::u32string from_utf8 (std::string const & str) + { + return converter().from_bytes(str); + } + +} diff --git a/todo.md b/todo.md new file mode 100644 index 00000000..5d75430b --- /dev/null +++ b/todo.md @@ -0,0 +1,10 @@ +* Use the same code style everywhere (mostly about spaces after function names) +* Make sure program & shaders are deleted properly if program creation fails +* Remove gfx::vertex, setup mesh using attributes directly +* Design affine transforms in geom & use them instead of matrices when appropriate +* Create an 'app' module that simplifies application creation +* Implement pixmap font rendering +* Create a simple generic primive painter +* Design resources system +* Design logging system +* Design ui system