Gamp v0.0.8
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 WindowSRef& 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 GLUniformSyncPMVMat4f& m_pmvMatUni;
65 GLUniformVec4f& m_colorUniform;
66 jau::math::Vec4f m_gearColor;
68 bool m_useMappedBuffers;
69 bool m_picked;
70 jau::math::geom::AABBox3f m_objbox, m_viewbox;
71 jau::math::Mat4f m_PMvi;
72
77 GLFloatArrayDataServerSRef m_outwardFace;
78 GLFloatArrayDataServerSRef m_insideRadiusCyl;
79
80 private:
81 GLFloatArrayDataServerSRef createInterleaved(bool useMappedBuffers, GLsizei compsPerElem, bool normalized, GLsizei initialSize, GLenum vboUsage) {
82 if( useMappedBuffers ) {
83 return GLFloatArrayDataServer::createGLSLInterleavedMapped(compsPerElem, normalized, initialSize, vboUsage);
84 } else {
85 return GLFloatArrayDataServer::createGLSLInterleaved(compsPerElem, normalized, initialSize, vboUsage);
86 }
87 }
88
89 void addInterleavedVertexAndNormalArrays(GLFloatArrayDataServerSRef& array, GLsizei compsPerElem) {
90 array->addGLSLSubArray("gca_Vertex", compsPerElem, GL_ARRAY_BUFFER);
91 array->addGLSLSubArray("gca_Normal", compsPerElem, GL_ARRAY_BUFFER);
92 }
93
94 void vert(GLFloatArrayDataServerSRef& array, float x, float y, float z, const jau::math::Vec3f& n) {
95 array->put3f(x, y, z);
96 array->put3f(n);
97 m_objbox.resize(x, y, z);
98 }
99
100 static void sincos(float x, float sin[], int sinIdx, float cos[], int cosIdx) {
101 sin[sinIdx] = std::sin(x);
102 cos[cosIdx] = std::cos(x);
103 }
104
105 void initGL(GL& gl, GLFloatArrayDataServerSRef& array) {
106 array->enableBuffer(gl, true);
107 array->enableBuffer(gl, false);
108 }
109
110 void associate(ShaderState& st) {
111 m_frontFace->associate(st, true);
112 m_frontSide->associate(st, true);
113 m_backFace->associate(st, true);
114 m_backSide->associate(st, true);
115 m_outwardFace->associate(st, true);
116 m_insideRadiusCyl->associate(st, true);
117 }
118
119 void draw(GL& gl, GLFloatArrayDataServerSRef& array, int mode) {
120 if( 0 < array->vboName() ) {
121 array->enableBuffer(gl, true);
122 ::glDrawArrays(mode, 0, array->elemCount());
123 array->enableBuffer(gl, false);
124 }
125 }
126
127 public:
129 float inner_radius, float outer_radius,
130 float width,
131 GLsizei teeth,
132 float tooth_depth,
134 GLUniformSyncPMVMat4f &pmvMatUni, GLUniformVec4f &colorUniform)
135 : m_name(name), m_st(st), m_pmvMatUni(pmvMatUni),
136 m_colorUniform(colorUniform), m_gearColor(gearColor), m_tx(tx),
137 m_useMappedBuffers(false), m_picked(false), m_objbox(), m_viewbox(), m_PMvi() {
138 const float dz = width * 0.5f;
139 float u, v, len;
140 float s[5];
141 float c[5];
142 jau::math::Vec3f normal;
143 // const int tris_per_tooth = 32;
144
145 const float r0 = inner_radius;
146 const float r1 = outer_radius - tooth_depth / 2.0f;
147 const float r2 = outer_radius + tooth_depth / 2.0f;
148
149 const float da = 2.0f * std::numbers::pi_v<float> / float(teeth) / 4.0f;
150
151 s[4] = 0; // sin(0f)
152 c[4] = 1; // cos(0f)
153
154 const GLenum vboUsage = GL_STATIC_DRAW;
155
156 m_frontFace = createInterleaved(m_useMappedBuffers, 6, false, 4 * teeth + 2, vboUsage);
157 addInterleavedVertexAndNormalArrays(m_frontFace, 3);
158 m_backFace = createInterleaved(m_useMappedBuffers, 6, false, 4 * teeth + 2, vboUsage);
159 addInterleavedVertexAndNormalArrays(m_backFace, 3);
160 m_frontSide = createInterleaved(m_useMappedBuffers, 6, false, 6 * teeth, vboUsage);
161 addInterleavedVertexAndNormalArrays(m_frontSide, 3);
162 m_backSide = createInterleaved(m_useMappedBuffers, 6, false, 6 * teeth, vboUsage);
163 addInterleavedVertexAndNormalArrays(m_backSide, 3);
164 m_outwardFace = createInterleaved(m_useMappedBuffers, 6, false, 4 * 4 * teeth + 2, vboUsage);
165 addInterleavedVertexAndNormalArrays(m_outwardFace, 3);
166 m_insideRadiusCyl = createInterleaved(m_useMappedBuffers, 6, false, 2 * teeth + 2, vboUsage);
167 addInterleavedVertexAndNormalArrays(m_insideRadiusCyl, 3);
168
169 for( GLsizei i = 0; i < teeth; i++ ) {
170 const float angle = float(i) * 2.0f * std::numbers::pi_v<float> / float(teeth);
171 sincos(angle + da * 0.0f, s, 0, c, 0);
172 sincos(angle + da * 1.0f, s, 1, c, 1);
173 sincos(angle + da * 2.0f, s, 2, c, 2);
174 sincos(angle + da * 3.0f, s, 3, c, 3);
175
176 /* front */
177 normal = jau::math::Vec3f(0, 0, 1);
178
179 /* front face - GL.GL_TRIANGLE_STRIP */
180 vert(m_frontFace, r0 * c[0], r0 * s[0], dz, normal);
181 vert(m_frontFace, r1 * c[0], r1 * s[0], dz, normal);
182 vert(m_frontFace, r0 * c[0], r0 * s[0], dz, normal);
183 vert(m_frontFace, r1 * c[3], r1 * s[3], dz, normal);
184
185 /* front sides of teeth - GL.GL_TRIANGLES */
186 vert(m_frontSide, r1 * c[0], r1 * s[0], dz, normal);
187 vert(m_frontSide, r2 * c[1], r2 * s[1], dz, normal);
188 vert(m_frontSide, r2 * c[2], r2 * s[2], dz, normal);
189 vert(m_frontSide, r1 * c[0], r1 * s[0], dz, normal);
190 vert(m_frontSide, r2 * c[2], r2 * s[2], dz, normal);
191 vert(m_frontSide, r1 * c[3], r1 * s[3], dz, normal);
192
193 /* back */
194 normal = jau::math::Vec3f(0, 0, -1);
195
196 /* back face - GL.GL_TRIANGLE_STRIP */
197 vert(m_backFace, r1 * c[0], r1 * s[0], -dz, normal);
198 vert(m_backFace, r0 * c[0], r0 * s[0], -dz, normal);
199 vert(m_backFace, r1 * c[3], r1 * s[3], -dz, normal);
200 vert(m_backFace, r0 * c[0], r0 * s[0], -dz, normal);
201
202 /* back sides of teeth - GL.GL_TRIANGLES*/
203 vert(m_backSide, r1 * c[3], r1 * s[3], -dz, normal);
204 vert(m_backSide, r2 * c[2], r2 * s[2], -dz, normal);
205 vert(m_backSide, r2 * c[1], r2 * s[1], -dz, normal);
206 vert(m_backSide, r1 * c[3], r1 * s[3], -dz, normal);
207 vert(m_backSide, r2 * c[1], r2 * s[1], -dz, normal);
208 vert(m_backSide, r1 * c[0], r1 * s[0], -dz, normal);
209
210 /* outward faces of teeth */
211 u = r2 * c[1] - r1 * c[0];
212 v = r2 * s[1] - r1 * s[0];
213 len = std::sqrt(u * u + v * v);
214 u /= len;
215 v /= len;
216 normal = jau::math::Vec3f(v, -u, 0);
217
218 vert(m_outwardFace, r1 * c[0], r1 * s[0], dz, normal);
219 vert(m_outwardFace, r1 * c[0], r1 * s[0], -dz, normal);
220 vert(m_outwardFace, r2 * c[1], r2 * s[1], dz, normal);
221 vert(m_outwardFace, r2 * c[1], r2 * s[1], -dz, normal);
222
223 normal[0] = c[0];
224 normal[1] = s[0];
225 vert(m_outwardFace, r2 * c[1], r2 * s[1], dz, normal);
226 vert(m_outwardFace, r2 * c[1], r2 * s[1], -dz, normal);
227 vert(m_outwardFace, r2 * c[2], r2 * s[2], dz, normal);
228 vert(m_outwardFace, r2 * c[2], r2 * s[2], -dz, normal);
229
230 normal[0] = (r1 * s[3] - r2 * s[2]);
231 normal[1] = (r1 * c[3] - r2 * c[2]) * -1.0f;
232 vert(m_outwardFace, r2 * c[2], r2 * s[2], dz, normal);
233 vert(m_outwardFace, r2 * c[2], r2 * s[2], -dz, normal);
234 vert(m_outwardFace, r1 * c[3], r1 * s[3], dz, normal);
235 vert(m_outwardFace, r1 * c[3], r1 * s[3], -dz, normal);
236
237 normal[0] = c[0];
238 normal[1] = s[0];
239 vert(m_outwardFace, r1 * c[3], r1 * s[3], dz, normal);
240 vert(m_outwardFace, r1 * c[3], r1 * s[3], -dz, normal);
241 vert(m_outwardFace, r1 * c[0], r1 * s[0], dz, normal);
242 vert(m_outwardFace, r1 * c[0], r1 * s[0], -dz, normal);
243
244 /* inside radius cylinder */
245 normal[0] = c[0] * -1.0f;
246 normal[1] = s[0] * -1.0f;
247 normal[2] = 0.0f;
248 vert(m_insideRadiusCyl, r0 * c[0], r0 * s[0], -dz, normal);
249 vert(m_insideRadiusCyl, r0 * c[0], r0 * s[0], dz, normal);
250 }
251 /* finish front face */
252 normal[0] = 0.0f;
253 normal[1] = 0.0f;
254 normal[2] = 1.0f;
255 vert(m_frontFace, r0 * c[4], r0 * s[4], dz, normal);
256 vert(m_frontFace, r1 * c[4], r1 * s[4], dz, normal);
257 m_frontFace->seal(true);
258
259 /* finish back face */
260 normal[2] = -1.0f;
261 vert(m_backFace, r1 * c[4], r1 * s[4], -dz, normal);
262 vert(m_backFace, r0 * c[4], r0 * s[4], -dz, normal);
263 m_backFace->seal(true);
264
265 m_backSide->seal(true);
266 m_frontSide->seal(true);
267
268 /* finish outward face */
269 sincos(da * 1.0f, s, 1, c, 1);
270 u = r2 * c[1] - r1 * c[4];
271 v = r2 * s[1] - r1 * s[4];
272 len = std::sqrt(u * u + v * v);
273 u /= len;
274 v /= len;
275 normal[0] = v;
276 normal[1] = -u;
277 normal[2] = 0.0f;
278 vert(m_outwardFace, r1 * c[4], r1 * s[4], dz, normal);
279 vert(m_outwardFace, r1 * c[4], r1 * s[4], -dz, normal);
280 m_outwardFace->seal(true);
281
282 /* finish inside radius cylinder */
283 normal[0] = c[4] * -1.0f;
284 normal[1] = s[4] * -1.0f;
285 normal[2] = 0.0f;
286 vert(m_insideRadiusCyl, r0 * c[4], r0 * s[4], -dz, normal);
287 vert(m_insideRadiusCyl, r0 * c[4], r0 * s[4], dz, normal);
288 m_insideRadiusCyl->seal(true);
289
290 associate(m_st);
291 }
292
293 void initGL(GL& gl) {
294 /** Init VBO and data .. */
295 initGL(gl, m_frontFace);
296 initGL(gl, m_frontSide);
297 initGL(gl, m_backFace);
298 initGL(gl, m_backSide);
299 initGL(gl, m_outwardFace);
300 initGL(gl, m_insideRadiusCyl);
301 }
302 void dispose(GL& gl) {
303 // could be already destroyed by shared configuration
304 if( m_frontFace ) {
305 m_frontFace->destroy(gl);
306 }
307 if( m_frontSide ) {
308 m_frontSide->destroy(gl);
309 }
310 if( m_backFace ) {
311 m_backFace->destroy(gl);
312 }
313 if( m_backSide ) {
314 m_backSide->destroy(gl);
315 }
316 if( m_outwardFace ) {
317 m_outwardFace->destroy(gl);
318 }
319 if( m_insideRadiusCyl ) {
320 m_insideRadiusCyl->destroy(gl);
321 }
322 m_frontFace = nullptr;
323 m_frontSide = nullptr;
324 m_backFace = nullptr;
325 m_backSide = nullptr;
326 m_outwardFace = nullptr;
327 m_insideRadiusCyl = nullptr;
328 }
329
330 void draw(GL& gl, float ang_rad) {
331 PMVMat4f& pmv = m_pmvMatUni.pmv();
332 pmv.pushMv();
333 pmv.translateMv(m_tx);
334 m_objbox.transform(pmv.getMv(), m_viewbox); // view-box for findPick
335 pmv.rotateMv(ang_rad, 0.0f, 0.0f, 1.0f);
336 m_st.send(gl, m_pmvMatUni); // 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.send(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 = pmv.getPMvi();
354 pmv.popMv();
355 }
356 bool dispatchAction(const PointerShapeAction& action, const PointerEvent& e, const WindowSRef& win) {
357 PMVMat4f& pmv = m_pmvMatUni.pmv();
358 pmv.pushMv();
359 pmv.translateMv(m_tx);
360
361 const bool done = action(e, win, *this);
362
363 pmv.popMv();
364 return done;
365 }
366
367 bool& picked() noexcept { return m_picked; }
368 const jau::math::geom::AABBox3f& objBounds() const noexcept { return m_objbox; }
369 const jau::math::geom::AABBox3f& viewBounds() const noexcept { return m_viewbox; }
370 const jau::math::Mat4f& matPMvi() const noexcept { return m_PMvi; }
371 constexpr int name() const noexcept { return m_name; }
372 std::string toString() const noexcept { return std::string("GearsObjES2[").append(std::to_string(m_name).append(", view ").append(m_viewbox.toString())).append("]"); }
373};
374
375/**
376 * GearsES2
377 * @author Brian Paul (converted to C++ and added pixel-lightning by Sven Gothel)
378 */
379class GearsES2 : public RenderListener {
380 private:
381 constexpr static jau::math::Vec3f lightPos = jau::math::Vec3f(5.0f, 5.0f, 10.0f);
382 constexpr static PMVData mat_req = PMVData::inv_proj | PMVData::inv_mv | PMVData::inv_tps_mv;
383
384 ShaderState m_st;
385 GLUniformSyncPMVMat4f m_pmvMatUni;
386 GLUniformVec4f m_colorUni;
387 GLUniformVec3f m_lightU;
388 jau::math::Vec4f m_gear1Color, m_gear2Color, m_gear3Color;
389 GearsObjectES2 m_gear1, m_gear2, m_gear3;
390
391 jau::math::Recti m_viewport;
393 Vec3f m_pan;
394 /// in angle degrees
395 float m_teethAngle = 0.0f;
396 int m_swapInterval = 1;
397
398 bool m_flipVerticalInGLOrientation = false;
399 bool m_doRotate = true;
400 jau::math::Vec4f m_clearColor = jau::math::Vec4f(0.0f);
401 bool m_clearBuffers = true;
402 bool m_initialized = false;
403
404 float m_zNear = 5.0f;
405 float m_zFar = 10000.0f;
406 float m_zViewDist = 40.0f;
407
408 public:
411 m_st(),
412 m_pmvMatUni("gcu_PMVMatrix", mat_req), // P, Mv, Mvi and Mvit
413 m_colorUni("gcu_StaticColor", GearsObjectES2::red),
414 m_lightU("gcu_Light0Pos", lightPos),
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_pmvMatUni, m_colorUni),
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_pmvMatUni, m_colorUni),
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_pmvMatUni, m_colorUni)
421 {
422 m_st.manage(m_pmvMatUni);
423
424 m_st.manage(m_lightU);
425 m_st.manage(m_colorUni);
426 }
427
428 constexpr bool doRotate() const noexcept { return m_doRotate; }
429 constexpr void setDoRotate(bool rotate) noexcept { m_doRotate = rotate; }
430 constexpr void setClearBuffers(bool v) noexcept { m_clearBuffers = v; }
431 constexpr void setFlipVerticalInGLOrientation(bool v) noexcept { m_flipVerticalInGLOrientation = v; }
432 PMVMat4f& pmvMatrix() noexcept { return m_pmvMatUni.pmv(); }
433 const PMVMat4f& pmvMatrix() const noexcept { return m_pmvMatUni.pmv(); }
434 constexpr const jau::math::Recti& viewport() const noexcept { return m_viewport; }
435 constexpr Vec3f& pan() noexcept { return m_pan; }
436 constexpr jau::math::Vec3f& rotEuler() noexcept { return m_rotEuler; }
437
438 void setClearColor(const jau::math::Vec4f& clearColor) noexcept {
439 m_clearColor = clearColor;
440 }
441
442 void setGearsColors(const jau::math::Vec4f& gear1Color, const jau::math::Vec4f& gear2Color, const jau::math::Vec4f& gear3Color) noexcept {
443 m_gear1Color = gear1Color;
444 m_gear2Color = gear2Color;
445 m_gear3Color = gear3Color;
446 }
447 constexpr const jau::math::Vec3f& rotEuler() const noexcept { return m_rotEuler; }
448
449 void setZ(float zNear, float zFar, float zViewDist) {
450 m_zNear = zNear;
451 m_zFar = zFar;
452 m_zViewDist = zViewDist;
453 }
454
455 bool init(const WindowSRef& win, const jau::fraction_timespec& when) override {
456 jau::fprintf_td(when.to_ms(), stdout, "RL::init: %s\n", toString().c_str());
457 GL& gl = GL::downcast(win->renderContext());
458
459 // m_st.setVerbose(true);
460 ShaderCodeSRef vp0 = ShaderCode::create(gl, GL_VERTEX_SHADER, "demos/glsl",
461 "demos/glsl/bin", "SingleLight0");
462 ShaderCodeSRef fp0 = ShaderCode::create(gl, GL_FRAGMENT_SHADER, "demos/glsl",
463 "demos/glsl/bin", "SingleLight0");
464 if( !vp0 || !fp0 ) {
465 jau::fprintf_td(when.to_ms(), stdout, "ERROR %s:%d: %s\n", E_FILE_LINE, toString().c_str());
466 win->dispose(when);
467 return false;
468 }
472 if( !sp0->add(gl, vp0, true) || !sp0->add(gl, fp0, true) ) {
473 jau::fprintf_td(when.to_ms(), stdout, "ERROR %s:%d: %s\n", E_FILE_LINE, toString().c_str());
474 sp0->destroy(gl);
475 win->dispose(when);
476 return false;
477 }
478 m_st.attachShaderProgram(gl, sp0, true);
479
480 m_gear1.initGL(gl);
481 m_gear2.initGL(gl);
482 m_gear3.initGL(gl);
483
484 m_st.send(gl, m_pmvMatUni);
485 m_st.send(gl, m_colorUni);
486 m_st.send(gl, m_lightU);
487
488 if( m_clearBuffers ) {
489 ::glClearColor(m_clearColor.x, m_clearColor.y, m_clearColor.z, m_clearColor.w);
490 }
491 m_initialized = sp0->inUse();
492 m_st.useProgram(gl, false);
493
494 if( !m_initialized ) {
495 jau::fprintf_td(when.to_ms(), stdout, "ERROR %s:%d: %s\n", E_FILE_LINE, toString().c_str());
496 m_st.destroy(gl);
497 win->dispose(when);
498 }
499 return m_initialized;
500 }
501
502 void dispose(const WindowSRef& win, const jau::fraction_timespec& when) override {
503 jau::fprintf_td(when.to_ms(), stdout, "RL::dispose: %s\n", toString().c_str());
504 jau::fprintf_td(when.to_ms(), stdout, "RL::dispose: %s\n", win->toString().c_str());
505 GL& gl = GL::downcast(win->renderContext());
506 m_st.useProgram(gl, false);
507 m_gear1.dispose(gl);
508 m_gear2.dispose(gl);
509 m_gear3.dispose(gl);
510 m_st.destroy(gl);
511 m_initialized = false;
512 }
513
514 void reshape(const WindowSRef& win, const jau::math::Recti& viewport, const jau::fraction_timespec& when) override {
515 jau::fprintf_td(when.to_ms(), stdout, "RL::reshape: %s\n\t%s\n", toString().c_str(), m_pmvMatUni.pmv().toString().c_str());
516 if( !m_initialized ) { return; }
517 m_viewport = viewport;
518 reshapeImpl(win, viewport, float(viewport.width()), float(viewport.height()), when);
519 }
520
521 void reshapeImpl(const WindowSRef& win, const jau::math::Recti& viewport, float imageWidth, float imageHeight, const jau::fraction_timespec& when) {
522 const bool msaa = false; // gl.getContext().getGLDrawable().getChosenGLCapabilities().getSampleBuffers();
523 jau::fprintf_td(when.to_ms(), stdout, "GearsES2.reshape %s of %fx%f, swapInterval %d, msaa %d, tileRendererInUse %d\n",
524 viewport.toString().c_str(), imageWidth, imageHeight, m_swapInterval, msaa, false);
525 GL& gl = GL::downcast(win->renderContext());
526 // compute projection parameters 'normal'
527 float left, right, bottom, top;
528 if( imageHeight > imageWidth ) {
529 const float a = imageHeight / imageWidth;
530 left = -1.0f;
531 right = 1.0f;
532 bottom = -a;
533 top = a;
534 } else {
535 const float a = imageWidth / imageHeight;
536 left = -a;
537 right = a;
538 bottom = -1.0f;
539 top = 1.0f;
540 }
541 const float w = right - left;
542 const float h = top - bottom;
543
544 // compute projection parameters 'tiled'
545 const float l = left + float(viewport.x()) * w / imageWidth;
546 const float r = l + float(viewport.width()) * w / imageWidth;
547 const float b = bottom + float(viewport.y()) * h / imageHeight;
548 const float t = b + float(viewport.height()) * h / imageHeight;
549 {
550 const float _w = r - l;
551 const float _h = t - b;
552 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",
553 m_teethAngle, left, right, bottom, top, w, h, l, r, b, t, _w, _h, m_flipVerticalInGLOrientation);
554 }
555
556 PMVMat4f& pmv = m_pmvMatUni.pmv();
557 pmv.loadPIdentity();
558 if( m_flipVerticalInGLOrientation && win->isBLOriented() ) {
559 pmv.scaleP(1.0f, -1.0f, 1.0f);
560 }
561 pmv.frustumP(l, r, b, t, m_zNear, m_zFar);
562
563 pmv.loadMvIdentity();
564 pmv.translateMv(0.0f, 0.0f, -m_zViewDist);
565
566 m_st.useProgram(gl, true);
567 m_st.send(gl, m_pmvMatUni);
568 m_st.useProgram(gl, false);
569 }
570
571 static constexpr float getTeethRotation(int name, float adeg) noexcept {
572 switch(name) {
573 case 1: return jau::adeg_to_rad( 1.0f * adeg - 0.0f);
574 case 2: return jau::adeg_to_rad(-2.0f * adeg - 9.0f);
575 default: return jau::adeg_to_rad(-2.0f * adeg - 25.0f);
576 }
577 }
578
579 void display(const WindowSRef& win, const jau::fraction_timespec&) override {
580 if( !m_initialized ) { return; }
581
582 // Turn the gears' teeth
583 if( m_doRotate ) {
584 m_teethAngle += 0.5f;
585 }
586 GL& gl = GL::downcast(win->renderContext());
587 // bool m_hasFocus = win->hasFocus();
588
589 if( m_clearBuffers ) {
590 ::glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
591 }
592
593 setGLStates(win, true);
594
595 m_st.useProgram(gl, true);
596 PMVMat4f& pmv = m_pmvMatUni.pmv();
597 pmv.pushMv();
598 pmv.translateMv(m_pan);
599 pmv.rotateMv(m_rotEuler.x, 1.0f, 0.0f, 0.0f);
600 pmv.rotateMv(m_rotEuler.y, 0.0f, 1.0f, 0.0f);
601 pmv.rotateMv(m_rotEuler.z, 0.0f, 0.0f, 1.0f);
602
603 m_gear1.draw(gl, getTeethRotation(1, m_teethAngle));
604 m_gear2.draw(gl, getTeethRotation(2, m_teethAngle));
605 m_gear3.draw(gl, getTeethRotation(3, m_teethAngle));
606 pmv.popMv();
607 m_st.useProgram(gl, false);
608
609 setGLStates(win, false);
610 }
611
612 /// Fast loop through all shapes using PointerShapeAction w/o matrix traversal using view-coordinates
613 GearsObjectES2* findPick(const PointerShapeAction& action, const PointerEvent& e, const WindowSRef& win) {
614 // Sort gears in z-axis descending order
615 std::array<GearsObjectES2*, 3> gears{ &m_gear1, &m_gear2, &m_gear3 };
616 struct ZDescending {
617 bool operator()(GearsObjectES2* a, GearsObjectES2* b) const {
618 return a->viewBounds().high().z > b->viewBounds().high().z;
619 }
620 } zDescending;
621 std::sort(gears.begin(), gears.end(), zDescending); // NOLINT(modernize-use-ranges)
622
623 // We do not perform teeth-object rotation in object space for PointerEventAction!
624 GearsObjectES2* res = nullptr;
625 for(size_t i=0; !res && i<gears.size(); ++i) {
626 if( action(e, win, *gears[i]) ) {
627 res = gears[i];
628 }
629 }
630 return res;
631 }
632 /// Dispatch PointerShapeAction to given shape w/ matrix traversal
633 bool dispatchForShape(GearsObjectES2& shape, const PointerShapeAction& action, const PointerEvent& e, const WindowSRef& win) {
634 PMVMat4f& pmv = m_pmvMatUni.pmv();
635 pmv.pushMv();
636 pmv.translateMv(m_pan);
637 pmv.rotateMv(m_rotEuler.x, 1.0f, 0.0f, 0.0f);
638 pmv.rotateMv(m_rotEuler.y, 0.0f, 1.0f, 0.0f);
639 pmv.rotateMv(m_rotEuler.z, 0.0f, 0.0f, 1.0f);
640
641 const bool res = shape.dispatchAction(action, e, win);
642
643 pmv.popMv();
644 return res;
645 }
646
647 private:
648 void setGLStates(const WindowSRef& 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 WindowSRef &win, GearsObjectES2 &shape)> PointerShapeAction
Definition GearsES2.hpp:49
void setZ(float zNear, float zFar, float zViewDist)
Definition GearsES2.hpp:449
void display(const WindowSRef &win, const jau::fraction_timespec &) override
Called by the drawable to initiate rendering by the client.
Definition GearsES2.hpp:579
void reshapeImpl(const WindowSRef &win, const jau::math::Recti &viewport, float imageWidth, float imageHeight, const jau::fraction_timespec &when)
Definition GearsES2.hpp:521
constexpr void setClearBuffers(bool v) noexcept
Definition GearsES2.hpp:430
constexpr Vec3f & pan() noexcept
Definition GearsES2.hpp:435
void dispose(const WindowSRef &win, const jau::fraction_timespec &when) override
Notifies the listener to perform the release of all renderer resources per context,...
Definition GearsES2.hpp:502
bool init(const WindowSRef &win, const jau::fraction_timespec &when) override
Called by the drawable immediately after the render context is initialized.
Definition GearsES2.hpp:455
constexpr bool doRotate() const noexcept
Definition GearsES2.hpp:428
constexpr void setDoRotate(bool rotate) noexcept
Definition GearsES2.hpp:429
constexpr const jau::math::Vec3f & rotEuler() const noexcept
Definition GearsES2.hpp:447
GearsObjectES2 * findPick(const PointerShapeAction &action, const PointerEvent &e, const WindowSRef &win)
Fast loop through all shapes using PointerShapeAction w/o matrix traversal using view-coordinates.
Definition GearsES2.hpp:613
constexpr void setFlipVerticalInGLOrientation(bool v) noexcept
Definition GearsES2.hpp:431
const PMVMat4f & pmvMatrix() const noexcept
Definition GearsES2.hpp:433
bool dispatchForShape(GearsObjectES2 &shape, const PointerShapeAction &action, const PointerEvent &e, const WindowSRef &win)
Dispatch PointerShapeAction to given shape w/ matrix traversal.
Definition GearsES2.hpp:633
constexpr jau::math::Vec3f & rotEuler() noexcept
Definition GearsES2.hpp:436
void reshape(const WindowSRef &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:514
std::string toStringImpl() const noexcept override
Definition GearsES2.hpp:665
static constexpr float getTeethRotation(int name, float adeg) noexcept
Definition GearsES2.hpp:571
constexpr const jau::math::Recti & viewport() const noexcept
Definition GearsES2.hpp:434
void setClearColor(const jau::math::Vec4f &clearColor) noexcept
Definition GearsES2.hpp:438
void setGearsColors(const jau::math::Vec4f &gear1Color, const jau::math::Vec4f &gear2Color, const jau::math::Vec4f &gear3Color) noexcept
Definition GearsES2.hpp:442
PMVMat4f & pmvMatrix() noexcept
Definition GearsES2.hpp:432
GearsObjectES2.
Definition GearsES2.hpp:55
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, GLUniformSyncPMVMat4f &pmvMatUni, GLUniformVec4f &colorUniform)
Definition GearsES2.hpp:128
std::string toString() const noexcept
Definition GearsES2.hpp:372
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
bool & picked() noexcept
Definition GearsES2.hpp:367
void dispose(GL &gl)
Definition GearsES2.hpp:302
bool dispatchAction(const PointerShapeAction &action, const PointerEvent &e, const WindowSRef &win)
Definition GearsES2.hpp:356
void initGL(GL &gl)
Definition GearsES2.hpp:293
const jau::math::Mat4f & matPMvi() const noexcept
Definition GearsES2.hpp:370
void draw(GL &gl, float ang_rad)
Definition GearsES2.hpp:330
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_sref createGLSLInterleaved(GLsizei compsPerElement, bool normalized, GLsizei initialElementCount, GLenum vboUsage)
static server_sref createGLSLInterleavedMapped(GLsizei compsPerElement, bool normalized, GLsizei mappedElementCount, GLenum vboUsage)
size_t defaultShaderCustomization(const GL &gl, bool preludeVersion=true, bool addDefaultPrecision=true, bool addDefaultDefines=true)
Default customization of this shader source code.
static ShaderCodeSRef create(GLenum type, size_t count, const source_list_t &sources)
static ShaderProgramSRef create() noexcept
void destroy(GL &gl) noexcept
Detaches all shader codes and deletes the program.
bool add(const ShaderCodeSRef &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:131
constexpr bool isBLOriented() const noexcept
Returns true if this surface is rendered in OpenGL's coordinate system, origin at bottom left.
Definition Surface.hpp:174
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: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
#define E_FILE_LINE
constexpr T adeg_to_rad(const T arc_degree) noexcept
Converts arc-degree to radians.
GLArrayDataServerSRef< float > GLFloatArrayDataServerSRef
std::shared_ptr< ShaderCode > ShaderCodeSRef
std::shared_ptr< ShaderProgram > ShaderProgramSRef
std::shared_ptr< Window > WindowSRef
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
@ inv_mv
Bit value for inverse modelview matrix (Mvi), updated via update().
Definition pmvmat4.hpp:60
@ inv_proj
Bit value for inverse projection matrix (Pi), updated via update().
Definition pmvmat4.hpp:64
@ inv_tps_mv
Bit value for inverse transposed modelview matrix (Mvit), updated via update().
Definition pmvmat4.hpp:62
ssize_t fprintf_td(const uint64_t elapsed_ms, FILE *stream, std::string_view format, const Args &...args) noexcept
Convenient secure fprintf() invocation, prepending the given elapsed_ms timestamp and using jau:forma...
Definition debug.hpp:188
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.