Gamp v0.0.7-36-g24b1eb6
Gamp: Graphics, Audio, Multimedia and Processing
Loading...
Searching...
No Matches
GearsES2.hpp
Go to the documentation of this file.
1/*
2 * Author: Sven Gothel <sgothel@jausoft.com>
3 * Copyright Gothel Software e.K.
4 *
5 * SPDX-License-Identifier: MIT
6 *
7 * This Source Code Form is subject to the terms of the MIT License
8 * If a copy of the MIT was not distributed with this file,
9 * you can obtain one at https://opensource.org/license/mit/.
10 */
11
12#ifndef GAMP_DEMOS_GEARSES02_HPP_
13#define GAMP_DEMOS_GEARSES02_HPP_
14
15#include <cmath>
16#include <cstdio>
17#include <memory>
18#include <numbers>
19
20#include <gamp/GampTypes.hpp>
29
30#include <jau/basic_types.hpp>
31#include <jau/debug.hpp>
32#include <jau/float_math.hpp>
33#include <jau/functional.hpp>
34#include <jau/math/mat4f.hpp>
35#include <jau/math/vec2f.hpp>
36#include <jau/math/vec3f.hpp>
39
40using namespace jau::math;
41using namespace jau::math::util;
42
43using namespace gamp::wt;
44using namespace gamp::wt::event;
45using namespace gamp::render::gl::glsl;
46using namespace gamp::render::gl::data;
47
48class GearsObjectES2;
49typedef jau::function<bool(const PointerEvent& e, const WindowRef& win, GearsObjectES2& shape)> PointerShapeAction;
50
51/**
52 * GearsObjectES2
53 * @author Brian Paul (converted to C++ and added pixel-lightning by Sven Gothel)
54 */
56 public:
57 constexpr static jau::math::Vec4f red = jau::math::Vec4f(0.8f, 0.1f, 0.0f, 0.7f);
58 constexpr static jau::math::Vec4f green = jau::math::Vec4f(0.0f, 0.8f, 0.2f, 0.7f);
59 constexpr static jau::math::Vec4f blue = jau::math::Vec4f(0.2f, 0.2f, 1.0f, 0.7f);
60
61 private:
62 int m_name;
63 ShaderState& m_st;
64 PMVMat4f& m_pmvMatrix;
65 GLUniformDataRef m_pmvMatrixUniform;
66 GLUniformVec4fRef m_colorUniform;
67 jau::math::Vec4f m_gearColor;
69 bool m_useMappedBuffers;
70 bool m_picked;
71 jau::math::geom::AABBox3f m_objbox, m_viewbox;
72 jau::math::Mat4f m_PMvi;
73
74 GLFloatArrayDataServerRef m_frontFace;
75 GLFloatArrayDataServerRef m_frontSide;
78 GLFloatArrayDataServerRef m_outwardFace;
79 GLFloatArrayDataServerRef m_insideRadiusCyl;
80
81 private:
82 GLFloatArrayDataServerRef createInterleaved(bool useMappedBuffers, GLsizei compsPerElem, bool normalized, GLsizei initialSize, GLenum vboUsage) {
83 if( useMappedBuffers ) {
84 return GLFloatArrayDataServer::createGLSLInterleavedMapped(compsPerElem, normalized, initialSize, vboUsage);
85 } else {
86 return GLFloatArrayDataServer::createGLSLInterleaved(compsPerElem, normalized, initialSize, vboUsage);
87 }
88 }
89
90 void addInterleavedVertexAndNormalArrays(GLFloatArrayDataServerRef& array, GLsizei compsPerElem) {
91 array->addGLSLSubArray("mgl_Vertex", compsPerElem, GL_ARRAY_BUFFER);
92 array->addGLSLSubArray("mgl_Normal", compsPerElem, GL_ARRAY_BUFFER);
93 }
94
95 void vert(GLFloatArrayDataServerRef& array, float x, float y, float z, const jau::math::Vec3f& n) {
96 array->put3f(x, y, z);
97 array->put3f(n);
98 m_objbox.resize(x, y, z);
99 }
100
101 static void sincos(float x, float sin[], int sinIdx, float cos[], int cosIdx) {
102 sin[sinIdx] = std::sin(x);
103 cos[cosIdx] = std::cos(x);
104 }
105
106 void initGL(GL& gl, GLFloatArrayDataServerRef& array) {
107 array->enableBuffer(gl, true);
108 array->enableBuffer(gl, false);
109 }
110
111 void associate(ShaderState& st) {
112 m_frontFace->associate(st, true);
113 m_frontSide->associate(st, true);
114 m_backFace->associate(st, true);
115 m_backSide->associate(st, true);
116 m_outwardFace->associate(st, true);
117 m_insideRadiusCyl->associate(st, true);
118 }
119
120 void draw(GL& gl, GLFloatArrayDataServerRef& array, int mode) {
121 if( 0 < array->vboName() ) {
122 array->enableBuffer(gl, true);
123 ::glDrawArrays(mode, 0, array->elemCount());
124 array->enableBuffer(gl, false);
125 }
126 }
127
128 public:
130 float inner_radius, float outer_radius,
131 float width,
132 GLsizei teeth,
133 float tooth_depth,
135 PMVMat4f& pmvMatrix, GLUniformDataRef pmvMatrixUniform, GLUniformVec4fRef colorUniform)
136 : m_name(name), m_st(st), m_pmvMatrix(pmvMatrix), m_pmvMatrixUniform(std::move(pmvMatrixUniform)),
137 m_colorUniform(std::move(colorUniform)), m_gearColor(gearColor), m_tx(tx),
138 m_useMappedBuffers(false), m_picked(false), m_objbox(), m_viewbox(), m_PMvi() {
139 const float dz = width * 0.5f;
140 float u, v, len;
141 float s[5];
142 float c[5];
143 jau::math::Vec3f normal;
144 // const int tris_per_tooth = 32;
145
146 const float r0 = inner_radius;
147 const float r1 = outer_radius - tooth_depth / 2.0f;
148 const float r2 = outer_radius + tooth_depth / 2.0f;
149
150 const float da = 2.0f * std::numbers::pi_v<float> / float(teeth) / 4.0f;
151
152 s[4] = 0; // sin(0f)
153 c[4] = 1; // cos(0f)
154
155 const GLenum vboUsage = GL_STATIC_DRAW;
156
157 m_frontFace = createInterleaved(m_useMappedBuffers, 6, false, 4 * teeth + 2, vboUsage);
158 addInterleavedVertexAndNormalArrays(m_frontFace, 3);
159 m_backFace = createInterleaved(m_useMappedBuffers, 6, false, 4 * teeth + 2, vboUsage);
160 addInterleavedVertexAndNormalArrays(m_backFace, 3);
161 m_frontSide = createInterleaved(m_useMappedBuffers, 6, false, 6 * teeth, vboUsage);
162 addInterleavedVertexAndNormalArrays(m_frontSide, 3);
163 m_backSide = createInterleaved(m_useMappedBuffers, 6, false, 6 * teeth, vboUsage);
164 addInterleavedVertexAndNormalArrays(m_backSide, 3);
165 m_outwardFace = createInterleaved(m_useMappedBuffers, 6, false, 4 * 4 * teeth + 2, vboUsage);
166 addInterleavedVertexAndNormalArrays(m_outwardFace, 3);
167 m_insideRadiusCyl = createInterleaved(m_useMappedBuffers, 6, false, 2 * teeth + 2, vboUsage);
168 addInterleavedVertexAndNormalArrays(m_insideRadiusCyl, 3);
169
170 for( GLsizei i = 0; i < teeth; i++ ) {
171 const float angle = float(i) * 2.0f * std::numbers::pi_v<float> / float(teeth);
172 sincos(angle + da * 0.0f, s, 0, c, 0);
173 sincos(angle + da * 1.0f, s, 1, c, 1);
174 sincos(angle + da * 2.0f, s, 2, c, 2);
175 sincos(angle + da * 3.0f, s, 3, c, 3);
176
177 /* front */
178 normal = jau::math::Vec3f(0, 0, 1);
179
180 /* front face - GL.GL_TRIANGLE_STRIP */
181 vert(m_frontFace, r0 * c[0], r0 * s[0], dz, normal);
182 vert(m_frontFace, r1 * c[0], r1 * s[0], dz, normal);
183 vert(m_frontFace, r0 * c[0], r0 * s[0], dz, normal);
184 vert(m_frontFace, r1 * c[3], r1 * s[3], dz, normal);
185
186 /* front sides of teeth - GL.GL_TRIANGLES */
187 vert(m_frontSide, r1 * c[0], r1 * s[0], dz, normal);
188 vert(m_frontSide, r2 * c[1], r2 * s[1], dz, normal);
189 vert(m_frontSide, r2 * c[2], r2 * s[2], dz, normal);
190 vert(m_frontSide, r1 * c[0], r1 * s[0], dz, normal);
191 vert(m_frontSide, r2 * c[2], r2 * s[2], dz, normal);
192 vert(m_frontSide, r1 * c[3], r1 * s[3], dz, normal);
193
194 /* back */
195 normal = jau::math::Vec3f(0, 0, -1);
196
197 /* back face - GL.GL_TRIANGLE_STRIP */
198 vert(m_backFace, r1 * c[0], r1 * s[0], -dz, normal);
199 vert(m_backFace, r0 * c[0], r0 * s[0], -dz, normal);
200 vert(m_backFace, r1 * c[3], r1 * s[3], -dz, normal);
201 vert(m_backFace, r0 * c[0], r0 * s[0], -dz, normal);
202
203 /* back sides of teeth - GL.GL_TRIANGLES*/
204 vert(m_backSide, r1 * c[3], r1 * s[3], -dz, normal);
205 vert(m_backSide, r2 * c[2], r2 * s[2], -dz, normal);
206 vert(m_backSide, r2 * c[1], r2 * s[1], -dz, normal);
207 vert(m_backSide, r1 * c[3], r1 * s[3], -dz, normal);
208 vert(m_backSide, r2 * c[1], r2 * s[1], -dz, normal);
209 vert(m_backSide, r1 * c[0], r1 * s[0], -dz, normal);
210
211 /* outward faces of teeth */
212 u = r2 * c[1] - r1 * c[0];
213 v = r2 * s[1] - r1 * s[0];
214 len = std::sqrt(u * u + v * v);
215 u /= len;
216 v /= len;
217 normal = jau::math::Vec3f(v, -u, 0);
218
219 vert(m_outwardFace, r1 * c[0], r1 * s[0], dz, normal);
220 vert(m_outwardFace, r1 * c[0], r1 * s[0], -dz, normal);
221 vert(m_outwardFace, r2 * c[1], r2 * s[1], dz, normal);
222 vert(m_outwardFace, r2 * c[1], r2 * s[1], -dz, normal);
223
224 normal[0] = c[0];
225 normal[1] = s[0];
226 vert(m_outwardFace, r2 * c[1], r2 * s[1], dz, normal);
227 vert(m_outwardFace, r2 * c[1], r2 * s[1], -dz, normal);
228 vert(m_outwardFace, r2 * c[2], r2 * s[2], dz, normal);
229 vert(m_outwardFace, r2 * c[2], r2 * s[2], -dz, normal);
230
231 normal[0] = (r1 * s[3] - r2 * s[2]);
232 normal[1] = (r1 * c[3] - r2 * c[2]) * -1.0f;
233 vert(m_outwardFace, r2 * c[2], r2 * s[2], dz, normal);
234 vert(m_outwardFace, r2 * c[2], r2 * s[2], -dz, normal);
235 vert(m_outwardFace, r1 * c[3], r1 * s[3], dz, normal);
236 vert(m_outwardFace, r1 * c[3], r1 * s[3], -dz, normal);
237
238 normal[0] = c[0];
239 normal[1] = s[0];
240 vert(m_outwardFace, r1 * c[3], r1 * s[3], dz, normal);
241 vert(m_outwardFace, r1 * c[3], r1 * s[3], -dz, normal);
242 vert(m_outwardFace, r1 * c[0], r1 * s[0], dz, normal);
243 vert(m_outwardFace, r1 * c[0], r1 * s[0], -dz, normal);
244
245 /* inside radius cylinder */
246 normal[0] = c[0] * -1.0f;
247 normal[1] = s[0] * -1.0f;
248 normal[2] = 0.0f;
249 vert(m_insideRadiusCyl, r0 * c[0], r0 * s[0], -dz, normal);
250 vert(m_insideRadiusCyl, r0 * c[0], r0 * s[0], dz, normal);
251 }
252 /* finish front face */
253 normal[0] = 0.0f;
254 normal[1] = 0.0f;
255 normal[2] = 1.0f;
256 vert(m_frontFace, r0 * c[4], r0 * s[4], dz, normal);
257 vert(m_frontFace, r1 * c[4], r1 * s[4], dz, normal);
258 m_frontFace->seal(true);
259
260 /* finish back face */
261 normal[2] = -1.0f;
262 vert(m_backFace, r1 * c[4], r1 * s[4], -dz, normal);
263 vert(m_backFace, r0 * c[4], r0 * s[4], -dz, normal);
264 m_backFace->seal(true);
265
266 m_backSide->seal(true);
267 m_frontSide->seal(true);
268
269 /* finish outward face */
270 sincos(da * 1.0f, s, 1, c, 1);
271 u = r2 * c[1] - r1 * c[4];
272 v = r2 * s[1] - r1 * s[4];
273 len = std::sqrt(u * u + v * v);
274 u /= len;
275 v /= len;
276 normal[0] = v;
277 normal[1] = -u;
278 normal[2] = 0.0f;
279 vert(m_outwardFace, r1 * c[4], r1 * s[4], dz, normal);
280 vert(m_outwardFace, r1 * c[4], r1 * s[4], -dz, normal);
281 m_outwardFace->seal(true);
282
283 /* finish inside radius cylinder */
284 normal[0] = c[4] * -1.0f;
285 normal[1] = s[4] * -1.0f;
286 normal[2] = 0.0f;
287 vert(m_insideRadiusCyl, r0 * c[4], r0 * s[4], -dz, normal);
288 vert(m_insideRadiusCyl, r0 * c[4], r0 * s[4], dz, normal);
289 m_insideRadiusCyl->seal(true);
290
291 associate(m_st);
292 }
293
294 void initGL(GL& gl) {
295 /** Init VBO and data .. */
296 initGL(gl, m_frontFace);
297 initGL(gl, m_frontSide);
298 initGL(gl, m_backFace);
299 initGL(gl, m_backSide);
300 initGL(gl, m_outwardFace);
301 initGL(gl, m_insideRadiusCyl);
302 }
303 void dispose(GL& gl) {
304 // could be already destroyed by shared configuration
305 if( m_frontFace ) {
306 m_frontFace->destroy(gl);
307 }
308 if( m_frontSide ) {
309 m_frontSide->destroy(gl);
310 }
311 if( m_backFace ) {
312 m_backFace->destroy(gl);
313 }
314 if( m_backSide ) {
315 m_backSide->destroy(gl);
316 }
317 if( m_outwardFace ) {
318 m_outwardFace->destroy(gl);
319 }
320 if( m_insideRadiusCyl ) {
321 m_insideRadiusCyl->destroy(gl);
322 }
323 m_frontFace = nullptr;
324 m_frontSide = nullptr;
325 m_backFace = nullptr;
326 m_backSide = nullptr;
327 m_outwardFace = nullptr;
328 m_insideRadiusCyl = nullptr;
329 }
330
331 void draw(GL& gl, float ang_rad) {
332 m_pmvMatrix.pushMv();
333 m_pmvMatrix.translateMv(m_tx);
334 m_objbox.transform(m_pmvMatrix.getMv(), m_viewbox); // view-box for findPick
335 m_pmvMatrix.rotateMv(ang_rad, 0.0f, 0.0f, 1.0f);
336 m_st.pushUniform(gl, m_pmvMatrixUniform); // automatic sync + update of Mvi + Mvit
337
338 if( m_picked ) {
339 const float gray = ( m_gearColor.x + m_gearColor.y + m_gearColor.z ) / 3.0f;
340 m_colorUniform->vec4f() = jau::math::Vec4f(gray, gray, gray, m_gearColor.w);
341 } else {
342 m_colorUniform->vec4f() = m_gearColor;
343 }
344 m_st.pushUniform(gl, m_colorUniform);
345
346 draw(gl, m_frontFace, GL_TRIANGLE_STRIP);
347 draw(gl, m_frontSide, GL_TRIANGLES);
348 draw(gl, m_backFace, GL_TRIANGLE_STRIP);
349 draw(gl, m_backSide, GL_TRIANGLES);
350 draw(gl, m_outwardFace, GL_TRIANGLE_STRIP);
351 draw(gl, m_insideRadiusCyl, GL_TRIANGLE_STRIP);
352
353 m_PMvi = m_pmvMatrix.getPMvi();
354 m_pmvMatrix.popMv();
355 }
356 bool dispatchAction(const PointerShapeAction& action, const PointerEvent& e, const WindowRef& win) {
357 m_pmvMatrix.pushMv();
358 m_pmvMatrix.translateMv(m_tx);
359
360 const bool done = action(e, win, *this);
361
362 m_pmvMatrix.popMv();
363 return done;
364 }
365
366 bool& picked() noexcept { return m_picked; }
367 const jau::math::geom::AABBox3f& objBounds() const noexcept { return m_objbox; }
368 const jau::math::geom::AABBox3f& viewBounds() const noexcept { return m_viewbox; }
369 const jau::math::Mat4f& matPMvi() const noexcept { return m_PMvi; }
370 constexpr int name() const noexcept { return m_name; }
371 std::string toString() const noexcept { return std::string("GearsObjES2[").append(std::to_string(m_name).append(", view ").append(m_viewbox.toString())).append("]"); }
372};
373
374/**
375 * GearsES2
376 * @author Brian Paul (converted to C++ and added pixel-lightning by Sven Gothel)
377 */
378class GearsES2 : public RenderListener {
379 private:
380 constexpr static jau::math::Vec3f lightPos = jau::math::Vec3f(5.0f, 5.0f, 10.0f);
381
382 ShaderState m_st;
383 PMVMat4f m_pmvMatrix;
384 GLUniformSyncMatrices4fRef m_pmvMatrixUniform;
385 GLUniformVec4fRef m_colorUniform;
386 bool m_useMappedBuffers;
387 jau::math::Vec4f m_gear1Color, m_gear2Color, m_gear3Color;
388 GearsObjectES2 m_gear1, m_gear2, m_gear3;
389
390 jau::math::Recti m_viewport;
392 Vec3f m_pan;
393 /// in angle degrees
394 float m_teethAngle = 0.0f;
395 int m_swapInterval = 1;
396
397 bool m_flipVerticalInGLOrientation = false;
398 bool m_doRotate = true;
399 jau::math::Vec4f m_clearColor = jau::math::Vec4f(0.0f);
400 bool m_clearBuffers = true;
401 bool m_initialized = false;
402
403 float m_zNear = 5.0f;
404 float m_zFar = 10000.0f;
405 float m_zViewDist = 40.0f;
406
407 public:
410 m_st(),
411 m_pmvMatrix(PMVMat4f::INVERSE_PROJECTION | PMVMat4f::INVERSE_MODELVIEW | PMVMat4f::INVERSE_TRANSPOSED_MODELVIEW),
412 m_pmvMatrixUniform(GLUniformSyncMatrices4f::create("mgl_PMVMatrix", m_pmvMatrix.getSyncPMvMviMvit())), // P, Mv, Mvi and Mvit
413 m_colorUniform(GLUniformVec4f::create("mgl_StaticColor", GearsObjectES2::red)),
414 m_useMappedBuffers(false),
415 m_gear1Color(GearsObjectES2::red),
416 m_gear2Color(GearsObjectES2::green),
417 m_gear3Color(GearsObjectES2::blue),
418 m_gear1(1, m_st, m_gear1Color, 1.0f, 4.0f, 1.0f, 20, 0.7f, Vec3f( -3.0f, -2.0f, 0.0f), m_pmvMatrix, m_pmvMatrixUniform, m_colorUniform),
419 m_gear2(2, m_st, m_gear2Color, 0.5f, 2.0f, 2.0f, 10, 0.7f, Vec3f( 3.1f, -2.0f, 0.0f), m_pmvMatrix, m_pmvMatrixUniform, m_colorUniform),
420 m_gear3(3, m_st, m_gear3Color, 1.3f, 2.0f, 0.5f, 10, 0.7f, Vec3f( -3.1f, 4.2f, 0.0f), m_pmvMatrix, m_pmvMatrixUniform, m_colorUniform)
421 { }
422
423 constexpr bool doRotate() const noexcept { return m_doRotate; }
424 constexpr void setDoRotate(bool rotate) noexcept { m_doRotate = rotate; }
425 constexpr void setClearBuffers(bool v) noexcept { m_clearBuffers = v; }
426 constexpr void setFlipVerticalInGLOrientation(bool v) noexcept { m_flipVerticalInGLOrientation = v; }
427 constexpr PMVMat4f& pmvMatrix() noexcept { return m_pmvMatrix; }
428 constexpr const PMVMat4f& pmvMatrix() const noexcept { return m_pmvMatrix; }
429 constexpr const jau::math::Recti& viewport() const noexcept { return m_viewport; }
430 constexpr Vec3f& pan() noexcept { return m_pan; }
431 constexpr jau::math::Vec3f& rotEuler() noexcept { return m_rotEuler; }
432
433 void setClearColor(const jau::math::Vec4f& clearColor) noexcept {
434 m_clearColor = clearColor;
435 }
436
437 void setGearsColors(const jau::math::Vec4f& gear1Color, const jau::math::Vec4f& gear2Color, const jau::math::Vec4f& gear3Color) noexcept {
438 m_gear1Color = gear1Color;
439 m_gear2Color = gear2Color;
440 m_gear3Color = gear3Color;
441 }
442 constexpr const jau::math::Vec3f& rotEuler() const noexcept { return m_rotEuler; }
443 constexpr bool usingMappedBuffers() const noexcept { return m_useMappedBuffers; }
444
445 void setZ(float zNear, float zFar, float zViewDist) {
446 m_zNear = zNear;
447 m_zFar = zFar;
448 m_zViewDist = zViewDist;
449 }
450 const PMVMat4f& getPMVMatrix() const noexcept { return m_pmvMatrix; }
451
452 bool init(const WindowRef& win, const jau::fraction_timespec& when) override {
453 jau::fprintf_td(when.to_ms(), stdout, "RL::init: %s\n", toString().c_str());
454 GL& gl = GL::downcast(win->renderContext());
455
456 // m_st.setVerbose(true);
457 ShaderCodeRef vp0 = ShaderCode::create(gl, GL_VERTEX_SHADER, "demos/glsl",
458 "demos/glsl/bin", "SingleLight0");
459 ShaderCodeRef fp0 = ShaderCode::create(gl, GL_FRAGMENT_SHADER, "demos/glsl",
460 "demos/glsl/bin", "SingleLight0");
461 if( !vp0 || !fp0 ) {
462 jau::fprintf_td(when.to_ms(), stdout, "ERROR %s:%d: %s\n", E_FILE_LINE, toString().c_str());
463 win->dispose(when);
464 return false;
465 }
466 vp0->defaultShaderCustomization(gl, true, true);
467 fp0->defaultShaderCustomization(gl, true, true);
469 if( !sp0->add(gl, vp0, true) || !sp0->add(gl, fp0, true) ) {
470 jau::fprintf_td(when.to_ms(), stdout, "ERROR %s:%d: %s\n", E_FILE_LINE, toString().c_str());
471 sp0->destroy(gl);
472 win->dispose(when);
473 return false;
474 }
475 m_st.attachShaderProgram(gl, sp0, true);
476
477 m_gear1.initGL(gl);
478 m_gear2.initGL(gl);
479 m_gear3.initGL(gl);
480
481 // st.attachObject("pmvMatrix", pmvMatrix);
482 m_st.ownUniform(m_pmvMatrixUniform, true);
483
484 GLUniformVec3fRef lightU = GLUniformVec3f::create("mgl_LightPos", lightPos);
485 m_st.ownUniform(lightU, true);
486
487 m_colorUniform = GLUniformVec4f::create("color", GearsObjectES2::red);
488 m_st.ownUniform(m_colorUniform, true);
489 m_st.pushAllUniforms(gl);
490
491 if( m_clearBuffers ) {
492 ::glClearColor(m_clearColor.x, m_clearColor.y, m_clearColor.z, m_clearColor.w);
493 }
494 m_initialized = sp0->inUse();
495 m_st.useProgram(gl, false);
496
497 if( !m_initialized ) {
498 jau::fprintf_td(when.to_ms(), stdout, "ERROR %s:%d: %s\n", E_FILE_LINE, toString().c_str());
499 m_st.destroy(gl);
500 win->dispose(when);
501 }
502 return m_initialized;
503 }
504
505 void dispose(const WindowRef& win, const jau::fraction_timespec& when) override {
506 jau::fprintf_td(when.to_ms(), stdout, "RL::dispose: %s\n", toString().c_str());
507 jau::fprintf_td(when.to_ms(), stdout, "RL::dispose: %s\n", win->toString().c_str());
508 GL& gl = GL::downcast(win->renderContext());
509 m_st.useProgram(gl, false);
510 m_gear1.dispose(gl);
511 m_gear2.dispose(gl);
512 m_gear3.dispose(gl);
513 m_st.destroy(gl);
514 m_initialized = false;
515 }
516
517 void reshape(const WindowRef& win, const jau::math::Recti& viewport, const jau::fraction_timespec& when) override {
518 jau::fprintf_td(when.to_ms(), stdout, "RL::reshape: %s\n", toString().c_str());
519 if( !m_initialized ) { return; }
520 m_viewport = viewport;
521 reshapeImpl(win, viewport, float(viewport.width()), float(viewport.height()), when);
522 }
523
524 void reshapeImpl(const WindowRef& win, const jau::math::Recti& viewport, float imageWidth, float imageHeight, const jau::fraction_timespec& when) {
525 const bool msaa = false; // gl.getContext().getGLDrawable().getChosenGLCapabilities().getSampleBuffers();
526 jau::fprintf_td(when.to_ms(), stdout, "GearsES2.reshape %s of %fx%f, swapInterval %d, msaa %d, tileRendererInUse %d\n",
527 viewport.toString().c_str(), imageWidth, imageHeight, m_swapInterval, msaa, false);
528 GL& gl = GL::downcast(win->renderContext());
529 // compute projection parameters 'normal'
530 float left, right, bottom, top;
531 if( imageHeight > imageWidth ) {
532 const float a = (float)imageHeight / (float)imageWidth;
533 left = -1.0f;
534 right = 1.0f;
535 bottom = -a;
536 top = a;
537 } else {
538 const float a = (float)imageWidth / (float)imageHeight;
539 left = -a;
540 right = a;
541 bottom = -1.0f;
542 top = 1.0f;
543 }
544 const float w = right - left;
545 const float h = top - bottom;
546
547 // compute projection parameters 'tiled'
548 const float l = left + float(viewport.x()) * w / imageWidth;
549 const float r = l + float(viewport.width()) * w / imageWidth;
550 const float b = bottom + float(viewport.y()) * h / imageHeight;
551 const float t = b + float(viewport.height()) * h / imageHeight;
552 {
553 const float _w = r - l;
554 const float _h = t - b;
555 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",
556 m_teethAngle, left, right, bottom, top, w, h, l, r, b, t, _w, _h, m_flipVerticalInGLOrientation);
557 }
558
559 m_pmvMatrix.loadPIdentity();
560 if( m_flipVerticalInGLOrientation && win->isBLOriented() ) {
561 m_pmvMatrix.scaleP(1.0f, -1.0f, 1.0f);
562 }
563 m_pmvMatrix.frustumP(l, r, b, t, m_zNear, m_zFar);
564
565 m_pmvMatrix.loadMvIdentity();
566 m_pmvMatrix.translateMv(0.0f, 0.0f, -m_zViewDist);
567
568 m_st.useProgram(gl, true);
569 m_st.pushUniform(gl, m_pmvMatrixUniform);
570 m_st.useProgram(gl, false);
571 }
572
573 static constexpr float getTeethRotation(int name, float adeg) noexcept {
574 switch(name) {
575 case 1: return jau::adeg_to_rad( 1.0f * adeg - 0.0f);
576 case 2: return jau::adeg_to_rad(-2.0f * adeg - 9.0f);
577 default: return jau::adeg_to_rad(-2.0f * adeg - 25.0f);
578 }
579 }
580
581 void display(const WindowRef& win, const jau::fraction_timespec&) override {
582 if( !m_initialized ) { return; }
583
584 // Turn the gears' teeth
585 if( m_doRotate ) {
586 m_teethAngle += 0.5f;
587 }
588 GL& gl = GL::downcast(win->renderContext());
589 // bool m_hasFocus = win->hasFocus();
590
591 if( m_clearBuffers ) {
592 ::glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
593 }
594
595 setGLStates(win, true);
596
597 m_st.useProgram(gl, true);
598 m_pmvMatrix.pushMv();
599 m_pmvMatrix.translateMv(m_pan);
600 m_pmvMatrix.rotateMv(m_rotEuler.x, 1.0f, 0.0f, 0.0f);
601 m_pmvMatrix.rotateMv(m_rotEuler.y, 0.0f, 1.0f, 0.0f);
602 m_pmvMatrix.rotateMv(m_rotEuler.z, 0.0f, 0.0f, 1.0f);
603
604 m_gear1.draw(gl, getTeethRotation(1, m_teethAngle));
605 m_gear2.draw(gl, getTeethRotation(2, m_teethAngle));
606 m_gear3.draw(gl, getTeethRotation(3, m_teethAngle));
607 m_pmvMatrix.popMv();
608 m_st.useProgram(gl, false);
609
610 setGLStates(win, false);
611 }
612
613 /// Fast loop through all shapes using PointerShapeAction w/o matrix traversal using view-coordinates
614 GearsObjectES2* findPick(const PointerShapeAction& action, const PointerEvent& e, const WindowRef& win) {
615 // Sort gears in z-axis descending order
616 std::array<GearsObjectES2*, 3> gears{ &m_gear1, &m_gear2, &m_gear3 };
617 struct ZDescending {
618 bool operator()(GearsObjectES2* a, GearsObjectES2* b) const {
619 return a->viewBounds().high().z > b->viewBounds().high().z;
620 }
621 } zDescending;
622 std::sort(gears.begin(), gears.end(), zDescending);
623
624 // We do not perform teeth-object rotation in object space for PointerEventAction!
625 GearsObjectES2* res = nullptr;
626 for(size_t i=0; !res && i<gears.size(); ++i) {
627 if( action(e, win, *gears[i]) ) {
628 res = gears[i];
629 }
630 }
631 return res;
632 }
633 /// Dispatch PointerShapeAction to given shape w/ matrix traversal
634 bool dispatchForShape(GearsObjectES2& shape, const PointerShapeAction& action, const PointerEvent& e, const WindowRef& win) {
635 m_pmvMatrix.pushMv();
636 m_pmvMatrix.translateMv(m_pan);
637 m_pmvMatrix.rotateMv(m_rotEuler.x, 1.0f, 0.0f, 0.0f);
638 m_pmvMatrix.rotateMv(m_rotEuler.y, 0.0f, 1.0f, 0.0f);
639 m_pmvMatrix.rotateMv(m_rotEuler.z, 0.0f, 0.0f, 1.0f);
640
641 const bool res = shape.dispatchAction(action, e, win);
642
643 m_pmvMatrix.popMv();
644 return res;
645 }
646
647 private:
648 void setGLStates(const WindowRef& win, bool enable) {
649 // Culling only possible if we do not flip the projection matrix
650 const bool useCullFace = !(m_flipVerticalInGLOrientation && win->isBLOriented());
651 if( enable ) {
652 ::glEnable(GL_DEPTH_TEST);
653 if( useCullFace ) {
654 ::glEnable(GL_CULL_FACE);
655 }
656 } else {
657 ::glDisable(GL_DEPTH_TEST);
658 if( useCullFace ) {
659 ::glDisable(GL_CULL_FACE);
660 }
661 }
662 }
663
664 public:
665 std::string toStringImpl() const noexcept override {
666 std::string r("GearsES2[isInit ");
667 r.append(std::to_string(m_initialized).append(", usesShared ").append(std::to_string(false)))
668 .append(", 1 ")
669 .append(m_gear1.toString())
670 .append(", 2 ")
671 .append(m_gear2.toString())
672 .append(", 3 ")
673 .append(m_gear3.toString())
674 .append("]");
675 return r;
676 }
677};
678
679#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
void setZ(float zNear, float zFar, float zViewDist)
Definition GearsES2.hpp:445
constexpr void setClearBuffers(bool v) noexcept
Definition GearsES2.hpp:425
constexpr Vec3f & pan() noexcept
Definition GearsES2.hpp:430
bool init(const WindowRef &win, const jau::fraction_timespec &when) override
Called by the drawable immediately after the render context is initialized.
Definition GearsES2.hpp:452
constexpr bool doRotate() const noexcept
Definition GearsES2.hpp:423
const PMVMat4f & getPMVMatrix() const noexcept
Definition GearsES2.hpp:450
constexpr void setDoRotate(bool rotate) noexcept
Definition GearsES2.hpp:424
constexpr const jau::math::Vec3f & rotEuler() const noexcept
Definition GearsES2.hpp:442
constexpr void setFlipVerticalInGLOrientation(bool v) noexcept
Definition GearsES2.hpp:426
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:614
constexpr jau::math::Vec3f & rotEuler() noexcept
Definition GearsES2.hpp:431
std::string toStringImpl() const noexcept override
Definition GearsES2.hpp:665
static constexpr float getTeethRotation(int name, float adeg) noexcept
Definition GearsES2.hpp:573
void reshape(const WindowRef &win, const jau::math::Recti &viewport, const jau::fraction_timespec &when) override
Called by the drawable during the first repaint after the component has been resized.
Definition GearsES2.hpp:517
constexpr const PMVMat4f & pmvMatrix() const noexcept
Definition GearsES2.hpp:428
constexpr const jau::math::Recti & viewport() const noexcept
Definition GearsES2.hpp:429
constexpr bool usingMappedBuffers() const noexcept
Definition GearsES2.hpp:443
void reshapeImpl(const WindowRef &win, const jau::math::Recti &viewport, float imageWidth, float imageHeight, const jau::fraction_timespec &when)
Definition GearsES2.hpp:524
bool dispatchForShape(GearsObjectES2 &shape, const PointerShapeAction &action, const PointerEvent &e, const WindowRef &win)
Dispatch PointerShapeAction to given shape w/ matrix traversal.
Definition GearsES2.hpp:634
void setClearColor(const jau::math::Vec4f &clearColor) noexcept
Definition GearsES2.hpp:433
void display(const WindowRef &win, const jau::fraction_timespec &) override
Called by the drawable to initiate rendering by the client.
Definition GearsES2.hpp:581
void setGearsColors(const jau::math::Vec4f &gear1Color, const jau::math::Vec4f &gear2Color, const jau::math::Vec4f &gear3Color) noexcept
Definition GearsES2.hpp:437
constexpr PMVMat4f & pmvMatrix() noexcept
Definition GearsES2.hpp:427
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:505
GearsObjectES2.
Definition GearsES2.hpp:55
std::string toString() const noexcept
Definition GearsES2.hpp:371
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:368
const jau::math::geom::AABBox3f & objBounds() const noexcept
Definition GearsES2.hpp:367
constexpr int name() const noexcept
Definition GearsES2.hpp:370
static constexpr jau::math::Vec4f green
Definition GearsES2.hpp:58
bool & picked() noexcept
Definition GearsES2.hpp:366
void dispose(GL &gl)
Definition GearsES2.hpp:303
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, PMVMat4f &pmvMatrix, GLUniformDataRef pmvMatrixUniform, GLUniformVec4fRef colorUniform)
Definition GearsES2.hpp:129
void initGL(GL &gl)
Definition GearsES2.hpp:294
const jau::math::Mat4f & matPMvi() const noexcept
Definition GearsES2.hpp:369
void draw(GL &gl, float ang_rad)
Definition GearsES2.hpp:331
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)
static std::shared_ptr< GLUniformVec3f > create(const string_t &name, const jau::math::Vec3f &v)
static std::shared_ptr< GLUniformVec4f > create(const string_t &name, const jau::math::Vec4f &v)
size_t defaultShaderCustomization(const GL &gl, bool preludeVersion, bool addDefaultPrecision)
Default customization of this shader source code.
static ShaderCodeRef create(GLenum type, size_t count, const source_list_t &sources) noexcept
void destroy(GL &gl) noexcept
Detaches all shader codes and deletes the program.
static ShaderProgramRef create() noexcept
bool add(const ShaderCodeRef &shaderCode) noexcept
Adds a new shader to this program.
constexpr bool inUse() const noexcept
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
const gamp::render::RenderContext * renderContext() const noexcept
Definition Surface.hpp:129
constexpr bool isBLOriented() const noexcept
Returns true if this surface is rendered in OpenGL's coordinate system, origin at bottom left.
Definition Surface.hpp:168
void dispose(const jau::fraction_timespec &when) noexcept override
Definition Window.hpp:355
std::string toString() const noexcept
Definition gamp_wt.cpp:145
Pointer event of type PointerType.
Class template jau::function is a general-purpose static-polymorphic function wrapper.
value_type z
Definition vec3f.hpp:71
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
consteval_cxx20 std::string_view name() noexcept
constexpr T adeg_to_rad(const T arc_degree) noexcept
Converts arc-degree to radians.
GLArrayDataServerRef< float > GLFloatArrayDataServerRef
std::shared_ptr< GLUniformSyncMatrices4f > GLUniformSyncMatrices4fRef
std::shared_ptr< GLUniformData > GLUniformDataRef
std::shared_ptr< GLUniformVec4f > GLUniformVec4fRef
std::shared_ptr< GLUniformVec3f > GLUniformVec3fRef
std::shared_ptr< ShaderProgram > ShaderProgramRef
std::shared_ptr< ShaderCode > ShaderCodeRef
std::shared_ptr< Window > WindowRef
Definition Event.hpp:36
Matrix4< float > Mat4f
Definition mat4f.hpp:1973
Vector4F< float > Vec4f
Definition vec4f.hpp:375
RectI< int > Recti
Definition recti.hpp:139
Vector3F< float > Vec3f
Definition vec3f.hpp:436
PMVMatrix4< float > PMVMat4f
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:270
STL namespace.
Timespec structure using int64_t for its components in analogy to struct timespec_t on 64-bit platfor...
constexpr uint64_t to_ms() const noexcept
Returns time in milliseconds.