Gamp v0.0.7-67-g7798ac4
Gamp: Graphics, Audio, Multimedia and Processing
Loading...
Searching...
No Matches
Primitives03.cpp
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#include <algorithm>
13#include <cstdio>
14#include <cmath>
15#include <gamp/graph/Graph.hpp>
20#include <memory>
21#include <string>
22#include <string_view>
23#include <vector>
24
25#include <jau/basic_types.hpp>
26#include <jau/cpp_lang_util.hpp>
27#include <jau/darray.hpp>
28#include <jau/debug.hpp>
29#include <jau/float_math.hpp>
30#include <jau/float_types.hpp>
31#include <jau/fraction_type.hpp>
32#include <jau/io/file_util.hpp>
35#include <jau/math/vec3f.hpp>
36#include <jau/math/vec4f.hpp>
37#include <jau/math/vec4f.hpp>
42
43#include <gamp/Gamp.hpp>
48
50
52
54
56
57#include <cstdio>
58#include <cmath>
61#include <memory>
62#include <vector>
63
64#include <jau/basic_types.hpp>
65#include <jau/darray.hpp>
66#include <jau/float_math.hpp>
67#include <jau/float_types.hpp>
68#include <jau/fraction_type.hpp>
69#include <jau/io/file_util.hpp>
70#include <jau/math/vec3f.hpp>
71#include <jau/math/vec4f.hpp>
72#include <jau/math/vec4f.hpp>
77
78#include <gamp/Gamp.hpp>
83
84#include "model_cobramk3.hpp"
85
87
88using namespace jau::math;
89using namespace jau::math::util;
90using namespace jau::math::geom;
91
92using namespace gamp;
93using namespace gamp::wt;
94using namespace gamp::wt::event;
95
96using namespace gamp::graph;
97using namespace gamp::render::gl::glsl;
98using namespace gamp::render::gl::data;
99
100using namespace gamp::graph::tess;
101
102#if 0
103static void printOutlineShape(const std::string &tag, const OutlineShape& o, size_t idx=0) {
104 size_t o_idx=0;
105 printf("- %s: OutlineShape [%2zu]: %u outlines: %s\n", tag.c_str(), idx, o.outlines().size(), o.toString().c_str());
106 for(const Outline& ol : o.outlines()){
107 printf(" - Outline [%2zu][%2zu]:\n", idx, o_idx);
108 for(const Vertex& v : ol.vertices()){
109 printf(" - V[%2zu][%2zu]: %s\n", idx, o_idx, v.coord().toString().c_str());
110 }
111 ++o_idx;
112 }
113}
114
115static void printOutlineShapes(const std::string &tag, const std::vector<OutlineShape>& oshapes) {
116 printf("%s: %zu OutlineShapes\n", tag.c_str(), oshapes.size());
117 size_t os_idx=0;
118 for( const OutlineShape& o : oshapes ) {
119 printOutlineShape(tag, o, os_idx);
120 ++os_idx;
121 }
122}
123#endif
124
125class GraphRenderer {
126 public:
127 struct GraphRendererProps {
128 bool m_isTwoPass = false;
129 bool m_pass1 = true;
130 bool m_hasFrustumClipping = false;
131 bool m_hasNormalChannel = false;
132 bool m_hasLight0 = true;
133 bool m_hasColorChannel = false;
134 bool m_hasColorTexture = false;
135 bool m_hasDiscard = true;
136 };
137 private:
138 constexpr static PMVData mat_req = PMVData::inv_proj | PMVData::inv_mv | PMVData::inv_tps_mv;
139 constexpr static jau::math::Vec3f lightPos = jau::math::Vec3f(2.0f, 2.0f, 5.0f);
140 GraphRendererProps m_props;
141 ShaderState& m_st;
142 GLUniformSyncPMVMat4f m_pmvMat;
143 GLUniformVec3f m_light0Pos;
144 GLUniformVec4f m_staticColor;
145 bool m_initialized;
146
147 public:
148 constexpr bool usesNormal() const noexcept { return m_props.m_hasLight0 || m_props.m_hasNormalChannel; }
149 constexpr GLsizei arrayCompsPerElement() const noexcept { return usesNormal()? 2*3 : 1*3; }
150
151 public:
153 : m_st(st),
154 m_pmvMat("gcu_PMVMatrix", mat_req), // P, Mv, Mvi and Mvit
155 m_light0Pos("gcu_Light0Pos", lightPos),
156 m_staticColor("gcu_StaticColor", Vec4f(0, 0, 0, 1)),
157 m_initialized(false)
158 {
159 m_st.manage(m_pmvMat);
160 m_st.manage(m_light0Pos);
161 m_st.manage(m_staticColor);
162 }
163
164 constexpr bool initialized() const noexcept { return m_initialized; }
165
166 bool init(GL& gl, const jau::fraction_timespec& when) {
168 // ShaderState::VERBOSE_STATE = true;
169
170 ShaderCodeSRef rsVp = ShaderCode::create(gl, GL_VERTEX_SHADER, "demos/glsl",
171 "demos/glsl/bin", "SingleLight0");
172 ShaderCodeSRef rsFp = ShaderCode::create(gl, GL_FRAGMENT_SHADER, "demos/glsl",
173 "demos/glsl/bin", "SingleLight0");
174 if( !rsVp || !rsFp ) {
175 jau::fprintf_td(when.to_ms(), stdout, "ERROR %s:%d\n", E_FILE_LINE);
176 return false;
177 }
178 {
179 std::string custom = "#define MAX_TEXTURE_UNITS 0\n";
180 size_t vsPos = rsVp->defaultShaderCustomization(gl, true, true);
181 size_t fsPos = rsFp->defaultShaderCustomization(gl, true, true);
182 rsVp->insertShaderSource(0, vsPos, custom);
183 rsFp->insertShaderSource(0, fsPos, custom);
184 }
186 if( !sp0->add(gl, rsVp, true) || !sp0->add(gl, rsFp, true) ) {
187 jau::fprintf_td(when.to_ms(), stdout, "ERROR %s:%d\n", E_FILE_LINE);
188 sp0->destroy(gl);
189 return false;
190 }
191 m_st.attachShaderProgram(gl, sp0, true);
192
193 PMVMat4f& pmv = m_pmvMat.pmv();
194 pmv.getP().loadIdentity();
195 pmv.getMv().loadIdentity();
196
197 m_st.send(gl, m_pmvMat);
198 m_st.send(gl, m_light0Pos);
199 m_st.send(gl, m_staticColor);
200
201 m_initialized = sp0->inUse();
202 if( !m_initialized ) {
203 jau::fprintf_td(when.to_ms(), stdout, "ERROR %s:%d\n", E_FILE_LINE);
204 m_st.destroy(gl);
205 }
206 return m_initialized;
207 }
208
209 void destroy(GL& gl) {
210 m_st.destroyShaderProgram(gl);
211 }
212
213 void useProgram(GL& gl, bool on) {
214 m_st.useProgram(gl, on);
215 }
216
218 m_st.send(gl, m_staticColor);
219 }
220 void updatePMV(GL& gl) {
221 m_st.send(gl, m_pmvMat);
222 }
223 void updateAll(GL& gl) {
224 m_st.send(gl, m_pmvMat);
225 m_st.send(gl, m_staticColor);
226 }
227 PMVMat4f& pmv() noexcept { return m_pmvMat.pmv(); }
228 const PMVMat4f& pmv() const noexcept { return m_pmvMat.pmv(); }
229 const Vec4f& color() const noexcept { return m_staticColor.vec4f(); }
230 void setColor(const Vec4f& c) noexcept { m_staticColor.vec4f()=c; }
231 ShaderState& st() noexcept { return m_st; }
232 const ShaderState& st() const noexcept { return m_st; }
233 GLUniformVec3f& lightPosition() noexcept { return m_light0Pos; }
234 const GLUniformVec3f& lightPosition() const noexcept { return m_light0Pos; }
235};
236
237class GraphRegion {
238 public:
240 private:
241 GraphRenderer& m_renderer;
242 bool m_initialized;
245
246 public:
248 : m_renderer(renderer),
249 m_initialized(m_renderer.initialized()),
250 m_array(GLFloatArrayDataServer::createGLSLInterleaved(m_renderer.arrayCompsPerElement(), false, 256, GL_STATIC_DRAW)) {
251 m_array->addGLSLSubArray("gca_Vertex", 3, GL_ARRAY_BUFFER);
252 if( m_renderer.usesNormal() ) {
253 m_array->addGLSLSubArray("gca_Normal", 3, GL_ARRAY_BUFFER);
254 }
255 m_renderer.st().manage(m_array);
256 // m_st.manage(m_indices);
257 }
258
259 constexpr bool initialized() const noexcept { return m_initialized; }
260
261 void destroy(GL& gl) {
262 m_renderer.st().destroyAllData(gl);
263 // m_array->destroy(gl); // owned by m_st
264 }
265
266 void seal(GL& gl, bool seal_) {
267 if( !m_initialized ) {
268 return;
269 }
270 m_array->seal(gl, seal_);
271 m_array->enableBuffer(gl, false);
272 }
273
274 public:
276 if( !m_initialized ) {
277 return;
278 }
279 if( Graph::DEBUG_MODE ) {
280 jau_PLAIN_PRINT(true, "add.0 array: %s", m_array->toString().c_str());
281 jau_PLAIN_PRINT(true, "add.0 segments:\n%s", GLUtilTesselator::Segment::toString("- ", m_segments).c_str() );
282 }
283 // TODO use a GLUtilTesselator instance to be reused (perf)?
284 // - Keep native tesselator instance in GLUtilTesselator, callback setup and etc
285 {
287 GLUtilTesselator::SegmentList segs = glutess.tesselate(shape);
288 m_segments.insert(m_segments.cend(), segs.cbegin(), segs.cend());
289 }
290
291 if( Graph::DEBUG_MODE ) {
292 jau_PLAIN_PRINT(true, "add.x array: %s", m_array->toString().c_str());
293 jau_PLAIN_PRINT(true, "add.x segments:\n%s", GLUtilTesselator::Segment::toString("- ", m_segments).c_str() );
294 }
295 }
296
297 void draw(GL &gl) {
298 if( !m_initialized ) {
299 return;
300 }
301 m_renderer.useProgram(gl, true);
302
303 m_array->enableBuffer(gl, true);
304
305 ::glEnable(GL_BLEND);
306 ::glBlendEquation(GL_FUNC_ADD); // default
307 ::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
308
309 for(const GLUtilTesselator::Segment& s : m_segments ) {
310 ::glDrawArrays(s.type, s.first, s.count);
311 }
312
313 m_array->enableBuffer(gl, false);
314 // m_renderer.useProgram(gl, false);
315 }
316};
317
318class Shape;
319typedef std::shared_ptr<Shape> ShapeRef;
320
321class Shape {
322 private:
323 std::vector<OutlineShape> m_oshapes;
324
325 Vec3f m_position;
326 Quat4f m_rotation;
327 Vec3f m_rotPivot;
328 Vec3f m_scale = Vec3f(1, 1, 1);
329 float m_zOffset = 0.0f;
330 Vec4f m_color = Vec4f(0, 0, 0, 1);
331 GraphRenderer& m_renderer;
332 GraphRegion m_region;
333
334 Mat4f iMat;
335 Mat4f tmpMat;
336 bool iMatIdent = true;
337 bool iMatDirty = false;
338
339 float m_velo = 0; // m/s
340
341 struct Private{ explicit Private() = default; };
342
343 public:
344 Shape(Private, GraphRenderer &renderer)
345 : m_renderer(renderer), m_region(m_renderer)
346 {
347 std::cerr << "XXX ctor.x " << m_renderer.st() << "\n";
348 }
349
351 return std::make_shared<Shape>(Private(), renderer);
352 }
353
354 void destroy(GL& gl) {
355 m_region.destroy(gl);
356 }
357
358 constexpr const Vec3f& position() const noexcept { return m_position; }
359 constexpr Vec3f& position() noexcept { iMatDirty=true; return m_position; }
360 constexpr void set_position(Vec3f new_pos) noexcept { m_position = new_pos; }
361
362 constexpr const float& zOffset() const noexcept { return m_zOffset; }
363 constexpr float& zOffset() noexcept { iMatDirty=true; return m_zOffset; }
364
365 constexpr const Quat4f& rotation() const noexcept { return m_rotation; }
366 constexpr Quat4f& rotation() noexcept { iMatDirty=true; return m_rotation; }
367
368 constexpr const Vec3f& rotationPivot() const noexcept { return m_rotPivot; }
369 constexpr Vec3f& rotationPivot() noexcept { iMatDirty=true; return m_rotPivot; }
370
371 constexpr const Vec3f& scale() const noexcept { return m_scale; }
372 constexpr Vec3f& scale() noexcept { iMatDirty=true; return m_scale; }
373
374 constexpr const std::vector<OutlineShape>& outlineShapes() const noexcept { return m_oshapes; }
375 constexpr std::vector<OutlineShape>& outlineShapes() noexcept { return m_oshapes; }
376
377 const Vec4f& color() const noexcept { return m_color; }
378 void setColor(const Vec4f& c) noexcept { m_color = c; }
379
380 void update(GL& gl) {
381 for(OutlineShape& o : m_oshapes){
382 m_region.addOutlineShape(o);
383 }
384 m_region.seal(gl, true);
385 }
386
387 void draw(GL &gl) {
388 PMVMat4f& pmv = m_renderer.pmv();
389 pmv.pushMv();
390 applyMatToMv(pmv);
391
392 m_renderer.setColor(m_color);
393 m_renderer.updateAll(gl); // PMV + Color
394
395 m_region.draw(gl);
396 pmv.popMv();
397 }
398
399 /// Game ..
400 void tick(float dt) {
401 if( !jau::is_zero(m_velo) ) {
402 iMatDirty = true;
403 m_rotation.rotateByAngleZ( M_PI_2);
404 Vec3f dir = m_rotation.rotateVector(Vec3f(1, 0, 0));
405 m_rotation.rotateByAngleZ(-M_PI_2);
406 Vec3f d_p = dir * m_velo * dt;
407 m_position += d_p;
408 }
409 }
410 float& velo() noexcept { return m_velo; }
411
412 private:
413 /**
414 * Applies the internal {@link Matrix4f} to the given {@link PMVMatrix4f#getMv() modelview matrix},
415 * i.e. {@code pmv.mulMv( getMat() )}.
416 * <p>
417 * Calls {@link #updateMat()} if dirty.
418 * </p>
419 * In case {@link #isMatIdentity()} is {@code true}, implementation is a no-operation.
420 * </p>
421 * @param pmv the matrix
422 * @see #isMatIdentity()
423 * @see #updateMat()
424 * @see #getMat()
425 * @see PMVMatrix4f#mulMv(Matrix4f)
426 */
427 void applyMatToMv(PMVMat4f& pmvMat) noexcept {
428 if( iMatDirty ) {
429 updateMat();
430 }
431 if( !iMatIdent ) {
432 pmvMat.mulMv(iMat);
433 }
434 }
435 void updateMat() noexcept {
436 bool hasPos = !m_position.is_zero();
437 bool hasScale = m_scale != Vec3f::one;
438 bool hasRotate = !m_rotation.isIdentity();
439 bool hasRotPivot = false; // null != rotPivot;
440 for(OutlineShape& o : m_oshapes){
441 const Vec3f& ctr = o.bounds().center();
442 bool sameScaleRotatePivot = hasScale && hasRotate && ( !hasRotPivot || m_rotPivot == ctr );
443
444 if( sameScaleRotatePivot ) {
445 iMatIdent = false;
446 iMat.setToTranslation(m_position); // identity + translate, scaled
447 // Scale shape from its center position and rotate around its center
448 iMat.translate(Vec3f(ctr).mul(m_scale)); // add-back center, scaled
449 iMat.rotate(m_rotation);
450 iMat.scale(m_scale);
451 iMat.translate(-ctr); // move to center
452 } else if( hasRotate || hasScale ) {
453 iMatIdent = false;
454 iMat.setToTranslation(m_position); // identity + translate, scaled
455 if( hasRotate ) {
456 if( hasRotPivot ) {
457 // Rotate shape around its scaled pivot
458 iMat.translate(Vec3f(m_rotPivot).mul(m_scale)); // pivot back from rot-pivot, scaled
459 iMat.rotate(m_rotation);
460 iMat.translate(Vec3f(-m_rotPivot).mul(m_scale)); // pivot to rot-pivot, scaled
461 } else {
462 // Rotate shape around its scaled center
463 iMat.translate(Vec3f(ctr).mul(m_scale)); // pivot back from center-pivot, scaled
464 iMat.rotate(m_rotation);
465 iMat.translate(Vec3f(-ctr).mul(m_scale)); // pivot to center-pivot, scaled
466 }
467 }
468 if( hasScale ) {
469 // Scale shape from its center position
470 iMat.translate(Vec3f(ctr).mul(m_scale)); // add-back center, scaled
471 iMat.scale(m_scale);
472 iMat.translate(Vec3f(-ctr).mul(m_scale)); // move to center
473 }
474 } else if( hasPos ) {
475 iMatIdent = false;
476 iMat.setToTranslation(m_position); // identity + translate, scaled
477
478 } else {
479 iMatIdent = true;
480 iMat.loadIdentity();
481 }
482 iMatDirty = false;
483 }
484 }
485};
486
488 private:
489 constexpr static float zNear= 1.0f;
490 constexpr static float zFar =100.0f;
491
492 ShaderState m_st;
493 Recti m_viewport;
494 bool m_initialized;
495 bool m_animating = true;
496 bool m_oneframe = false;
498 GraphRenderer m_renderer;
499 std::vector<ShapeRef> m_shapes;
500 bool m_once = true;
501 GLUniformSyncPMVMat4f m_pmvMat;
502 GLUniformVec3f m_light0Pos;
503 GLUniformVec4f m_staticColor;
504
505 public:
508 m_initialized(false),
509 m_renderer(m_st),
510 m_pmvMat("gcu_PMVMatrix", PMVData::inv_proj | PMVData::inv_mv | PMVData::inv_tps_mv), // P, Mv, Mvi and Mvit
511 m_light0Pos("gcu_Light0Pos", m_renderer.lightPosition().vec3f()),
512 m_staticColor("gcu_StaticColor", Vec4f(0.05f, 0.05f, 0.5f, 1))
513 {
514 m_st.manage(m_pmvMat);
515 m_st.manage(m_light0Pos);
516 m_st.manage(m_staticColor);
517 }
518
519 Recti& viewport() noexcept { return m_viewport; }
520 const Recti& viewport() const noexcept { return m_viewport; }
521 std::vector<ShapeRef>& shapes() noexcept { return m_shapes; }
522
523 bool animating() const noexcept { return m_animating; }
524 bool& animating() noexcept { return m_animating; }
525 void setOneFrame() noexcept { m_animating=false; m_oneframe=true; }
526
527 bool init(const WindowSRef& win, const jau::fraction_timespec& when) override {
528 jau::fprintf_td(when.to_ms(), stdout, "RL::init: %s\n", toString().c_str());
529 m_tlast = when;
530
531 GL& gl = GL::downcast(win->renderContext());
532
533 if( !m_renderer.init(gl, when) ) {
534 jau::fprintf_td(when.to_ms(), stdout, "ERROR %s:%d: %s\n", E_FILE_LINE, toString().c_str());
535 win->dispose(when);
536 return false;
537 }
538
539 //const float lineWidth = 1/2.5f;
540 ShapeRef cobraMkIII_Shape = Shape::createShared(m_renderer);
541 models::appendCobraMkIII(cobraMkIII_Shape->outlineShapes());
542 cobraMkIII_Shape->setColor(Vec4f(0.05f, 0.05f, 0.5f, 1.0f));
543 cobraMkIII_Shape->rotation().rotateByAngleX(-M_PI / 4.0f);
544 cobraMkIII_Shape->update(gl);
545 m_shapes.push_back(cobraMkIII_Shape);
546 if ( false ) {
547 ShapeRef frontShape = Shape::createShared(m_renderer);
548 m_shapes.push_back(frontShape);
549 std::vector<OutlineShape>& oshapes = frontShape->outlineShapes();
550 for(OutlineShape& o : oshapes){
552
553 OutlineShape back = o.flipFace(); // -dz);
554 oshapes.push_back(back);
555 }
556 frontShape->update(gl);
557 frontShape->setColor(Vec4f(0.05f, 0.5f, 0.05f, 1));
558 frontShape->position().x = 1.5f;
559 frontShape->position().y = 0.5f;
560 frontShape->scale().x *= 2.0f;
561 frontShape->scale().y *= 2.0f;
562 }
563 //::glClearColor(1.0f, 1.0f, 1.0f, 0.0f);
564 ::glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
565 ::glEnable(GL_DEPTH_TEST);
566 // ::glEnable(GL_CULL_FACE);
567 ::glDisable(GL_CULL_FACE);
568
569 m_initialized = true;
570 if( !m_initialized ) {
571 jau::fprintf_td(when.to_ms(), stdout, "ERROR %s:%d: %s\n", E_FILE_LINE, toString().c_str());
572 m_st.destroy(gl);
573 win->dispose(when);
574 }
575 return m_initialized;
576 }
577
578 void dispose(const WindowSRef& win, const jau::fraction_timespec& when) override {
579 GL& gl = GL::downcast(win->renderContext());
580 jau::fprintf_td(when.to_ms(), stdout, "RL::dispose: %s\n", toString().c_str());
581 for(ShapeRef& s : m_shapes) {
582 s->destroy(gl);
583 }
584 m_renderer.destroy(gl);
585 m_st.destroy(GL::downcast(win->renderContext()));
586 m_initialized = false;
587 }
588
589 void reshape(const WindowSRef& win, const jau::math::Recti& viewport, const jau::fraction_timespec& when) override {
590 GL& gl = GL::downcast(win->renderContext());
591 jau::fprintf_td(when.to_ms(), stdout, "RL::reshape: %s\n", toString().c_str());
592 m_viewport = viewport;
593
594 PMVMat4f& pmv = m_renderer.pmv();
595 pmv.getP().loadIdentity();
596 const float aspect = 1.0f;
597 const float fovy_deg=45.0f;
598 const float aspect2 = ( (float) m_viewport.width() / (float) m_viewport.height() ) / aspect;
599 pmv.perspectiveP(jau::adeg_to_rad(fovy_deg), aspect2, zNear, zFar);
600 pmv.getMv().loadIdentity();
601 pmv.translateMv(0, 0, -5);
602
603 m_st.useProgram(gl, true);
604 // m_st.useProgram(gl, false);
605 }
606
607 void display(const WindowSRef& win, const jau::fraction_timespec& when) override {
608 // jau::fprintf_td(when.to_ms(), stdout, "RL::display: %s, %s\n", toString().c_str(), win->toString().c_str());
609 if( !m_initialized ) {
610 return;
611 }
612 GL& gl = GL::downcast(win->renderContext());
613 ::glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
614
615 m_st.useProgram(gl, true);
616
617 const float dt = float( (when - m_tlast).to_double() );
618 for(const ShapeRef& s : m_shapes) {
619 if( (animating() || m_oneframe) && s != m_shapes[0]) {
620 constexpr float angle_per_sec = 30;
621 const float rad = dt * angle_per_sec;
622 s->rotation().rotateByAngleX(jau::adeg_to_rad( -rad ));
623 s->rotation().rotateByAngleY(jau::adeg_to_rad( rad ));
624 //s->rotation().rotateByAngleZ(jau::adeg_to_rad( rad ));
625 }
626 s->tick(dt);
627 s->draw(gl);
628 }
629 m_oneframe = false;
630
631 if( m_once ) {
632 m_once = false;
633 std::cerr << "XXX draw " << m_st << "\n";
634 }
635
636 // m_st.useProgram(gl, false);
637
638 m_tlast = when;
639 }
640
641 std::string toStringImpl() const noexcept override { return "GraphShapes01"; }
642};
643
644class Example : public Primitives03 {
645 private:
646 class MyKeyListener : public KeyListener {
647 private:
648 Primitives03& m_parent;
649 public:
650 MyKeyListener(Primitives03& p) : m_parent(p) {}
651
652 void keyPressed(KeyEvent& e, const KeyboardTracker& kt) override {
653 jau::fprintf_td(e.when().to_ms(), stdout, "KeyPressed: %s; keys %zu\n", e.toString().c_str(), kt.pressedKeyCodes().count());
654 std::vector<ShapeRef>& shapeList = m_parent.shapes();
655 if( e.keySym() == VKeyCode::VK_ESCAPE ) {
656 WindowSRef win = e.source().lock();
657 if( win ) {
658 win->dispose(e.when());
659 }
660 } else if( e.keySym() == VKeyCode::VK_PAUSE || e.keySym() == VKeyCode::VK_P ) {
661 m_parent.animating() = !m_parent.animating();
662 } else if( e.keySym() == VKeyCode::VK_PERIOD ) {
663 m_parent.setOneFrame();
664 } else if( e.keySym() == VKeyCode::VK_W ) {
665 WindowSRef win = e.source().lock();
666 jau::fprintf_td(e.when().to_ms(), stdout, "Source: %s\n", win ? win->toString().c_str() : "null");
667 } else if( e.keySym() == VKeyCode::VK_UP ) {
668 shapeList[0]->rotation().rotateByAngleX(-M_PI / 50);
669 } else if( e.keySym() == VKeyCode::VK_DOWN ) {
670 shapeList[0]->rotation().rotateByAngleX( M_PI / 50);
671 } else if( e.keySym() == VKeyCode::VK_SHIFT ) {
672 shapeList[0]->velo() += 0.1f;
673 } else if( e.keySym() == VKeyCode::VK_ENTER ) {
674 shapeList[0]->velo() = std::max(shapeList[0]->velo() - 0.1f, 0.0f);
675 } else if( e.keySym() == VKeyCode::VK_RIGHT) {
676 shapeList[0]->rotation().rotateByAngleY( M_PI / 50);
677 } else if( e.keySym() == VKeyCode::VK_LEFT ) {
678 shapeList[0]->rotation().rotateByAngleY(-M_PI / 50);
679 }
680 }
681 void keyReleased(KeyEvent& e, const KeyboardTracker& kt) override {
682 jau::fprintf_td(e.when().to_ms(), stdout, "KeyRelease: %s; keys %zu\n", e.toString().c_str(), kt.pressedKeyCodes().count());
683 }
684 };
685 typedef std::shared_ptr<MyKeyListener> MyKeyListenerRef;
686 MyKeyListenerRef m_kl;
687
688 public:
690 : Primitives03(),
691 m_kl(std::make_shared<MyKeyListener>(*this)) { }
692
693 bool init(const WindowSRef& win, const jau::fraction_timespec& when) override {
694 if( !Primitives03::init(win, when) ) {
695 return false;
696 }
697 win->addKeyListener(m_kl);
698 return true;
699 }
700 void dispose(const WindowSRef& win, const jau::fraction_timespec& when) override {
701 win->removeKeyListener(m_kl);
702 Primitives03::dispose(win, when);
703 }
704};
705
706int main(int argc, char *argv[]) // NOLINT(bugprone-exception-escape)
707{
708 return launch("Primitives03.cpp",
710 .contextFlags=gamp::render::RenderContextFlags::verbose}, // | gamp::render::RenderContextFlags::debug},
711 std::make_shared<Example>(), argc, argv);
712}
int launch(std::string_view sfile, GLLaunchProps props, const RenderListenerSRef &demo, int argc, char *argv[])
std::shared_ptr< Shape > ShapeRef
int main(int argc, char *argv[])
std::shared_ptr< Shape > ShapeRef
bool init(const WindowSRef &win, const jau::fraction_timespec &when) override
Called by the drawable immediately after the render context is initialized.
void dispose(const WindowSRef &win, const jau::fraction_timespec &when) override
Notifies the listener to perform the release of all renderer resources per context,...
static void addShapeToRegion(gamp::graph::OutlineShape &shape)
void destroy(GL &gl)
constexpr bool initialized() const noexcept
void draw(GL &gl)
void addOutlineShape(OutlineShape &shape)
GraphRegion(GraphRenderer &renderer)
jau::darray< uint32_t, glmemsize_t > u32buffer_t
void seal(GL &gl, bool seal_)
void destroy(GL &gl)
ShaderState & st() noexcept
bool init(GL &gl, const jau::fraction_timespec &when)
void updatePMV(GL &gl)
const PMVMat4f & pmv() const noexcept
GLUniformVec3f & lightPosition() noexcept
constexpr GLsizei arrayCompsPerElement() const noexcept
const Vec4f & color() const noexcept
constexpr bool initialized() const noexcept
constexpr bool usesNormal() const noexcept
const ShaderState & st() const noexcept
const GLUniformVec3f & lightPosition() const noexcept
void updateAll(GL &gl)
void updateColor(GL &gl)
PMVMat4f & pmv() noexcept
GraphRenderer(ShaderState &st)
void useProgram(GL &gl, bool on)
void setColor(const Vec4f &c) noexcept
bool init(const WindowSRef &win, const jau::fraction_timespec &when) override
Called by the drawable immediately after the render context is initialized.
bool & animating() noexcept
Recti & viewport() noexcept
std::string toStringImpl() const noexcept override
void setOneFrame() noexcept
void display(const WindowSRef &win, const jau::fraction_timespec &when) override
Called by the drawable to initiate rendering by the client.
bool animating() const noexcept
std::vector< ShapeRef > & shapes() noexcept
const Recti & viewport() const noexcept
void dispose(const WindowSRef &win, const jau::fraction_timespec &when) override
Notifies the listener to perform the release of all renderer resources per context,...
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.
constexpr const float & zOffset() const noexcept
void setColor(const Vec4f &c) noexcept
void tick(float dt)
Game ..
Shape(Private, GraphRenderer &renderer)
constexpr Vec3f & position() noexcept
constexpr std::vector< OutlineShape > & outlineShapes() noexcept
static ShapeRef createShared(ShaderState &st, GraphRenderer &renderer)
void draw(GL &gl)
void update(GL &gl)
float & velo() noexcept
constexpr const std::vector< OutlineShape > & outlineShapes() const noexcept
constexpr const Quat4f & rotation() const noexcept
constexpr void set_position(Vec3f new_pos) noexcept
void destroy(GL &gl)
constexpr const Vec3f & rotationPivot() const noexcept
constexpr float & zOffset() noexcept
constexpr const Vec3f & position() const noexcept
constexpr Vec3f & scale() noexcept
constexpr Vec3f & rotationPivot() noexcept
static ShapeRef createShared(GraphRenderer &renderer)
const Vec4f & color() const noexcept
constexpr const Vec3f & scale() const noexcept
constexpr Quat4f & rotation() noexcept
static bool DEBUG_MODE
Definition Graph.hpp:24
A Generic shape objects which is defined by a list of Outlines.
const AABBox3f & bounds() const noexcept
const OutlineList & outlines() const noexcept
std::string toString() const noexcept
OutlineShape flipFace(float zoffset=0) const
Returns a copy of this instance with normal() and all outlines() vertices()'s z-axis sign-flipped,...
Define a single continuous stroke by control vertices.
Definition Outline.hpp:51
GLUtilTesselator transform OutlineShapes to triangles using glutess2.
static SegmentList tesselate(int flags, GLFloatArrayDataServer &array, OutlineShape &outlines)
static GLContext & downcast(RenderContext *rc)
Downcast dereferenced given RenderContext* to GLContext&, throws exception if signature doesn't match...
Specifies the OpenGL profile.
Definition GLContext.hpp:42
static constexpr std::string_view GLES2
The embedded OpenGL profile ES 2.x, with x >= 0.
Definition GLContext.hpp:65
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)
size_t insertShaderSource(size_t shaderIdx, stringview_t tag, size_t fromIndex, stringview_t data) noexcept
Adds data after the line containing tag.
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:129
void addKeyListener(const KeyListenerSRef &l)
Definition Window.hpp:310
void dispose(const jau::fraction_timespec &when) noexcept override
Definition Window.hpp:355
size_t removeKeyListener(const KeyListenerSRef &l)
Definition Window.hpp:311
std::string toString() const noexcept
Definition gamp_wt.cpp:145
std::string toString() const noexcept
Definition KeyEvent.hpp:855
constexpr VKeyCode keySym() const noexcept
Returns the virtual key symbol reflecting the current keyboard layout.
Definition KeyEvent.hpp:798
virtual const PressedKeyCodes & pressedKeyCodes() const noexcept=0
constexpr const WindowWeakPtr & source() const noexcept
Definition Event.hpp:85
constexpr const jau::fraction_timespec & when() const noexcept
Definition Event.hpp:84
size_type count() const noexcept
Definition bitfield.hpp:368
Implementation of a dynamic linear array storage, aka vector, including relative positional access.
Definition darray.hpp:154
constexpr size_type size() const noexcept
Like std::vector::size().
Definition darray.hpp:1116
constexpr Matrix4 & loadIdentity() noexcept
Set this matrix to identity.
Definition mat4f.hpp:239
static constexpr const value_type one
Definition vec3f.hpp:64
constexpr const Point3f & center() const noexcept
Returns computed center of this aabbox3f of low() and high().
Definition aabbox3f.hpp:105
constexpr Mat4 & getP() noexcept
Returns the projection matrix (P).
Definition pmvmat4.hpp:263
constexpr PMVMatrix4 & translateMv(float x, float y, float z) noexcept
Translate the modelview matrix.
Definition pmvmat4.hpp:641
constexpr_cxx20 PMVMatrix4 & popMv() noexcept
Pop the modelview matrix from its stack.
Definition pmvmat4.hpp:795
PMVMatrix4 & perspectiveP(const float fovy_rad, const float aspect, const float zNear, const float zFar)
Multiply the projection matrix with the perspective/frustum matrix.
Definition pmvmat4.hpp:885
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
#define jau_PLAIN_PRINT(printPrefix, fmt,...)
Use for unconditional plain messages, prefix '[elapsed_time] ' if printPrefix == true.
Definition debug.hpp:169
#define E_FILE_LINE
constexpr T adeg_to_rad(const T arc_degree) noexcept
Converts arc-degree to radians.
constexpr bool is_zero(const T &a, const T &epsilon=std::numeric_limits< T >::epsilon()) noexcept
Returns true if the given value is less than epsilon, w/ epsilon > 0.
GLArrayDataServer< float > GLFloatArrayDataServer
GLArrayDataServerSRef< float > GLFloatArrayDataServerSRef
std::shared_ptr< ShaderCode > ShaderCodeSRef
std::shared_ptr< ShaderProgram > ShaderProgramSRef
@ verbose
Verbose operations (debugging).
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
Quaternion< float > Quat4f
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
Gamp: Graphics, Audio, Multimedia and Processing Framework (Native C++, WebAssembly,...
Definition PTS.hpp:24
int fprintf_td(const uint64_t elapsed_ms, FILE *stream, std::string_view format, const Args &...args) noexcept
Convenient fprintf() invocation, prepending the given elapsed_ms timestamp.
Definition debug.hpp:184
void appendCobraMkIII(std::vector< OutlineShape > &oshapes, const float height=1.0f, const float width=2.0f, const float deep=0.3f)
STL namespace.
static std::string toString(const std::string &pre, const SegmentList &segments) noexcept
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.
int printf(const char *format,...)
Operating Systems predefined macros.