Gamp v0.0.8
Gamp: Graphics, Audio, Multimedia and Processing
Loading...
Searching...
No Matches
GraphShapes01.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 <cstdio>
13#include <cmath>
14#include <gamp/graph/Graph.hpp>
17#include <memory>
18#include <string>
19#include <string_view>
20#include <vector>
21
22#include <jau/basic_types.hpp>
23#include <jau/cpp_lang_util.hpp>
24#include <jau/darray.hpp>
25#include <jau/debug.hpp>
26#include <jau/float_math.hpp>
27#include <jau/float_types.hpp>
28#include <jau/fraction_type.hpp>
29#include <jau/io/file_util.hpp>
31#include <jau/math/vec3f.hpp>
32#include <jau/math/vec4f.hpp>
33#include <jau/math/vec4f.hpp>
38
39#include <gamp/Gamp.hpp>
44
46
49
51
52using namespace jau::math;
53using namespace jau::math::util;
54using namespace jau::math::geom;
55
56using namespace gamp;
57using namespace gamp::wt;
58using namespace gamp::wt::event;
59
60using namespace gamp::graph;
61using namespace gamp::render::gl::glsl;
62using namespace gamp::render::gl::data;
63
65 public:
67 bool m_isTwoPass = false;
68 bool m_pass1 = true;
70 bool m_hasNormalChannel = false;
71 bool m_hasLight0 = true;
72 bool m_hasColorChannel = false;
73 bool m_hasColorTexture = false;
74 bool m_hasDiscard = true;
75 };
76 private:
77 constexpr static PMVData mat_req = PMVData::inv_proj | PMVData::inv_mv | PMVData::inv_tps_mv;
78 constexpr static jau::math::Vec3f lightPos = jau::math::Vec3f(0.0f, 5.0f, 10.0f);
79 GraphRendererProps m_props;
80 ShaderState& m_st;
81 GLUniformSyncPMVMat4f m_pmvMat;
82 GLUniformVec3f m_light0Pos;
83 GLUniformVec4f m_staticColor;
84 bool m_initialized;
85
86 public:
87 constexpr bool usesNormal() const noexcept { return m_props.m_hasLight0 || m_props.m_hasNormalChannel; }
88 constexpr GLsizei arrayCompsPerElement() const noexcept { return usesNormal()? 3*3 : 2*3; }
89
90 static constexpr std::string_view GLSL_PARAM_COMMENT_START = "\n// Gamp Graph Parameter Start\n";
91 static constexpr std::string_view GLSL_PARAM_COMMENT_END = "// Gamp Graph Parameter End\n\n";
92 static constexpr std::string_view GLSL_USE_COLOR_CHANNEL = "#define USE_COLOR_CHANNEL 1\n";
93 static constexpr std::string_view GLSL_USE_NORMAL_CHANNEL = "#define USE_NORMAL_CHANNEL 1\n";
94 static constexpr std::string_view GLSL_USE_LIGHT0 = "#define USE_LIGHT0 1\n";
95 static constexpr std::string_view GLSL_USE_COLOR_TEXTURE = "#define USE_COLOR_TEXTURE 1\n";
96 static constexpr std::string_view GLSL_USE_FRUSTUM_CLIPPING = "#define USE_FRUSTUM_CLIPPING 1\n";
97 static constexpr std::string_view GLSL_USE_DISCARD = "#define USE_DISCARD 1\n";
98 static constexpr std::string_view GLSL_DEF_SAMPLE_COUNT = "#define SAMPLE_COUNT ";
99 static constexpr std::string_view GLSL_CONST_SAMPLE_COUNT = "const float sample_count = ";
100 static constexpr std::string_view GLSL_MAIN_BEGIN = "void main (void)\n{\n";
101 static constexpr std::string_view gcuTexture2D = "gcuTexture2D";
102 static constexpr std::string_view colTexLookupFuncName = "texture2D";
103 static constexpr std::string_view shader_basename = "curverenderer01";
104 static constexpr std::string_view source_dir = "impl/graph/glsl";
105 static constexpr std::string_view bin_dir = "impl/graph/glsl/bin";
106
107 public:
109 : m_st(st),
110 m_pmvMat("gcu_PMVMatrix", mat_req), // P, Mv, Mvi and Mvit
111 m_light0Pos("gcu_Light0Pos", lightPos),
112 m_staticColor("gcu_StaticColor", Vec4f(0, 0, 0, 1)),
113 m_initialized(false)
114 {
115 m_st.manage(m_pmvMat);
116 m_st.manage(m_light0Pos);
117 m_st.manage(m_staticColor);
118 }
119
120 constexpr bool initialized() const noexcept { return m_initialized; }
121
122 bool init(GL& gl, const jau::fraction_timespec& when) {
123 // ShaderCode::DEBUG_CODE = true;
124 // ShaderState::VERBOSE_STATE = true;
125
126 std::string vertexShaderName, fragmentShaderName;
127 vertexShaderName.append(shader_basename);
128 if( m_props.m_isTwoPass ) {
129 vertexShaderName.append("-pass").append(m_props.m_pass1 ? "1":"2");
130 } else {
131 vertexShaderName.append("-single");
132 }
133 fragmentShaderName.append(shader_basename).append("-segment-head");
134
135 ShaderCodeSRef rsVp = ShaderCode::create(gl, GL_VERTEX_SHADER, source_dir, bin_dir, vertexShaderName);
136 ShaderCodeSRef rsFp = ShaderCode::create(gl, GL_FRAGMENT_SHADER, source_dir, bin_dir, fragmentShaderName);
137 if( !rsVp || !rsFp ) {
138 jau::fprintf_td(when.to_ms(), stdout, "ERROR %s:%d\n", E_FILE_LINE);
139 return false;
140 }
141 {
142 size_t posVp = rsVp->defaultShaderCustomization(gl);
143 size_t posFp = rsFp->defaultShaderCustomization(gl);
144 if( posVp == std::string::npos || posFp == std::string::npos ) {
145 jau::fprintf_td(when.to_ms(), stdout, "ERROR %s:%d\n", E_FILE_LINE);
146 return false;
147 }
148
149 // GLSL append from here on
150 posFp = -1;
151
152 posVp = rsVp->insertShaderSource(0, posVp, GLSL_PARAM_COMMENT_START);
153 posFp = rsFp->insertShaderSource(0, posFp, GLSL_PARAM_COMMENT_START);
154
155 // if( !gl.getContext().hasRendererQuirk(GLRendererQuirks.GLSLBuggyDiscard) ) {
156 if( m_props.m_hasDiscard ) {
157 posFp = rsFp->insertShaderSource(0, posFp, GLSL_USE_DISCARD);
158 }
159
160 if( m_props.m_hasFrustumClipping ) {
161 posVp = rsVp->insertShaderSource(0, posVp, GLSL_USE_FRUSTUM_CLIPPING);
162 posFp = rsFp->insertShaderSource(0, posFp, GLSL_USE_FRUSTUM_CLIPPING);
163 }
164
165 if( usesNormal() ) {
166 posVp = rsVp->insertShaderSource(0, posVp, GLSL_USE_NORMAL_CHANNEL);
167 posFp = rsFp->insertShaderSource(0, posFp, GLSL_USE_NORMAL_CHANNEL);
168 }
169 if( m_props.m_hasLight0 ) {
170 posVp = rsVp->insertShaderSource(0, posVp, GLSL_USE_LIGHT0);
171 posFp = rsFp->insertShaderSource(0, posFp, GLSL_USE_LIGHT0);
172 }
173 if( m_props.m_hasColorChannel ) {
174 posVp = rsVp->insertShaderSource(0, posVp, GLSL_USE_COLOR_CHANNEL);
175 posFp = rsFp->insertShaderSource(0, posFp, GLSL_USE_COLOR_CHANNEL);
176 }
177 if( m_props.m_hasColorTexture ) {
179 posFp = rsFp->insertShaderSource(0, posFp, GLSL_USE_COLOR_TEXTURE);
180 }
181 /*if( !pass1 ) {
182 posFp = rsFp->insertShaderSource(0, posFp, GLSL_DEF_SAMPLE_COUNT+sms.sampleCount+"\n");
183 posFp = rsFp->insertShaderSource(0, posFp, GLSL_CONST_SAMPLE_COUNT+sms.sampleCount+".0;\n");
184 } */
185
186 posVp = rsVp->insertShaderSource(0, posVp, GLSL_PARAM_COMMENT_END);
187 if( posVp == std::string::npos ) {
188 jau::fprintf_td(when.to_ms(), stdout, "ERROR %s:%d\n", E_FILE_LINE);
189 return false;
190 }
191
192 posFp = rsFp->insertShaderSource(0, posFp, GLSL_PARAM_COMMENT_END);
193
194 posFp = rsFp->insertShaderSourceFile(0, posFp, string_t(source_dir).append("/constants.glsl"));
195 if( posFp == std::string::npos ) {
196 jau::fprintf_td(when.to_ms(), stdout, "ERROR %s:%d\n", E_FILE_LINE);
197 return false;
198 }
199 posFp = rsFp->insertShaderSourceFile(0, posFp, string_t(source_dir).append("/uniforms.glsl"));
200 if( posFp == std::string::npos ) {
201 jau::fprintf_td(when.to_ms(), stdout, "ERROR %s:%d\n", E_FILE_LINE);
202 return false;
203 }
204 posFp = rsFp->insertShaderSourceFile(0, posFp, string_t(source_dir).append("/varyings.glsl"));
205 if( posFp == std::string::npos ) {
206 jau::fprintf_td(when.to_ms(), stdout, "ERROR %s:%d\n", E_FILE_LINE);
207 return false;
208 }
209 if( m_props.m_hasColorTexture || m_props.m_hasFrustumClipping ) {
210 posFp = rsFp->insertShaderSourceFile(0, posFp, string_t(source_dir).append("/functions.glsl"));
211 if( posFp == std::string::npos ) {
212 jau::fprintf_td(when.to_ms(), stdout, "ERROR %s:%d\n", E_FILE_LINE);
213 return false;
214 }
215 }
216 /*if( hasColorTexture ) {
217 posFp = rsFp->insertShaderSource(0, posFp, "uniform "+colorTexSeq.getTextureSampler2DType()+" "+UniformNames.gcu_ColorTexUnit+";\n");
218 posFp = rsFp->insertShaderSource(0, posFp, colorTexSeq.getTextureLookupFragmentShaderImpl());
219 }*/
220
221 posFp = rsFp->insertShaderSource(0, posFp, GLSL_MAIN_BEGIN);
222
223 std::string passS = m_props.m_pass1 ? "-pass1-" : "-pass2-";
224 std::string shaderSegment = string_t(source_dir).append("/").append(shader_basename).append(passS).append("curve_simple").append(".glsl"); // sms.tech+sms.sub+".glsl";
226 jau_fprintf_td(stderr, "RegionRenderer.createShaderProgram.1: segment %s", shaderSegment);
227 }
228 posFp = rsFp->insertShaderSourceFile(0, posFp, shaderSegment);
229 if( posFp == std::string::npos ) {
230 jau::fprintf_td(when.to_ms(), stdout, "ERROR %s:%d\n", E_FILE_LINE);
231 return false;
232 }
233 posFp = rsFp->insertShaderSource(0, posFp, "}\n");
234 if( posFp == std::string::npos ) {
235 jau::fprintf_td(when.to_ms(), stdout, "ERROR %s:%d\n", E_FILE_LINE);
236 return false;
237 }
238
239 if( m_props.m_hasColorTexture ) {
240 rsFp->replaceInShaderSource(std::string(gcuTexture2D), std::string(colTexLookupFuncName));
241 }
242
243 }
245 if( !sp0->add(gl, rsVp, true) || !sp0->add(gl, rsFp, true) ) {
246 jau::fprintf_td(when.to_ms(), stdout, "ERROR %s:%d\n", E_FILE_LINE);
247 sp0->destroy(gl);
248 return false;
249 }
250 m_st.attachShaderProgram(gl, sp0, true);
251
252 PMVMat4f& pmv = m_pmvMat.pmv();
253 pmv.getP().loadIdentity();
254 pmv.getMv().loadIdentity();
255
256 m_st.send(gl, m_pmvMat);
257 m_st.send(gl, m_light0Pos);
258 m_st.send(gl, m_staticColor);
259
260 m_initialized = sp0->inUse();
261 if( !m_initialized ) {
262 jau::fprintf_td(when.to_ms(), stdout, "ERROR %s:%d\n", E_FILE_LINE);
263 m_st.destroy(gl);
264 }
265 return m_initialized;
266 }
267
268 void destroy(GL& gl) {
269 m_st.destroyShaderProgram(gl);
270 }
271
272 void useProgram(GL& gl, bool on) {
273 m_st.useProgram(gl, on);
274 }
275
277 m_st.send(gl, m_staticColor);
278 }
279 void updatePMV(GL& gl) {
280 m_st.send(gl, m_pmvMat);
281 }
282 void updateAll(GL& gl) {
283 m_st.send(gl, m_pmvMat);
284 m_st.send(gl, m_staticColor);
285 }
286 PMVMat4f& pmv() noexcept { return m_pmvMat.pmv(); }
287 const PMVMat4f& pmv() const noexcept { return m_pmvMat.pmv(); }
288 const Vec4f& color() const noexcept { return m_staticColor.vec4f(); }
289 void setColor(const Vec4f& c) noexcept { m_staticColor.vec4f()=c; }
290};
291
293 public:
295 private:
296 GraphRenderer& m_renderer;
297 ShaderState& m_st;
298 bool m_initialized;
301 int m_num_vertices, m_num_indices;
302
303 public:
305 : m_renderer(renderer), m_st(st),
306 m_initialized(m_renderer.initialized()),
307 m_array(GLFloatArrayDataServer::createGLSLInterleaved(m_renderer.arrayCompsPerElement(), false, 256, GL_STATIC_DRAW)),
308 m_indices(GLUIntArrayDataServer::createData(3, 256, GL_STATIC_DRAW, GL_ELEMENT_ARRAY_BUFFER)),
309 m_num_vertices(0), m_num_indices(0)
310 {
311 m_array->addGLSLSubArray("gca_Vertex", 3, GL_ARRAY_BUFFER);
312 m_array->addGLSLSubArray("gca_CurveParam", 3, GL_ARRAY_BUFFER);
313 if( m_renderer.usesNormal() ) {
314 m_array->addGLSLSubArray("gca_Normal", 3, GL_ARRAY_BUFFER);
315 }
316 m_st.manage(m_array);
317 // m_st.manage(m_indices);
318 }
319
320 constexpr bool initialized() const noexcept { return m_initialized; }
321
322 void destroy(GL& gl) {
323 m_st.destroyAllData(gl);
324 // m_array->destroy(gl); // owned by m_st
325 m_indices->destroy(gl);
326 m_num_vertices = 0;
327 m_num_indices = 0;
328 }
329
330 void seal(GL& gl, bool seal_) {
331 if( !m_initialized ) {
332 return;
333 }
334 m_array->seal(gl, seal_);
335 m_indices->seal(gl, seal_);
336 m_array->enableBuffer(gl, false);
337 m_indices->enableBuffer(gl, false);
338 }
339
340 private:
341 void pushVertex(const Vertex& v, const Vec3f& normal) {
342 // jau_fprintf_td(stderr, "pushVertex.0[%d]: v %s]", m_num_vertices, v.toString());
343 m_array->put3f(v.coord());
344 m_array->put3f(v.texCoord());
345 if( m_renderer.usesNormal() ) {
346 m_array->put3f(normal);
347 }
348 ++m_num_vertices;
349 }
350 void pushIndices(uint32_t i, uint32_t j, uint32_t k) {
351 // jau_fprintf_td(stderr, "pushIndices.0[%d]: %u, %u, %u]", m_num_indices, i, j, k);
352 m_indices->putN(i, j, k);
353 m_num_indices += 3;
354 }
355 void pushNewVerticesIdx(const Vertex& vertIn1, const Vertex& vertIn2, const Vertex& vertIn3, const Vec3f& normal) {
356 pushIndices(m_num_vertices, m_num_vertices+1, m_num_vertices+2);
357 pushVertex(vertIn1, normal);
358 pushVertex(vertIn2, normal);
359 pushVertex(vertIn3, normal);
360 }
361
362 public:
364 if( !m_initialized ) {
365 return;
366 }
367 if( Graph::DEBUG_MODE ) {
368 jau_fprintf_td(stderr, "add.0 num[vertices %d, indices %d]", m_num_vertices, m_num_indices);
369 jau_fprintf_td(stderr, "add.0 array: %s", m_array->toString());
370 jau_fprintf_td(stderr, "add.0 indices: %s", m_indices->toString());
371 }
372 const TriangleRefList& trisIn = shape.getTriangles();
373 const VertexList& vertsIn = shape.getVertices();
374 if( Graph::DEBUG_MODE ) {
375 jau_fprintf_td(stderr, "add.0 triangles %u, vertices %u", trisIn.size(), vertsIn.size());
376 }
377 {
378 glmemsize_t verticeCount = (glmemsize_t)vertsIn.size() + shape.addedVertexCount();
379 glmemsize_t indexCount = (glmemsize_t)trisIn.size() * 3;
380 m_array->growIfNeeded(verticeCount * m_array->compsPerElem());
381 m_indices->growIfNeeded(indexCount * m_indices->compsPerElem());
382 }
383 uint32_t idxOffset = m_num_vertices;
384 if( vertsIn.size() >= 3 ) {
385 //
386 // Processing Vertices
387 //
388 for(const Vertex& v : vertsIn) {
389 pushVertex(v, shape.normal());
390 }
391 constexpr static uint32_t max_index = std::numeric_limits<uint32_t>::max() / sizeof(uint32_t);
392 OutlineShape::size_type trisIn_sz = trisIn.size();
393 for(OutlineShape::size_type i=0; i < trisIn_sz; ++i) {
394 const TriangleRef& triIn = trisIn[i];
395 // triEx.addVertexIndicesOffset(idxOffset);
396 // triangles.add( triEx );
397 Triangle::trivert_t& triInVertices = triIn->vertices();
398 uint32_t tv0Idx = triInVertices[0].id();
399 if ( max_index - idxOffset > tv0Idx ) {
400 // valid 'known' idx - move by offset
401 pushIndices(tv0Idx+idxOffset,
402 triInVertices[1].id()+idxOffset,
403 triInVertices[2].id()+idxOffset);
404 } else {
405 // FIXME: If exceeding max_indices, we would need to generate a new buffer w/ indices
406 pushNewVerticesIdx(triInVertices[0], triInVertices[1], triInVertices[2], shape.normal());
407 }
408 }
409 }
410 if( Graph::DEBUG_MODE ) {
411 jau_fprintf_td(stderr, "add.x num[vertices %d, indices %d]", m_num_vertices, m_num_indices);
412 jau_fprintf_td(stderr, "add.x array: %s", m_array->toString());
413 jau_fprintf_td(stderr, "add.x indices: %s", m_indices->toString());
414 }
415 }
416
417 void draw(GL &gl) {
418 if( !m_initialized ) {
419 return;
420 }
421 m_renderer.useProgram(gl, true);
422
423 m_array->enableBuffer(gl, true);
424 m_indices->bindBuffer(gl, true); // keeps VBO binding
425
426 ::glEnable(GL_BLEND);
427 ::glBlendEquation(GL_FUNC_ADD); // default
428 ::glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
429
430 ::glDrawElements(GL_TRIANGLES, m_indices->elemCount() * m_indices->compsPerElem(), GL_UNSIGNED_INT, nullptr);
431
432 m_indices->bindBuffer(gl, false);
433 m_array->enableBuffer(gl, false);
434 // m_renderer.useProgram(gl, false);
435 }
436};
437
438class Shape;
439typedef std::shared_ptr<Shape> ShapeRef;
440
441class Shape {
442 private:
443 ShaderState& m_st;
444 OutlineShape m_oshape;
445
446 Vec3f m_position;
447 Quat4f m_rotation;
448 Vec3f m_rotPivot;
449 Vec3f m_scale = Vec3f(1, 1, 1);
450 float m_zOffset = 0.0f;
451 Vec4f m_color = Vec4f(0, 0, 0, 1);
452 GraphRenderer& m_renderer;
453 GraphRegion m_region;
454
455 Mat4f iMat;
456 Mat4f tmpMat;
457 bool iMatIdent = true;
458 bool iMatDirty = false;
459
460 struct Private{ explicit Private() = default; };
461
462 public:
463 Shape(Private, ShaderState &st, GraphRenderer &renderer)
464 : m_st(st), m_oshape(3, 16),
465 m_renderer(renderer), m_region(m_renderer, m_st)
466 {
467 // std::cerr << "XXX ctor.x " << m_st << "\n";
468 }
469
471 return std::make_shared<Shape>(Private(), st, renderer);
472 }
473
474 void destroy(GL& gl) {
475 m_region.destroy(gl);
476 }
477
478 constexpr const Vec3f& position() const noexcept { return m_position; }
479 constexpr Vec3f& position() noexcept { iMatDirty=true; return m_position; }
480
481 constexpr const float& zOffset() const noexcept { return m_zOffset; }
482 constexpr float& zOffset() noexcept { iMatDirty=true; return m_zOffset; }
483
484 constexpr const Quat4f& rotation() const noexcept { return m_rotation; }
485 constexpr Quat4f& rotation() noexcept { iMatDirty=true; return m_rotation; }
486
487 constexpr const Vec3f& rotationPivot() const noexcept { return m_rotPivot; }
488 constexpr Vec3f& rotationPivot() noexcept { iMatDirty=true; return m_rotPivot; }
489
490 constexpr const Vec3f& scale() const noexcept { return m_scale; }
491 constexpr Vec3f& scale() noexcept { iMatDirty=true; return m_scale; }
492
493 constexpr const OutlineShape& outlineShape() const noexcept { return m_oshape; }
494 constexpr OutlineShape& outlineShape() noexcept { return m_oshape; }
495
496 const Vec4f& color() const noexcept { return m_color; }
497 void setColor(const Vec4f& c) noexcept { m_color = c; }
498
499 void update(GL& gl) {
500 m_region.addOutlineShape(m_oshape);
501 m_region.seal(gl, true);
502 }
503
504 void draw(GL &gl) {
505 PMVMat4f& pmv = m_renderer.pmv();
506 pmv.pushMv();
507 applyMatToMv(pmv);
508
509 m_renderer.setColor(m_color);
510 m_renderer.updateAll(gl); // PMV + Color
511
512 m_region.draw(gl);
513 pmv.popMv();
514 }
515
516 private:
517 /**
518 * Applies the internal {@link Matrix4f} to the given {@link PMVMatrix4f#getMv() modelview matrix},
519 * i.e. {@code pmv.mulMv( getMat() )}.
520 * <p>
521 * Calls {@link #updateMat()} if dirty.
522 * </p>
523 * In case {@link #isMatIdentity()} is {@code true}, implementation is a no-operation.
524 * </p>
525 * @param pmv the matrix
526 * @see #isMatIdentity()
527 * @see #updateMat()
528 * @see #getMat()
529 * @see PMVMatrix4f#mulMv(Matrix4f)
530 */
531 void applyMatToMv(PMVMat4f& pmvMat) noexcept {
532 if( iMatDirty ) {
533 updateMat();
534 }
535 if( !iMatIdent ) {
536 pmvMat.mulMv(iMat);
537 }
538 }
539 void updateMat() noexcept {
540 bool hasPos = !m_position.is_zero();
541 bool hasScale = m_scale != Vec3f::one;
542 bool hasRotate = !m_rotation.isIdentity();
543 bool hasRotPivot = false; // null != rotPivot;
544 const Vec3f& ctr = m_oshape.bounds().center();
545 bool sameScaleRotatePivot = hasScale && hasRotate && ( !hasRotPivot || m_rotPivot == ctr );
546
547 if( sameScaleRotatePivot ) {
548 iMatIdent = false;
549 iMat.setToTranslation(m_position); // identity + translate, scaled
550 // Scale shape from its center position and rotate around its center
551 iMat.translate(Vec3f(ctr).mul(m_scale)); // add-back center, scaled
552 iMat.rotate(m_rotation);
553 iMat.scale(m_scale);
554 iMat.translate(-ctr); // move to center
555 } else if( hasRotate || hasScale ) {
556 iMatIdent = false;
557 iMat.setToTranslation(m_position); // identity + translate, scaled
558 if( hasRotate ) {
559 if( hasRotPivot ) {
560 // Rotate shape around its scaled pivot
561 iMat.translate(Vec3f(m_rotPivot).mul(m_scale)); // pivot back from rot-pivot, scaled
562 iMat.rotate(m_rotation);
563 iMat.translate(Vec3f(-m_rotPivot).mul(m_scale)); // pivot to rot-pivot, scaled
564 } else {
565 // Rotate shape around its scaled center
566 iMat.translate(Vec3f(ctr).mul(m_scale)); // pivot back from center-pivot, scaled
567 iMat.rotate(m_rotation);
568 iMat.translate(Vec3f(-ctr).mul(m_scale)); // pivot to center-pivot, scaled
569 }
570 }
571 if( hasScale ) {
572 // Scale shape from its center position
573 iMat.translate(Vec3f(ctr).mul(m_scale)); // add-back center, scaled
574 iMat.scale(m_scale);
575 iMat.translate(Vec3f(-ctr).mul(m_scale)); // move to center
576 }
577 } else if( hasPos ) {
578 iMatIdent = false;
579 iMat.setToTranslation(m_position); // identity + translate, scaled
580
581 } else {
582 iMatIdent = true;
583 iMat.loadIdentity();
584 }
585 iMatDirty = false;
586 }
587};
588
590 private:
591 constexpr static float zNear= 1.0f;
592 constexpr static float zFar =100.0f;
593
594 ShaderState m_st;
595 Recti m_viewport;
596 bool m_initialized;
597 bool m_animating = true;
598 bool m_oneframe = false;
600 GraphRenderer m_renderer;
601 std::vector<ShapeRef> m_shapes;
602 bool m_once = true;
603
604 public:
607 m_initialized(false),
608 m_renderer(m_st)
609 {
610 }
611
612 Recti& viewport() noexcept { return m_viewport; }
613 const Recti& viewport() const noexcept { return m_viewport; }
614
615 bool animating() const noexcept { return m_animating; }
616 bool& animating() noexcept { return m_animating; }
617 void setOneFrame() noexcept { m_animating=false; m_oneframe=true; }
618
619 bool init(const WindowSRef& win, const jau::fraction_timespec& when) override {
620 jau::fprintf_td(when.to_ms(), stdout, "RL::init: %s\n", toString());
621 m_tlast = when;
622
623 GL& gl = GL::downcast(win->renderContext());
624
625 if( !m_renderer.init(gl, when) ) {
626 jau::fprintf_td(when.to_ms(), stdout, "ERROR %s:%d: %s\n", E_FILE_LINE, toString());
627 win->dispose(when);
628 return false;
629 }
630
631 const float lineWidth = 1/2.5f;
632 const float dz = 0.001f;
633 if( true ) {
634 // Cross / Plus
635 const float width = 1.5f;
636 const float height = 1.5f;
637
638 float lwh = lineWidth/2.0f;
639
640 float twh = width/2.0f;
641 float thh = height/2.0f;
642
643 float ctrX = 0, ctrY = 0, ctrZ = dz;
644 ShapeRef frontShape = Shape::createShared(m_st, m_renderer);
645 m_shapes.push_back(frontShape);
646 OutlineShape& oshape = frontShape->outlineShape();
647 // CCW
648 oshape.moveTo(ctrX+twh, ctrY-lwh, ctrZ); // horz: right-bottom
649 oshape.lineTo(ctrX+twh, ctrY+lwh, ctrZ); // horz: right-top
650 oshape.lineTo(ctrX+lwh, ctrY+lwh, ctrZ);
651 oshape.lineTo(ctrX+lwh, ctrY+thh, ctrZ); // vert: right-top
652 oshape.lineTo(ctrX-lwh, ctrY+thh, ctrZ); // vert: left-top
653 oshape.lineTo(ctrX-lwh, ctrY+lwh, ctrZ);
654 oshape.lineTo(ctrX-twh, ctrY+lwh, ctrZ); // horz: left-top
655 oshape.lineTo(ctrX-twh, ctrY-lwh, ctrZ); // horz: left-bottom
656 oshape.lineTo(ctrX-lwh, ctrY-lwh, ctrZ);
657 oshape.lineTo(ctrX-lwh, ctrY-thh, ctrZ); // vert: left-bottom
658 oshape.lineTo(ctrX+lwh, ctrY-thh, ctrZ); // vert: right-bottom
659 oshape.lineTo(ctrX+lwh, ctrY-lwh, ctrZ);
660 oshape.lineTo(ctrX+twh, ctrY-lwh, ctrZ); // horz: right-bottom
661 oshape.closePath();
662 oshape.normal() = Vec3f(0, 0, 1); // manual
663
664 // shape1->seal(gl, true);
665 frontShape->update(gl);
666 frontShape->setColor(Vec4f(0.5f, 0.05f, 0.05f, 1));
667 frontShape->position().x = -2.0f;
668
669 ShapeRef backShape = Shape::createShared(m_st, m_renderer);
670 m_shapes.push_back(backShape);
671 backShape->outlineShape() = oshape.flipFace(); // -dz);
672 backShape->outlineShape().clearCache();
673 backShape->update(gl);
674 backShape->setColor(Vec4f(0.2f, 0.5f, 0.2f, 1));
675 backShape->position().x = -2.0f;
676 }
677 if( true) {
678 ShapeRef frontShape = Shape::createShared(m_st, m_renderer);
679 m_shapes.push_back(frontShape);
680 OutlineShape& oshape = frontShape->outlineShape();
681 // Outer boundary-shapes are required as Winding::CCW (is CCW)
682 oshape.moveTo(0.0f,-10.0f, 0);
683 oshape.lineTo(15.0f,-10.0f, 0);
684 oshape.quadTo(10.0f,5.0f,0, 15.0f,10.0f,0);
685 oshape.cubicTo(6.0f,15.0f,0, 5.0f,8.0f,0, 0.0f,10.0f,0);
686 oshape.closePath();
687 // Inner hole-shapes should be Winding::CW (is CCW and will be fixed to CW below)
688 oshape.moveTo(5.0f,-5.0f,0);
689 oshape.quadTo(10.0f,-5.0f,0, 10.0f,0.0f,0);
690 oshape.quadTo(5.0f,0.0f,0, 5.0f,-5.0f,0);
691 oshape.closePath();
692 {
693 const Winding w10 = oshape.outlines()[0].getWinding();
694 const Winding w11 = oshape.outlines()[1].getWinding();
695 oshape.outlines()[0].setWinding(Winding::CCW);
696 oshape.outlines()[1].setWinding(Winding::CW);
697 jau_fprintf_td(stderr, "Special.frontShape.10.winding_area: %s -> %s",
698 to_string(w10), to_string(oshape.outlines()[0].getWinding()));
699 jau_fprintf_td(stderr, "Special.frontShape.11.winding_area: %s -> %s",
700 to_string(w11), to_string(oshape.outlines()[1].getWinding()));
701 }
702
703 frontShape->update(gl);
704 frontShape->setColor(Vec4f(0.4f, 0.4f, 0.1f, 1));
705 frontShape->position().x = -1.0f;
706 frontShape->scale().x *= 0.1f;
707 frontShape->scale().y *= 0.1f;
708
709 ShapeRef backShape = Shape::createShared(m_st, m_renderer);
710 m_shapes.push_back(backShape);
711 backShape->outlineShape() = oshape.flipFace(-dz); // winding preserved and is correct
712 backShape->outlineShape().clearCache();
713 backShape->update(gl);
714 backShape->setColor(Vec4f(0.2f, 0.2f, 0.5f, 1));
715 backShape->position().x = -1.0f;
716 backShape->scale().x *= 0.1f;
717 backShape->scale().y *= 0.1f;
718 jau_fprintf_td(stderr, "Special.backShape.10.winding_area: %s",
719 to_string(backShape->outlineShape().outlines()[0].getWinding()));
720 jau_fprintf_td(stderr, "Special.backShape.11.winding_area: %s",
721 to_string(backShape->outlineShape().outlines()[1].getWinding()));
722 }
723 if ( true ) {
724 ShapeRef frontShape = Shape::createShared(m_st, m_renderer);
725 m_shapes.push_back(frontShape);
726 OutlineShape& oshape = frontShape->outlineShape();
728 frontShape->update(gl);
729 frontShape->setColor(Vec4f(0.05f, 0.05f, 0.5f, 1));
730 frontShape->position().x = 1.5f;
731 frontShape->position().y = -1.0f;
732 frontShape->scale().x *= 2.0f;
733 frontShape->scale().y *= 2.0f;
734
735 ShapeRef backShape = Shape::createShared(m_st, m_renderer);
736 m_shapes.push_back(backShape);
737 backShape->outlineShape() = oshape.flipFace(-dz);
738 backShape->outlineShape().clearCache();
739 backShape->update(gl);
740 backShape->setColor(Vec4f(0.4f, 0.4f, 0.1f, 1));
741 backShape->position().x = 1.5f;
742 backShape->position().y = -1.0f;
743 backShape->scale().x *= 2.0f;
744 backShape->scale().y *= 2.0f;
745 }
746 if ( true ) {
747 ShapeRef frontShape = Shape::createShared(m_st, m_renderer);
748 m_shapes.push_back(frontShape);
749 OutlineShape& oshape = frontShape->outlineShape();
751 frontShape->update(gl);
752 frontShape->setColor(Vec4f(0.05f, 0.5f, 0.05f, 1));
753 frontShape->position().x = 1.5f;
754 frontShape->position().y = 0.5f;
755 frontShape->scale().x *= 2.0f;
756 frontShape->scale().y *= 2.0f;
757
758 ShapeRef backShape = Shape::createShared(m_st, m_renderer);
759 m_shapes.push_back(backShape);
760 backShape->outlineShape() = oshape.flipFace(-dz);
761 backShape->outlineShape().clearCache();
762 backShape->update(gl);
763 backShape->setColor(Vec4f(0.5f, 0.1f, 0.1f, 1));
764 backShape->position().x = 1.5f;
765 backShape->position().y = 0.5f;
766 backShape->scale().x *= 2.0f;
767 backShape->scale().y *= 2.0f;
768 }
769
770 ::glClearColor(1.0f, 1.0f, 1.0f, 0.0f);
771 ::glEnable(GL_DEPTH_TEST);
772 // ::glEnable(GL_CULL_FACE);
773 ::glDisable(GL_CULL_FACE);
774
775 m_initialized = true;
776 if( !m_initialized ) {
777 jau::fprintf_td(when.to_ms(), stdout, "ERROR %s:%d: %s\n", E_FILE_LINE, toString());
778 m_st.destroy(gl);
779 win->dispose(when);
780 }
781 return m_initialized;
782 }
783
784 void dispose(const WindowSRef& win, const jau::fraction_timespec& when) override {
785 GL& gl = GL::downcast(win->renderContext());
786 jau::fprintf_td(when.to_ms(), stdout, "RL::dispose: %s\n", toString());
787 for(ShapeRef& s : m_shapes) {
788 s->destroy(gl);
789 }
790 m_renderer.destroy(gl);
791 m_st.destroy(GL::downcast(win->renderContext()));
792 m_initialized = false;
793 }
794
795 void reshape(const WindowSRef& win, const jau::math::Recti& viewport, const jau::fraction_timespec& when) override {
796 GL& gl = GL::downcast(win->renderContext());
797 jau::fprintf_td(when.to_ms(), stdout, "RL::reshape: %s\n", toString());
798 m_viewport = viewport;
799
800 PMVMat4f& pmv = m_renderer.pmv();
801 pmv.getP().loadIdentity();
802 const float aspect = 1.0f;
803 const float fovy_deg=45.0f;
804 const float aspect2 = ( (float) m_viewport.width() / (float) m_viewport.height() ) / aspect;
805 pmv.perspectiveP(jau::adeg_to_rad(fovy_deg), aspect2, zNear, zFar);
806 pmv.getMv().loadIdentity();
807 pmv.translateMv(0, 0, -5);
808
809 m_st.useProgram(gl, true);
810 // m_st.useProgram(gl, false);
811 }
812
813 void display(const WindowSRef& win, const jau::fraction_timespec& when) override {
814 // jau::fprintf_td(when.to_ms(), stdout, "RL::display: %s, %s\n", toString(), win->toString());
815 if( !m_initialized ) {
816 return;
817 }
818 GL& gl = GL::downcast(win->renderContext());
819 ::glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
820
821 m_st.useProgram(gl, true);
822
823 for(const ShapeRef& s : m_shapes) {
824 if( animating() || m_oneframe ) {
825 constexpr double angle_per_sec = 30;
826 const float rad = (float) ( (when - m_tlast).to_double() * angle_per_sec );
827 s->rotation().rotateByAngleY(jau::adeg_to_rad( rad ));
828 }
829 s->draw(gl);
830 }
831 m_oneframe = false;
832
833 if( m_once ) {
834 m_once = false;
835 // std::cerr << "XXX draw " << m_st << "\n";
836 }
837
838 // m_st.useProgram(gl, false);
839
840 m_tlast = when;
841 }
842
843 std::string toStringImpl() const noexcept override { return "GraphShapes01"; }
844};
845
846class Example : public GraphShapes01 {
847 private:
848 class MyKeyListener : public KeyListener {
849 private:
850 GraphShapes01& m_parent;
851 public:
852 MyKeyListener(GraphShapes01& p) : m_parent(p) {}
853
854 void keyPressed(KeyEvent& e, const KeyboardTracker& kt) override {
855 jau::fprintf_td(e.when().to_ms(), stdout, "KeyPressed: %s; keys %zu\n", e.toString(), kt.pressedKeyCodes().count());
856 if( e.keySym() == VKeyCode::VK_ESCAPE ) {
857 WindowSRef win = e.source().lock();
858 if( win ) {
859 win->dispose(e.when());
860 }
861 } else if( e.keySym() == VKeyCode::VK_PAUSE || e.keySym() == VKeyCode::VK_P ) {
862 m_parent.animating() = !m_parent.animating();
863 } else if( e.keySym() == VKeyCode::VK_PERIOD ) {
864 m_parent.setOneFrame();
865 } else if( e.keySym() == VKeyCode::VK_W ) {
866 WindowSRef win = e.source().lock();
867 jau::fprintf_td(e.when().to_ms(), stdout, "Source: %s\n", win ? win->toString() : "null");
868 }
869 }
870 void keyReleased(KeyEvent& e, const KeyboardTracker& kt) override {
871 jau::fprintf_td(e.when().to_ms(), stdout, "KeyRelease: %s; keys %zu\n", e.toString(), kt.pressedKeyCodes().count());
872 }
873 };
874 typedef std::shared_ptr<MyKeyListener> MyKeyListenerRef;
875 MyKeyListenerRef m_kl;
876
877 public:
879 : GraphShapes01(),
880 m_kl(std::make_shared<MyKeyListener>(*this)) { }
881
882 bool init(const WindowSRef& win, const jau::fraction_timespec& when) override {
883 if( !GraphShapes01::init(win, when) ) {
884 return false;
885 }
886 win->addKeyListener(m_kl);
887 return true;
888 }
889 void dispose(const WindowSRef& win, const jau::fraction_timespec& when) override {
890 win->removeKeyListener(m_kl);
891 GraphShapes01::dispose(win, when);
892 }
893};
894
895int main(int argc, char *argv[]) // NOLINT(bugprone-exception-escape)
896{
897 return launch("GraphShapes01.cpp",
899 .contextFlags=gamp::render::RenderContextFlags::verbose, // | gamp::render::RenderContextFlags::debug,
900 .requestedCaps=GLCapabilities().setMultiSamplesCount(4)},
901 std::make_shared<Example>(), argc, argv);
902}
int launch(std::string_view sfile, GLLaunchProps props, const RenderListenerSRef &demo, int argc, char *argv[])
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)
static void addShapeToRegion(gamp::graph::OutlineShape &shape)
void destroy(GL &gl)
constexpr bool initialized() const noexcept
void draw(GL &gl)
void addOutlineShape(OutlineShape &shape)
jau::darray< uint32_t, glmemsize_t > u32buffer_t
GraphRegion(GraphRenderer &renderer, ShaderState &st)
void seal(GL &gl, bool seal_)
void destroy(GL &gl)
static constexpr std::string_view GLSL_USE_LIGHT0
ShaderState & st() noexcept
bool init(GL &gl, const jau::fraction_timespec &when)
static constexpr std::string_view GLSL_CONST_SAMPLE_COUNT
static constexpr std::string_view GLSL_USE_COLOR_CHANNEL
static constexpr std::string_view GLSL_USE_DISCARD
void updatePMV(GL &gl)
const PMVMat4f & pmv() const noexcept
static constexpr std::string_view GLSL_USE_FRUSTUM_CLIPPING
static constexpr std::string_view source_dir
static constexpr std::string_view GLSL_PARAM_COMMENT_END
constexpr GLsizei arrayCompsPerElement() const noexcept
const Vec4f & color() const noexcept
constexpr bool initialized() const noexcept
static constexpr std::string_view shader_basename
static constexpr std::string_view bin_dir
static constexpr std::string_view gcuTexture2D
static constexpr std::string_view GLSL_MAIN_BEGIN
static constexpr std::string_view GLSL_USE_COLOR_TEXTURE
static constexpr std::string_view GLSL_USE_NORMAL_CHANNEL
constexpr bool usesNormal() const noexcept
void updateAll(GL &gl)
void updateColor(GL &gl)
PMVMat4f & pmv() noexcept
static constexpr std::string_view colTexLookupFuncName
GraphRenderer(ShaderState &st)
void useProgram(GL &gl, bool on)
static constexpr std::string_view GLSL_PARAM_COMMENT_START
static constexpr std::string_view GLSL_DEF_SAMPLE_COUNT
void setColor(const Vec4f &c) noexcept
void setOneFrame() noexcept
bool animating() const noexcept
void display(const WindowSRef &win, const jau::fraction_timespec &when) override
Called by the drawable to initiate rendering by the client.
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.
std::string toStringImpl() const noexcept override
bool & animating() noexcept
Recti & viewport() 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,...
bool init(const WindowSRef &win, const jau::fraction_timespec &when) override
Called by the drawable immediately after the render context is initialized.
const Recti & viewport() const noexcept
constexpr const float & zOffset() const noexcept
void setColor(const Vec4f &c) noexcept
constexpr const OutlineShape & outlineShape() const noexcept
constexpr Vec3f & position() noexcept
static ShapeRef createShared(ShaderState &st, GraphRenderer &renderer)
void draw(GL &gl)
void update(GL &gl)
constexpr const Quat4f & rotation() const noexcept
Shape(Private, ShaderState &st, GraphRenderer &renderer)
constexpr OutlineShape & outlineShape() 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
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.
constexpr size_type addedVertexCount() const noexcept
Return the number of newly added vertices during getTriangles(VerticesState) while transforming the o...
const VertexList & getVertices()
Return list of concatenated vertices associated with all Outlines of this object.
void clearCache() noexcept
Clears cached triangulated data, i.e.
void cubicTo(float x1, float y1, float z1, float x2, float y2, float z2, float x3, float y3, float z3)
Add a cubic Bézier curve segment, intersecting the last point and the second given point x3/y3 (P3).
const OutlineList & outlines() const noexcept
void quadTo(float x1, float y1, float z1, float x2, float y2, float z2)
Add a quadratic curve segment, intersecting the last point and the second given point x2/y2 (P2).
constexpr const Vec3f & normal() const noexcept
Normal vector, optionally used by tesselator to add (interleaved) normals.
void moveTo(float x, float y, float z)
Start a new position for the next line segment at given point x/y (P1).
void closePath()
Closes the current sub-path segment by drawing a straight line back to the coordinates of the last mo...
const TriangleRefList & getTriangles(VertexState destinationType=VertexState::quadratic_nurbs)
Triangulate the OutlineShape generating a list of triangles, while transformOutlines(VerticesState) b...
OutlineShape flipFace(float zoffset=0) const
Returns a copy of this instance with normal() pointing to the opposite direction and all outlines() v...
void lineTo(float x, float y, float z)
Add a line segment, intersecting the last point and the given point x/y (P1).
std::array< Vertex, 3 > trivert_t
constexpr const trivert_t & vertices() const noexcept
Returns array of 3 vertices, denominating the triangle.
constexpr const Vec3f & texCoord() const noexcept
Definition PrimTypes.hpp:96
constexpr const Vec3f & coord() const noexcept
Definition PrimTypes.hpp:93
Specifies a set of OpenGL capabilities.
constexpr GLCapabilities & setMultiSamplesCount(int v) noexcept
Defaults to 0, i.e.
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 replaceInShaderSource(const string_t &oldName, const string_t &newName) noexcept
Replaces oldName with newName in all shader sources.
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 insertShaderSourceFile(size_t shaderIdx, size_t position, const string_t &path) noexcept
Adds shader source located in path, either relative to the location or absolute as-is at position in ...
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:131
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
value_type x
Definition vec3f.hpp:66
value_type y
Definition vec3f.hpp:67
static constexpr const value_type one
Definition vec3f.hpp:64
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_fprintf_td(stream, fmt,...)
Definition debug.hpp:249
std::shared_ptr< Shape > ShapeRef
#define E_FILE_LINE
constexpr T adeg_to_rad(const T arc_degree) noexcept
Converts arc-degree to radians.
GLArrayDataServer< float > GLFloatArrayDataServer
GLArrayDataServerSRef< float > GLFloatArrayDataServerSRef
GLsizeiptr glmemsize_t
Compatible with ssize_t.
Definition GLBuffers.hpp:26
GLArrayDataServer< uint32_t > GLUIntArrayDataServer
GLArrayDataServerSRef< uint32_t > GLUIntArrayDataServerSRef
std::shared_ptr< ShaderCode > ShaderCodeSRef
std::shared_ptr< ShaderProgram > ShaderProgramSRef
jau::darray< Vertex, uint32_t > VertexList
std::shared_ptr< Triangle > TriangleRef
jau::darray< TriangleRef, uint32_t > TriangleRefList
@ 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
std::string_view to_string(const math_error_t v) noexcept
Returns std::string_view representation of math_error_t.
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
@ CCW
Counter-Clockwise.
Definition geom.hpp:39
Gamp: Graphics, Audio, Multimedia and Processing Framework (Native C++, WebAssembly,...
Definition PTS.hpp:24
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
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.