Gamp v0.0.7-54-gccdc599
Gamp: Graphics, Audio, Multimedia and Processing
Loading...
Searching...
No Matches
GearsES2.hpp

This C++ demo showcases a simple gamp::wt::RenderListener exposing three shapes, implementing rendering using gamp::render::gl::glsl::ShaderState setup with attributes, uniforms and gamp::render::gl::glsl::ShaderCode.

This C++ demo showcases a simple gamp::wt::RenderListener exposing three shapes, implementing rendering using gamp::render::gl::glsl::ShaderState setup with attributes, uniforms and gamp::render::gl::glsl::ShaderCode.

/*
* Author: Sven Gothel <sgothel@jausoft.com>
* Copyright Gothel Software e.K.
*
* SPDX-License-Identifier: MIT
*
* This Source Code Form is subject to the terms of the MIT License
* If a copy of the MIT was not distributed with this file,
* you can obtain one at https://opensource.org/license/mit/.
*/
#ifndef GAMP_DEMOS_GEARSES02_HPP_
#define GAMP_DEMOS_GEARSES02_HPP_
#include <cmath>
#include <cstdio>
#include <memory>
#include <numbers>
#include <jau/debug.hpp>
using namespace jau::math;
using namespace jau::math::util;
using namespace gamp::wt;
using namespace gamp::wt::event;
using namespace gamp::render::gl::glsl;
using namespace gamp::render::gl::data;
typedef jau::function<bool(const PointerEvent& e, const WindowRef& win, GearsObjectES2& shape)> PointerShapeAction;
/**
* GearsObjectES2
* @author Brian Paul (converted to C++ and added pixel-lightning by Sven Gothel)
*/
public:
constexpr static jau::math::Vec4f red = jau::math::Vec4f(0.8f, 0.1f, 0.0f, 0.7f);
constexpr static jau::math::Vec4f green = jau::math::Vec4f(0.0f, 0.8f, 0.2f, 0.7f);
constexpr static jau::math::Vec4f blue = jau::math::Vec4f(0.2f, 0.2f, 1.0f, 0.7f);
private:
int m_name;
ShaderState& m_st;
GLUniformVec4fRef m_colorUniform;
jau::math::Vec4f m_gearColor;
bool m_useMappedBuffers;
bool m_picked;
jau::math::geom::AABBox3f m_objbox, m_viewbox;
GLFloatArrayDataServerRef m_insideRadiusCyl;
private:
GLFloatArrayDataServerRef createInterleaved(bool useMappedBuffers, GLsizei compsPerElem, bool normalized, GLsizei initialSize, GLenum vboUsage) {
if( useMappedBuffers ) {
return GLFloatArrayDataServer::createGLSLInterleavedMapped(compsPerElem, normalized, initialSize, vboUsage);
} else {
return GLFloatArrayDataServer::createGLSLInterleaved(compsPerElem, normalized, initialSize, vboUsage);
}
}
void addInterleavedVertexAndNormalArrays(GLFloatArrayDataServerRef& array, GLsizei compsPerElem) {
array->addGLSLSubArray("gca_Vertex", compsPerElem, GL_ARRAY_BUFFER);
array->addGLSLSubArray("gca_Normal", compsPerElem, GL_ARRAY_BUFFER);
}
void vert(GLFloatArrayDataServerRef& array, float x, float y, float z, const jau::math::Vec3f& n) {
array->put3f(x, y, z);
array->put3f(n);
m_objbox.resize(x, y, z);
}
static void sincos(float x, float sin[], int sinIdx, float cos[], int cosIdx) {
sin[sinIdx] = std::sin(x);
cos[cosIdx] = std::cos(x);
}
void initGL(GL& gl, GLFloatArrayDataServerRef& array) {
array->enableBuffer(gl, true);
array->enableBuffer(gl, false);
}
void associate(ShaderState& st) {
m_frontFace->associate(st, true);
m_frontSide->associate(st, true);
m_backFace->associate(st, true);
m_backSide->associate(st, true);
m_outwardFace->associate(st, true);
m_insideRadiusCyl->associate(st, true);
}
void draw(GL& gl, GLFloatArrayDataServerRef& array, int mode) {
if( 0 < array->vboName() ) {
array->enableBuffer(gl, true);
::glDrawArrays(mode, 0, array->elemCount());
array->enableBuffer(gl, false);
}
}
public:
GearsObjectES2(int name, ShaderState& st, const jau::math::Vec4f& gearColor,
float inner_radius, float outer_radius,
float width,
GLsizei teeth,
float tooth_depth,
GLUniformSyncPMVMat4fRef &pmvMatUni, GLUniformVec4fRef colorUniform)
: m_name(name), m_st(st), m_pmvMatUni(pmvMatUni),
m_colorUniform(std::move(colorUniform)), m_gearColor(gearColor), m_tx(tx),
m_useMappedBuffers(false), m_picked(false), m_objbox(), m_viewbox(), m_PMvi() {
const float dz = width * 0.5f;
float u, v, len;
float s[5];
float c[5];
// const int tris_per_tooth = 32;
const float r0 = inner_radius;
const float r1 = outer_radius - tooth_depth / 2.0f;
const float r2 = outer_radius + tooth_depth / 2.0f;
const float da = 2.0f * std::numbers::pi_v<float> / float(teeth) / 4.0f;
s[4] = 0; // sin(0f)
c[4] = 1; // cos(0f)
const GLenum vboUsage = GL_STATIC_DRAW;
m_frontFace = createInterleaved(m_useMappedBuffers, 6, false, 4 * teeth + 2, vboUsage);
addInterleavedVertexAndNormalArrays(m_frontFace, 3);
m_backFace = createInterleaved(m_useMappedBuffers, 6, false, 4 * teeth + 2, vboUsage);
addInterleavedVertexAndNormalArrays(m_backFace, 3);
m_frontSide = createInterleaved(m_useMappedBuffers, 6, false, 6 * teeth, vboUsage);
addInterleavedVertexAndNormalArrays(m_frontSide, 3);
m_backSide = createInterleaved(m_useMappedBuffers, 6, false, 6 * teeth, vboUsage);
addInterleavedVertexAndNormalArrays(m_backSide, 3);
m_outwardFace = createInterleaved(m_useMappedBuffers, 6, false, 4 * 4 * teeth + 2, vboUsage);
addInterleavedVertexAndNormalArrays(m_outwardFace, 3);
m_insideRadiusCyl = createInterleaved(m_useMappedBuffers, 6, false, 2 * teeth + 2, vboUsage);
addInterleavedVertexAndNormalArrays(m_insideRadiusCyl, 3);
for( GLsizei i = 0; i < teeth; i++ ) {
const float angle = float(i) * 2.0f * std::numbers::pi_v<float> / float(teeth);
sincos(angle + da * 0.0f, s, 0, c, 0);
sincos(angle + da * 1.0f, s, 1, c, 1);
sincos(angle + da * 2.0f, s, 2, c, 2);
sincos(angle + da * 3.0f, s, 3, c, 3);
/* front */
normal = jau::math::Vec3f(0, 0, 1);
/* front face - GL.GL_TRIANGLE_STRIP */
vert(m_frontFace, r0 * c[0], r0 * s[0], dz, normal);
vert(m_frontFace, r1 * c[0], r1 * s[0], dz, normal);
vert(m_frontFace, r0 * c[0], r0 * s[0], dz, normal);
vert(m_frontFace, r1 * c[3], r1 * s[3], dz, normal);
/* front sides of teeth - GL.GL_TRIANGLES */
vert(m_frontSide, r1 * c[0], r1 * s[0], dz, normal);
vert(m_frontSide, r2 * c[1], r2 * s[1], dz, normal);
vert(m_frontSide, r2 * c[2], r2 * s[2], dz, normal);
vert(m_frontSide, r1 * c[0], r1 * s[0], dz, normal);
vert(m_frontSide, r2 * c[2], r2 * s[2], dz, normal);
vert(m_frontSide, r1 * c[3], r1 * s[3], dz, normal);
/* back */
normal = jau::math::Vec3f(0, 0, -1);
/* back face - GL.GL_TRIANGLE_STRIP */
vert(m_backFace, r1 * c[0], r1 * s[0], -dz, normal);
vert(m_backFace, r0 * c[0], r0 * s[0], -dz, normal);
vert(m_backFace, r1 * c[3], r1 * s[3], -dz, normal);
vert(m_backFace, r0 * c[0], r0 * s[0], -dz, normal);
/* back sides of teeth - GL.GL_TRIANGLES*/
vert(m_backSide, r1 * c[3], r1 * s[3], -dz, normal);
vert(m_backSide, r2 * c[2], r2 * s[2], -dz, normal);
vert(m_backSide, r2 * c[1], r2 * s[1], -dz, normal);
vert(m_backSide, r1 * c[3], r1 * s[3], -dz, normal);
vert(m_backSide, r2 * c[1], r2 * s[1], -dz, normal);
vert(m_backSide, r1 * c[0], r1 * s[0], -dz, normal);
/* outward faces of teeth */
u = r2 * c[1] - r1 * c[0];
v = r2 * s[1] - r1 * s[0];
len = std::sqrt(u * u + v * v);
u /= len;
v /= len;
normal = jau::math::Vec3f(v, -u, 0);
vert(m_outwardFace, r1 * c[0], r1 * s[0], dz, normal);
vert(m_outwardFace, r1 * c[0], r1 * s[0], -dz, normal);
vert(m_outwardFace, r2 * c[1], r2 * s[1], dz, normal);
vert(m_outwardFace, r2 * c[1], r2 * s[1], -dz, normal);
normal[0] = c[0];
normal[1] = s[0];
vert(m_outwardFace, r2 * c[1], r2 * s[1], dz, normal);
vert(m_outwardFace, r2 * c[1], r2 * s[1], -dz, normal);
vert(m_outwardFace, r2 * c[2], r2 * s[2], dz, normal);
vert(m_outwardFace, r2 * c[2], r2 * s[2], -dz, normal);
normal[0] = (r1 * s[3] - r2 * s[2]);
normal[1] = (r1 * c[3] - r2 * c[2]) * -1.0f;
vert(m_outwardFace, r2 * c[2], r2 * s[2], dz, normal);
vert(m_outwardFace, r2 * c[2], r2 * s[2], -dz, normal);
vert(m_outwardFace, r1 * c[3], r1 * s[3], dz, normal);
vert(m_outwardFace, r1 * c[3], r1 * s[3], -dz, normal);
normal[0] = c[0];
normal[1] = s[0];
vert(m_outwardFace, r1 * c[3], r1 * s[3], dz, normal);
vert(m_outwardFace, r1 * c[3], r1 * s[3], -dz, normal);
vert(m_outwardFace, r1 * c[0], r1 * s[0], dz, normal);
vert(m_outwardFace, r1 * c[0], r1 * s[0], -dz, normal);
/* inside radius cylinder */
normal[0] = c[0] * -1.0f;
normal[1] = s[0] * -1.0f;
normal[2] = 0.0f;
vert(m_insideRadiusCyl, r0 * c[0], r0 * s[0], -dz, normal);
vert(m_insideRadiusCyl, r0 * c[0], r0 * s[0], dz, normal);
}
/* finish front face */
normal[0] = 0.0f;
normal[1] = 0.0f;
normal[2] = 1.0f;
vert(m_frontFace, r0 * c[4], r0 * s[4], dz, normal);
vert(m_frontFace, r1 * c[4], r1 * s[4], dz, normal);
m_frontFace->seal(true);
/* finish back face */
normal[2] = -1.0f;
vert(m_backFace, r1 * c[4], r1 * s[4], -dz, normal);
vert(m_backFace, r0 * c[4], r0 * s[4], -dz, normal);
m_backFace->seal(true);
m_backSide->seal(true);
m_frontSide->seal(true);
/* finish outward face */
sincos(da * 1.0f, s, 1, c, 1);
u = r2 * c[1] - r1 * c[4];
v = r2 * s[1] - r1 * s[4];
len = std::sqrt(u * u + v * v);
u /= len;
v /= len;
normal[0] = v;
normal[1] = -u;
normal[2] = 0.0f;
vert(m_outwardFace, r1 * c[4], r1 * s[4], dz, normal);
vert(m_outwardFace, r1 * c[4], r1 * s[4], -dz, normal);
m_outwardFace->seal(true);
/* finish inside radius cylinder */
normal[0] = c[4] * -1.0f;
normal[1] = s[4] * -1.0f;
normal[2] = 0.0f;
vert(m_insideRadiusCyl, r0 * c[4], r0 * s[4], -dz, normal);
vert(m_insideRadiusCyl, r0 * c[4], r0 * s[4], dz, normal);
m_insideRadiusCyl->seal(true);
associate(m_st);
}
void initGL(GL& gl) {
/** Init VBO and data .. */
initGL(gl, m_frontFace);
initGL(gl, m_frontSide);
initGL(gl, m_backFace);
initGL(gl, m_backSide);
initGL(gl, m_outwardFace);
initGL(gl, m_insideRadiusCyl);
}
void dispose(GL& gl) {
// could be already destroyed by shared configuration
if( m_frontFace ) {
m_frontFace->destroy(gl);
}
if( m_frontSide ) {
m_frontSide->destroy(gl);
}
if( m_backFace ) {
m_backFace->destroy(gl);
}
if( m_backSide ) {
m_backSide->destroy(gl);
}
if( m_outwardFace ) {
m_outwardFace->destroy(gl);
}
if( m_insideRadiusCyl ) {
m_insideRadiusCyl->destroy(gl);
}
m_frontFace = nullptr;
m_frontSide = nullptr;
m_backFace = nullptr;
m_backSide = nullptr;
m_outwardFace = nullptr;
m_insideRadiusCyl = nullptr;
}
void draw(GL& gl, float ang_rad) {
PMVMat4f& pmv = m_pmvMatUni->pmv();
pmv.pushMv();
pmv.translateMv(m_tx);
m_objbox.transform(pmv.getMv(), m_viewbox); // view-box for findPick
pmv.rotateMv(ang_rad, 0.0f, 0.0f, 1.0f);
m_st.pushUniform(gl, m_pmvMatUni); // automatic sync + update of Mvi + Mvit
if( m_picked ) {
const float gray = ( m_gearColor.x + m_gearColor.y + m_gearColor.z ) / 3.0f;
m_colorUniform->vec4f() = jau::math::Vec4f(gray, gray, gray, m_gearColor.w);
} else {
m_colorUniform->vec4f() = m_gearColor;
}
m_st.pushUniform(gl, m_colorUniform);
draw(gl, m_frontFace, GL_TRIANGLE_STRIP);
draw(gl, m_frontSide, GL_TRIANGLES);
draw(gl, m_backFace, GL_TRIANGLE_STRIP);
draw(gl, m_backSide, GL_TRIANGLES);
draw(gl, m_outwardFace, GL_TRIANGLE_STRIP);
draw(gl, m_insideRadiusCyl, GL_TRIANGLE_STRIP);
m_PMvi = pmv.getPMvi();
pmv.popMv();
}
bool dispatchAction(const PointerShapeAction& action, const PointerEvent& e, const WindowRef& win) {
PMVMat4f& pmv = m_pmvMatUni->pmv();
pmv.pushMv();
pmv.translateMv(m_tx);
const bool done = action(e, win, *this);
pmv.popMv();
return done;
}
bool& picked() noexcept { return m_picked; }
const jau::math::geom::AABBox3f& objBounds() const noexcept { return m_objbox; }
const jau::math::geom::AABBox3f& viewBounds() const noexcept { return m_viewbox; }
const jau::math::Mat4f& matPMvi() const noexcept { return m_PMvi; }
constexpr int name() const noexcept { return m_name; }
std::string toString() const noexcept { return std::string("GearsObjES2[").append(std::to_string(m_name).append(", view ").append(m_viewbox.toString())).append("]"); }
};
/**
* GearsES2
* @author Brian Paul (converted to C++ and added pixel-lightning by Sven Gothel)
*/
class GearsES2 : public RenderListener {
private:
constexpr static jau::math::Vec3f lightPos = jau::math::Vec3f(5.0f, 5.0f, 10.0f);
constexpr static PMVData mat_req = PMVData::inv_proj | PMVData::inv_mv | PMVData::inv_tps_mv;
ShaderState m_st;
GLUniformVec4fRef m_colorUni;
jau::math::Vec4f m_gear1Color, m_gear2Color, m_gear3Color;
GearsObjectES2 m_gear1, m_gear2, m_gear3;
jau::math::Recti m_viewport;
Vec3f m_pan;
/// in angle degrees
float m_teethAngle = 0.0f;
int m_swapInterval = 1;
bool m_flipVerticalInGLOrientation = false;
bool m_doRotate = true;
jau::math::Vec4f m_clearColor = jau::math::Vec4f(0.0f);
bool m_clearBuffers = true;
bool m_initialized = false;
float m_zNear = 5.0f;
float m_zFar = 10000.0f;
float m_zViewDist = 40.0f;
public:
m_st(),
m_pmvMatUni(GLUniformSyncPMVMat4f::create("gcu_PMVMatrix", mat_req)), // P, Mv, Mvi and Mvit
m_colorUni(GLUniformVec4f::create("gcu_StaticColor", GearsObjectES2::red)),
m_gear1Color(GearsObjectES2::red),
m_gear2Color(GearsObjectES2::green),
m_gear3Color(GearsObjectES2::blue),
m_gear1(1, m_st, m_gear1Color, 1.0f, 4.0f, 1.0f, 20, 0.7f, Vec3f( -3.0f, -2.0f, 0.0f), m_pmvMatUni, m_colorUni),
m_gear2(2, m_st, m_gear2Color, 0.5f, 2.0f, 2.0f, 10, 0.7f, Vec3f( 3.1f, -2.0f, 0.0f), m_pmvMatUni, m_colorUni),
m_gear3(3, m_st, m_gear3Color, 1.3f, 2.0f, 0.5f, 10, 0.7f, Vec3f( -3.1f, 4.2f, 0.0f), m_pmvMatUni, m_colorUni)
{ }
constexpr bool doRotate() const noexcept { return m_doRotate; }
constexpr void setDoRotate(bool rotate) noexcept { m_doRotate = rotate; }
constexpr void setClearBuffers(bool v) noexcept { m_clearBuffers = v; }
constexpr void setFlipVerticalInGLOrientation(bool v) noexcept { m_flipVerticalInGLOrientation = v; }
PMVMat4f& pmvMatrix() noexcept { return m_pmvMatUni->pmv(); }
const PMVMat4f& pmvMatrix() const noexcept { return m_pmvMatUni->pmv(); }
constexpr const jau::math::Recti& viewport() const noexcept { return m_viewport; }
constexpr Vec3f& pan() noexcept { return m_pan; }
constexpr jau::math::Vec3f& rotEuler() noexcept { return m_rotEuler; }
void setClearColor(const jau::math::Vec4f& clearColor) noexcept {
m_clearColor = clearColor;
}
void setGearsColors(const jau::math::Vec4f& gear1Color, const jau::math::Vec4f& gear2Color, const jau::math::Vec4f& gear3Color) noexcept {
m_gear1Color = gear1Color;
m_gear2Color = gear2Color;
m_gear3Color = gear3Color;
}
constexpr const jau::math::Vec3f& rotEuler() const noexcept { return m_rotEuler; }
void setZ(float zNear, float zFar, float zViewDist) {
m_zNear = zNear;
m_zFar = zFar;
m_zViewDist = zViewDist;
}
bool init(const WindowRef& win, const jau::fraction_timespec& when) override {
jau::fprintf_td(when.to_ms(), stdout, "RL::init: %s\n", toString().c_str());
GL& gl = GL::downcast(win->renderContext());
// m_st.setVerbose(true);
ShaderCodeRef vp0 = ShaderCode::create(gl, GL_VERTEX_SHADER, "demos/glsl",
"demos/glsl/bin", "SingleLight0");
ShaderCodeRef fp0 = ShaderCode::create(gl, GL_FRAGMENT_SHADER, "demos/glsl",
"demos/glsl/bin", "SingleLight0");
if( !vp0 || !fp0 ) {
jau::fprintf_td(when.to_ms(), stdout, "ERROR %s:%d: %s\n", E_FILE_LINE, toString().c_str());
win->dispose(when);
return false;
}
vp0->defaultShaderCustomization(gl);
fp0->defaultShaderCustomization(gl);
ShaderProgramRef sp0 = ShaderProgram::create();
if( !sp0->add(gl, vp0, true) || !sp0->add(gl, fp0, true) ) {
jau::fprintf_td(when.to_ms(), stdout, "ERROR %s:%d: %s\n", E_FILE_LINE, toString().c_str());
sp0->destroy(gl);
win->dispose(when);
return false;
}
m_st.attachShaderProgram(gl, sp0, true);
m_gear1.initGL(gl);
m_gear2.initGL(gl);
m_gear3.initGL(gl);
// st.attachObject("pmvMatrix", pmvMatrix);
m_st.ownUniform(m_pmvMatUni, true);
GLUniformVec3fRef lightU = GLUniformVec3f::create("gcu_Light0Pos", lightPos);
m_st.ownUniform(lightU, true);
m_st.ownUniform(m_colorUni, true);
m_st.pushAllUniforms(gl);
if( m_clearBuffers ) {
::glClearColor(m_clearColor.x, m_clearColor.y, m_clearColor.z, m_clearColor.w);
}
m_initialized = sp0->inUse();
m_st.useProgram(gl, false);
if( !m_initialized ) {
jau::fprintf_td(when.to_ms(), stdout, "ERROR %s:%d: %s\n", E_FILE_LINE, toString().c_str());
m_st.destroy(gl);
win->dispose(when);
}
return m_initialized;
}
void dispose(const WindowRef& win, const jau::fraction_timespec& when) override {
jau::fprintf_td(when.to_ms(), stdout, "RL::dispose: %s\n", toString().c_str());
jau::fprintf_td(when.to_ms(), stdout, "RL::dispose: %s\n", win->toString().c_str());
GL& gl = GL::downcast(win->renderContext());
m_st.useProgram(gl, false);
m_gear1.dispose(gl);
m_gear2.dispose(gl);
m_gear3.dispose(gl);
m_st.destroy(gl);
m_initialized = false;
}
void reshape(const WindowRef& win, const jau::math::Recti& viewport, const jau::fraction_timespec& when) override {
jau::fprintf_td(when.to_ms(), stdout, "RL::reshape: %s\n\t%s\n", toString().c_str(), m_pmvMatUni->pmv().toString().c_str());
if( !m_initialized ) { return; }
m_viewport = viewport;
reshapeImpl(win, viewport, float(viewport.width()), float(viewport.height()), when);
}
void reshapeImpl(const WindowRef& win, const jau::math::Recti& viewport, float imageWidth, float imageHeight, const jau::fraction_timespec& when) {
const bool msaa = false; // gl.getContext().getGLDrawable().getChosenGLCapabilities().getSampleBuffers();
jau::fprintf_td(when.to_ms(), stdout, "GearsES2.reshape %s of %fx%f, swapInterval %d, msaa %d, tileRendererInUse %d\n",
viewport.toString().c_str(), imageWidth, imageHeight, m_swapInterval, msaa, false);
GL& gl = GL::downcast(win->renderContext());
// compute projection parameters 'normal'
float left, right, bottom, top;
if( imageHeight > imageWidth ) {
const float a = imageHeight / imageWidth;
left = -1.0f;
right = 1.0f;
bottom = -a;
top = a;
} else {
const float a = imageWidth / imageHeight;
left = -a;
right = a;
bottom = -1.0f;
top = 1.0f;
}
const float w = right - left;
const float h = top - bottom;
// compute projection parameters 'tiled'
const float l = left + float(viewport.x()) * w / imageWidth;
const float r = l + float(viewport.width()) * w / imageWidth;
const float b = bottom + float(viewport.y()) * h / imageHeight;
const float t = b + float(viewport.height()) * h / imageHeight;
{
const float _w = r - l;
const float _h = t - b;
jau::fprintf_td(when.to_ms(), stdout, ">> GearsES2 angle %f, [l %f, r %f, b %f, t %f] %fx%f -> [l %f, r %f, b %f, t %f] %fx%f, v-flip %d",
m_teethAngle, left, right, bottom, top, w, h, l, r, b, t, _w, _h, m_flipVerticalInGLOrientation);
}
PMVMat4f& pmv = m_pmvMatUni->pmv();
if( m_flipVerticalInGLOrientation && win->isBLOriented() ) {
pmv.scaleP(1.0f, -1.0f, 1.0f);
}
pmv.frustumP(l, r, b, t, m_zNear, m_zFar);
pmv.translateMv(0.0f, 0.0f, -m_zViewDist);
m_st.useProgram(gl, true);
m_st.pushUniform(gl, m_pmvMatUni);
m_st.useProgram(gl, false);
}
static constexpr float getTeethRotation(int name, float adeg) noexcept {
switch(name) {
case 1: return jau::adeg_to_rad( 1.0f * adeg - 0.0f);
case 2: return jau::adeg_to_rad(-2.0f * adeg - 9.0f);
default: return jau::adeg_to_rad(-2.0f * adeg - 25.0f);
}
}
void display(const WindowRef& win, const jau::fraction_timespec&) override {
if( !m_initialized ) { return; }
// Turn the gears' teeth
if( m_doRotate ) {
m_teethAngle += 0.5f;
}
GL& gl = GL::downcast(win->renderContext());
// bool m_hasFocus = win->hasFocus();
if( m_clearBuffers ) {
::glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}
setGLStates(win, true);
m_st.useProgram(gl, true);
PMVMat4f& pmv = m_pmvMatUni->pmv();
pmv.pushMv();
pmv.translateMv(m_pan);
pmv.rotateMv(m_rotEuler.x, 1.0f, 0.0f, 0.0f);
pmv.rotateMv(m_rotEuler.y, 0.0f, 1.0f, 0.0f);
pmv.rotateMv(m_rotEuler.z, 0.0f, 0.0f, 1.0f);
m_gear1.draw(gl, getTeethRotation(1, m_teethAngle));
m_gear2.draw(gl, getTeethRotation(2, m_teethAngle));
m_gear3.draw(gl, getTeethRotation(3, m_teethAngle));
pmv.popMv();
m_st.useProgram(gl, false);
setGLStates(win, false);
}
/// Fast loop through all shapes using PointerShapeAction w/o matrix traversal using view-coordinates
GearsObjectES2* findPick(const PointerShapeAction& action, const PointerEvent& e, const WindowRef& win) {
// Sort gears in z-axis descending order
std::array<GearsObjectES2*, 3> gears{ &m_gear1, &m_gear2, &m_gear3 };
struct ZDescending {
bool operator()(GearsObjectES2* a, GearsObjectES2* b) const {
return a->viewBounds().high().z > b->viewBounds().high().z;
}
} zDescending;
std::sort(gears.begin(), gears.end(), zDescending); // NOLINT(modernize-use-ranges)
// We do not perform teeth-object rotation in object space for PointerEventAction!
GearsObjectES2* res = nullptr;
for(size_t i=0; !res && i<gears.size(); ++i) {
if( action(e, win, *gears[i]) ) {
res = gears[i];
}
}
return res;
}
/// Dispatch PointerShapeAction to given shape w/ matrix traversal
bool dispatchForShape(GearsObjectES2& shape, const PointerShapeAction& action, const PointerEvent& e, const WindowRef& win) {
PMVMat4f& pmv = m_pmvMatUni->pmv();
pmv.pushMv();
pmv.translateMv(m_pan);
pmv.rotateMv(m_rotEuler.x, 1.0f, 0.0f, 0.0f);
pmv.rotateMv(m_rotEuler.y, 0.0f, 1.0f, 0.0f);
pmv.rotateMv(m_rotEuler.z, 0.0f, 0.0f, 1.0f);
const bool res = shape.dispatchAction(action, e, win);
pmv.popMv();
return res;
}
private:
void setGLStates(const WindowRef& win, bool enable) {
// Culling only possible if we do not flip the projection matrix
const bool useCullFace = !(m_flipVerticalInGLOrientation && win->isBLOriented());
if( enable ) {
::glEnable(GL_DEPTH_TEST);
if( useCullFace ) {
::glEnable(GL_CULL_FACE);
}
} else {
::glDisable(GL_DEPTH_TEST);
if( useCullFace ) {
::glDisable(GL_CULL_FACE);
}
}
}
public:
std::string toStringImpl() const noexcept override {
std::string r("GearsES2[isInit ");
r.append(std::to_string(m_initialized).append(", usesShared ").append(std::to_string(false)))
.append(", 1 ")
.append(m_gear1.toString())
.append(", 2 ")
.append(m_gear2.toString())
.append(", 3 ")
.append(m_gear3.toString())
.append("]");
return r;
}
};
#endif // GAMP_DEMO_GEARSES02_HPP_
jau::function< bool(const PointerEvent &e, const WindowRef &win, GearsObjectES2 &shape)> PointerShapeAction
Definition GearsES2.hpp:49
#define E_FILE_LINE
GearsES2.
Definition GearsES2.hpp:379
void setZ(float zNear, float zFar, float zViewDist)
Definition GearsES2.hpp:442
constexpr void setClearBuffers(bool v) noexcept
Definition GearsES2.hpp:423
constexpr Vec3f & pan() noexcept
Definition GearsES2.hpp:428
constexpr bool doRotate() const noexcept
Definition GearsES2.hpp:421
constexpr void setDoRotate(bool rotate) noexcept
Definition GearsES2.hpp:422
constexpr void setFlipVerticalInGLOrientation(bool v) noexcept
Definition GearsES2.hpp:424
GearsObjectES2 * findPick(const PointerShapeAction &action, const PointerEvent &e, const WindowRef &win)
Fast loop through all shapes using PointerShapeAction w/o matrix traversal using view-coordinates.
Definition GearsES2.hpp:611
constexpr jau::math::Vec3f & rotEuler() noexcept
Definition GearsES2.hpp:429
std::string toStringImpl() const noexcept override
Definition GearsES2.hpp:663
static constexpr float getTeethRotation(int name, float adeg) noexcept
Definition GearsES2.hpp:569
constexpr const jau::math::Recti & viewport() const noexcept
Definition GearsES2.hpp:427
void reshapeImpl(const WindowRef &win, const jau::math::Recti &viewport, float imageWidth, float imageHeight, const jau::fraction_timespec &when)
Definition GearsES2.hpp:519
bool dispatchForShape(GearsObjectES2 &shape, const PointerShapeAction &action, const PointerEvent &e, const WindowRef &win)
Dispatch PointerShapeAction to given shape w/ matrix traversal.
Definition GearsES2.hpp:631
void setClearColor(const jau::math::Vec4f &clearColor) noexcept
Definition GearsES2.hpp:431
void display(const WindowRef &win, const jau::fraction_timespec &) override
Called by the drawable to initiate rendering by the client.
Definition GearsES2.hpp:577
void setGearsColors(const jau::math::Vec4f &gear1Color, const jau::math::Vec4f &gear2Color, const jau::math::Vec4f &gear3Color) noexcept
Definition GearsES2.hpp:435
PMVMat4f & pmvMatrix() noexcept
Definition GearsES2.hpp:425
void dispose(const WindowRef &win, const jau::fraction_timespec &when) override
Notifies the listener to perform the release of all renderer resources per context,...
Definition GearsES2.hpp:500
GearsObjectES2.
Definition GearsES2.hpp:55
std::string toString() const noexcept
Definition GearsES2.hpp:372
bool dispatchAction(const PointerShapeAction &action, const PointerEvent &e, const WindowRef &win)
Definition GearsES2.hpp:356
const jau::math::geom::AABBox3f & viewBounds() const noexcept
Definition GearsES2.hpp:369
const jau::math::geom::AABBox3f & objBounds() const noexcept
Definition GearsES2.hpp:368
constexpr int name() const noexcept
Definition GearsES2.hpp:371
static constexpr jau::math::Vec4f green
Definition GearsES2.hpp:58
GearsObjectES2(int name, ShaderState &st, const jau::math::Vec4f &gearColor, float inner_radius, float outer_radius, float width, GLsizei teeth, float tooth_depth, jau::math::Vec3f tx, GLUniformSyncPMVMat4fRef &pmvMatUni, GLUniformVec4fRef colorUniform)
Definition GearsES2.hpp:128
bool & picked() noexcept
Definition GearsES2.hpp:367
void dispose(GL &gl)
Definition GearsES2.hpp:302
const jau::math::Mat4f & matPMvi() const noexcept
Definition GearsES2.hpp:370
static constexpr jau::math::Vec4f red
Definition GearsES2.hpp:57
static constexpr jau::math::Vec4f blue
Definition GearsES2.hpp:59
static GLContext & downcast(RenderContext *rc)
Downcast dereferenced given RenderContext* to GLContext&, throws exception if signature doesn't match...
static server_ref createGLSLInterleaved(GLsizei compsPerElement, bool normalized, GLsizei initialElementCount, GLenum vboUsage)
static server_ref createGLSLInterleavedMapped(GLsizei compsPerElement, bool normalized, GLsizei mappedElementCount, GLenum vboUsage)
ShaderState allows to sharing data between shader programs, while updating the attribute and uniform ...
constexpr RenderListener(Private) noexcept
Private ctor for shared_ptr<RenderListener> instance method w/o public ctor.
Definition Window.hpp:60
std::string toString() const noexcept
Definition Window.hpp:112
Pointer event of type PointerType.
Class template jau::function is a general-purpose static-polymorphic function wrapper.
value_type z
Definition vec3f.hpp:68
Axis Aligned Bounding Box.
Definition aabbox3f.hpp:43
constexpr const Point3f & high() const noexcept
Returns the maximum right-top-near (xyz) coordinate.
Definition aabbox3f.hpp:99
constexpr PMVMatrix4 & scaleP(float x, float y, float z) noexcept
Scale the projection matrix.
Definition pmvmat4.hpp:704
void frustumP(const float left, const float right, const float bottom, const float top, const float zNear, const float zFar)
Multiply the projection matrix with the frustum matrix.
Definition pmvmat4.hpp:850
constexpr PMVMatrix4 & translateMv(float x, float y, float z) noexcept
Translate the modelview matrix.
Definition pmvmat4.hpp:641
constexpr_cxx26 PMVMatrix4 & rotateMv(const float ang_rad, const float x, const float y, const float z) noexcept
Rotate the modelview matrix by the given axis and angle in radians.
Definition pmvmat4.hpp:728
constexpr_cxx20 PMVMatrix4 & popMv() noexcept
Pop the modelview matrix from its stack.
Definition pmvmat4.hpp:795
constexpr PMVMatrix4 & loadMvIdentity() noexcept
Load the modelview matrix with the values of the given Mat4.
Definition pmvmat4.hpp:577
constexpr Mat4 & getPMvi() noexcept
Returns the pre-multiplied inverse projection x modelview, if Mat4#invert(Mat4) succeeded,...
Definition pmvmat4.hpp:1342
constexpr PMVMatrix4 & loadPIdentity() noexcept
Load the projection matrix with the values of the given Mat4.
Definition pmvmat4.hpp:586
constexpr Mat4 & getMv() noexcept
Returns the modelview matrix (Mv).
Definition pmvmat4.hpp:275
constexpr_cxx20 PMVMatrix4 & pushMv() noexcept
Push the modelview matrix to its stack, while preserving its values.
Definition pmvmat4.hpp:813
consteval_cxx20 std::string_view name() noexcept
constexpr T adeg_to_rad(const T arc_degree) noexcept
Converts arc-degree to radians.
@ std
Denotes a func::std_target_t.
std::shared_ptr< GLUniformSyncPMVMat4f > GLUniformSyncPMVMat4fRef
GLArrayDataServerRef< float > GLFloatArrayDataServerRef
std::shared_ptr< GLUniformVec4f > GLUniformVec4fRef
std::shared_ptr< GLUniformVec3f > GLUniformVec3fRef
std::shared_ptr< ShaderProgram > ShaderProgramRef
std::shared_ptr< ShaderCode > ShaderCodeRef
@ msaa
MSAA based Anti-Aliasing, a two pass region rendering, slower and more resource hungry (FBO with samp...
std::shared_ptr< Window > WindowRef
Definition Event.hpp:36
Matrix4< float > Mat4f
Definition mat4f.hpp:1968
Vector4F< float > Vec4f
Definition vec4f.hpp:360
PMVData
PMVMatrix4 derived matrices and values.
Definition pmvmat4.hpp:57
RectI< int > Recti
Definition recti.hpp:146
Vector3F< float > Vec3f
Definition vec3f.hpp:422
PMVMatrix4< float > PMVMat4f
Definition pmvmat4.hpp:1463
int fprintf_td(const uint64_t elapsed_ms, FILE *stream, const char *format,...) noexcept
Convenient fprintf() invocation, prepending the given elapsed_ms timestamp.
Definition debug.cpp:276
constexpr uint64_t to_ms() const noexcept
Returns time in milliseconds.