Gamp v0.0.7-36-g24b1eb6
Gamp: Graphics, Audio, Multimedia and Processing
Loading...
Searching...
No Matches
GearsES2.cpp

This C++ example uses the simple Launcher01.hpp mainloop framework integration.

This C++ example uses the simple Launcher01.hpp mainloop framework integration. It creates a window, provides keyboard and pointer interaction including picking, rotate & drag. It uses GearsES2 gamp::wt::RenderListener for rendering and uses per-pixel-lighting.

/*
* Author: Sven Gothel <sgothel@jausoft.com>
* Copyright Gothel Software e.K.
*
* SPDX-License-Identifier: MIT
*
* This Source Code Form is subject to the terms of the MIT License
* If a copy of the MIT was not distributed with this file,
* you can obtain one at https://opensource.org/license/mit/.
*/
#include <gamp/Gamp.hpp>
#include <cstdio>
#include <cmath>
#include <memory>
#include <gamp/Gamp.hpp>
#include "../demos/GearsES2.hpp"
#include "../demos/GLLauncher01.hpp"
using namespace jau::math;
using namespace jau::math::util;
using namespace gamp::wt;
using namespace gamp::wt::event;
class Example : public GearsES2 {
private:
class MyKeyListener : public KeyListener {
private:
GearsES2& m_parent;
public:
MyKeyListener(GearsES2& p): m_parent(p) { }
void keyPressed(KeyEvent& e, const KeyboardTracker&) override {
const VKeyCode kc = e.keySym();
if( e.keySym() == VKeyCode::VK_ESCAPE ) {
WindowRef win = e.source().lock();
if( win ) {
win->dispose(e.when());
}
} else if( kc == VKeyCode::VK_PAUSE || kc == VKeyCode::VK_P ) {
m_parent.setDoRotate(!m_parent.doRotate());
} else if( kc == VKeyCode::VK_W ) {
WindowRef win = e.source().lock();
jau::fprintf_td(e.when().to_ms(), stdout, "Source: %s\n", win ? win->toString().c_str() : "null");
} else if( VKeyCode::VK_LEFT == kc ) {
m_parent.rotEuler().y -= jau::adeg_to_rad(1.0f);
} else if( VKeyCode::VK_RIGHT == kc ) {
m_parent.rotEuler().y += jau::adeg_to_rad(1.0f);
} else if( VKeyCode::VK_UP == kc ) {
m_parent.rotEuler().x -= jau::adeg_to_rad(1.0f);
} else if( VKeyCode::VK_DOWN == kc ) {
m_parent.rotEuler().x += jau::adeg_to_rad(1.0f);
}
}
};
typedef std::shared_ptr<MyKeyListener> MyKeyListenerRef;
class MyPointerListener : public PointerListener {
private:
GearsES2& m_parent;
jau::math::Vec2i preWinPos;
jau::math::Vec3f startPos;
GearsObjectES2* m_picked = nullptr;
bool m_dragInit = true;
bool mapWinToObj(const GearsObjectES2& shape, const jau::math::Vec2i& winPos, jau::math::Vec3f& viewPos) noexcept {
// OK global: m_parent.m_pmvMatrix, m_parent.m_viewport
const jau::math::Vec3f& ctr = shape.objBounds().center();
if( m_parent.pmvMatrix().mapObjToWin(ctr, m_parent.viewport(), viewPos) ) {
const float winZ = viewPos.z;
return m_parent.pmvMatrix().mapWinToObj((float)winPos.x, (float)winPos.y, winZ, m_parent.viewport(), viewPos);
}
return false;
}
bool mapWinToObjRay(const jau::math::Vec2i& pos, jau::math::Ray3f& ray, const Mat4f& mPmvi) noexcept {
// OK global: m_parent.m_pmvMatrix, m_parent.m_viewport
constexpr float winZ0 = 0.0f;
constexpr float winZ1 = 0.3f;
return Mat4f::mapWinToAnyRay((float)pos.x, (float)pos.y, winZ0, winZ1, mPmvi, m_parent.viewport(), ray);
}
bool pick(const PointerEvent& e, const WindowRef&, GearsObjectES2& shape) noexcept {
// While being processed fast w/o matrix traversal of shapes,
// we still need to use the cached PMvi matrix for win->obj ray for accuracy.
// A win->view ray fails in certain angles in edge cases!
const jau::math::Vec2i& winPos = e.position();
if( !mapWinToObjRay(winPos, objRay, shape.matPMvi()) ) {
return false;
}
const jau::math::geom::AABBox3f& objBox = shape.objBounds();
if( !objBox.intersectsRay(objRay) ) {
return false;
}
if( !objBox.getRayIntersection(objPos, objRay, std::numeric_limits<float>::epsilon(), /*assumeIntersection=*/true) ) {
printf("obj getRayIntersection failed\n");
return false;
}
preWinPos = winPos;
printf("XXX pick: mouse %s -> %s\n", winPos.toString().c_str(), objPos.toString().c_str());
printf("XXX pick: %s\n", shape.toString().c_str());
return true;
}
bool navigate(const PointerEvent& e, const WindowRef& win, GearsObjectES2& shape) noexcept {
const jau::math::Vec2i& winPos = e.position();
if( !mapWinToObj(shape, winPos, objPos) ) {
return false;
}
if( e.isControlDown() ) {
if( m_dragInit ) {
m_dragInit = false;
startPos = objPos;
} else {
jau::math::Vec3f diffPos = ( objPos - startPos ).mul(flip);
m_parent.pan() += diffPos;
}
} else {
const jau::math::Vec2i& sdim = win->surfaceSize();
const float thetaY = 360.0f * ((float)(winPos.x - preWinPos.x) / (float)sdim.x);
const float thetaX = 360.0f * ((float)(preWinPos.y - winPos.y) / (float)sdim.y);
m_parent.rotEuler().x += jau::adeg_to_rad(thetaX);
m_parent.rotEuler().y += jau::adeg_to_rad(thetaY);
m_dragInit = true;
}
preWinPos = winPos;
// printf("XXX navi: mouse %s -> %s\n", winPos.toString().c_str(), objPos.toString().c_str());
return true;
}
PointerShapeAction pickAction, navigateAction;
public:
MyPointerListener(GearsES2& p): m_parent(p) {
pickAction = jau::bind_member(this, &MyPointerListener::pick);
navigateAction = jau::bind_member(this, &MyPointerListener::navigate);
}
void pointerPressed(PointerEvent& e) override {
if( e.pointerCount() == 1 ) {
WindowRef win = e.source().lock();
if( !win ) {
return;
}
GearsObjectES2* new_pick = m_parent.findPick(pickAction, e, win); // no matrix traversal
if( m_picked ) {
m_picked->picked() = false;
}
m_picked = new_pick;
if( m_picked ) {
m_picked->picked() = true;
}
}
}
void pointerDragged(PointerEvent& e) override {
if( m_picked ) {
WindowRef win = e.source().lock();
if( !win ) {
return;
}
if( !m_parent.dispatchForShape(*m_picked, navigateAction, e, win) ) { // matrix traversal
if( m_picked ) {
m_picked->picked() = false;
}
m_picked = nullptr;
printf("XXX shape: lost\n");
}
}
}
void pointerWheelMoved(PointerEvent& e) override {
const jau::math::Vec3f& rot = e.rotation();
if( e.isControlDown() ) {
// alternative zoom
float incr = e.isShiftDown() ? rot.x : rot.y * 0.5f;
m_parent.pan().z += incr;
} else {
// panning
m_parent.pan().x -= rot.x; // positive -> left
m_parent.pan().y += rot.y; // positive -> up
}
}
void pointerReleased(PointerEvent&) override {
if( m_picked ) {
m_picked->picked() = false;
printf("XXX shape: released\n");
}
m_picked = nullptr;
m_dragInit = true;
}
};
typedef std::shared_ptr<MyPointerListener> MyPointerListenerRef;
MyPointerListenerRef m_pl;
public:
: GearsES2(),
m_kl(std::make_shared<MyKeyListener>(*this)),
m_pl(std::make_shared<MyPointerListener>(*this))
{ }
bool init(const WindowRef& win, const jau::fraction_timespec& when) override {
if( !GearsES2::init(win, when) ) {
return false;
}
win->addKeyListener(m_kl);
win->addPointerListener(m_pl);
return true;
}
void dispose(const WindowRef& win, const jau::fraction_timespec& when) override {
win->removeKeyListener(m_kl);
win->removePointerListener(m_pl);
GearsES2::dispose(win, when);
}
};
int main(int argc, char *argv[]) // NOLINT(bugprone-exception-escape)
{
return launch("GearsES2.hpp",
std::make_shared<Example>(), argc, argv);
}
int launch(std::string_view sfile, const GLLaunchProps &props, const RenderListenerRef &demo, int argc, char *argv[])
int main(int argc, char *argv[])
Definition GearsES2.cpp:232
jau::function< bool(const PointerEvent &e, const WindowRef &win, GearsObjectES2 &shape)> PointerShapeAction
Definition GearsES2.hpp:49
std::shared_ptr< MyKeyListener > MyKeyListenerRef
void dispose(const WindowRef &win, const jau::fraction_timespec &when) override
Notifies the listener to perform the release of all renderer resources per context,...
Definition GearsES2.cpp:225
GearsES2.
Definition GearsES2.hpp:378
constexpr Vec3f & pan() noexcept
Definition GearsES2.hpp:430
bool init(const WindowRef &win, const jau::fraction_timespec &when) override
Called by the drawable immediately after the render context is initialized.
Definition GearsES2.hpp:452
constexpr bool doRotate() const noexcept
Definition GearsES2.hpp:423
constexpr void setDoRotate(bool rotate) noexcept
Definition GearsES2.hpp:424
GearsObjectES2 * findPick(const PointerShapeAction &action, const PointerEvent &e, const WindowRef &win)
Fast loop through all shapes using PointerShapeAction w/o matrix traversal using view-coordinates.
Definition GearsES2.hpp:614
constexpr jau::math::Vec3f & rotEuler() noexcept
Definition GearsES2.hpp:431
constexpr const jau::math::Recti & viewport() const noexcept
Definition GearsES2.hpp:429
bool dispatchForShape(GearsObjectES2 &shape, const PointerShapeAction &action, const PointerEvent &e, const WindowRef &win)
Dispatch PointerShapeAction to given shape w/ matrix traversal.
Definition GearsES2.hpp:634
constexpr PMVMat4f & pmvMatrix() noexcept
Definition GearsES2.hpp:427
void dispose(const WindowRef &win, const jau::fraction_timespec &when) override
Notifies the listener to perform the release of all renderer resources per context,...
Definition GearsES2.hpp:505
GearsObjectES2.
Definition GearsES2.hpp:55
std::string toString() const noexcept
Definition GearsES2.hpp:371
const jau::math::geom::AABBox3f & objBounds() const noexcept
Definition GearsES2.hpp:367
bool & picked() noexcept
Definition GearsES2.hpp:366
const jau::math::Mat4f & matPMvi() const noexcept
Definition GearsES2.hpp:369
constexpr bool isShiftDown() const noexcept
Returns true if modifier() contains InputModifier::shift.
Definition Event.hpp:285
constexpr bool isControlDown() const noexcept
Returns true if modifier() contains InputModifier::ctrl.
Definition Event.hpp:277
constexpr VKeyCode keySym() const noexcept
Returns the virtual key symbol reflecting the current keyboard layout.
Definition KeyEvent.hpp:798
Listener for multiple KeyEvent.
Definition KeyEvent.hpp:894
Pointer event of type PointerType.
constexpr const jau::math::Vec2i & position(size_t index=0) const noexcept
Returns position of given pointer-index in pixel units.
constexpr size_t pointerCount() const noexcept
See details for multiple-pointer events.
constexpr const jau::math::Vec3f & rotation() const noexcept
Returns a 3-component float array filled with the values of the rotational axis in the following orde...
Listener for PointerEvent.
constexpr const WindowWeakPtr & source() const noexcept
Definition Event.hpp:85
constexpr const jau::fraction_timespec & when() const noexcept
Definition Event.hpp:84
static bool mapWinToAnyRay(const value_type winx, const value_type winy, const value_type winz0, const value_type winz1, const Matrix4 &invAny, const Recti &viewport, Ray3 &ray) noexcept
Definition mat4f.hpp:1915
value_type x
Definition vec2i.hpp:65
std::string toString() const noexcept
Definition vec2i.hpp:211
value_type y
Definition vec2i.hpp:66
value_type x
Definition vec3f.hpp:69
value_type y
Definition vec3f.hpp:70
std::string toString() const noexcept
Definition vec3f.hpp:239
value_type z
Definition vec3f.hpp:71
Axis Aligned Bounding Box.
Definition aabbox3f.hpp:43
constexpr bool intersectsRay(const Ray3f &r) const noexcept
Check if Ray intersects this bounding box.
Definition aabbox3f.hpp:533
bool getRayIntersection(Vec3f &result, const Ray3f &ray, const float epsilon, const bool assumeIntersection) const noexcept
Return intersection of a Ray with this bounding box, or false if none exist.
Definition aabbox3f.hpp:578
constexpr const Point3f & center() const noexcept
Returns computed center of this aabbox3f of low() and high().
Definition aabbox3f.hpp:105
bool mapWinToObj(const float winx, const float winy, const float winz, const Recti &viewport, Vec3 &objPos) noexcept
Map window coordinates to object coordinates.
Definition pmvmat4f.hpp:935
bool mapObjToWin(const Vec3 &objPos, const Recti &viewport, Vec3 &winPos) const noexcept
Map object coordinates to window coordinates.
Definition pmvmat4f.hpp:888
constexpr T adeg_to_rad(const T arc_degree) noexcept
Converts arc-degree to radians.
jau::function< R(A...)> bind_member(C1 *base, R(C0::*mfunc)(A...)) noexcept
Bind given class instance and non-void member function to an anonymous function using func_member_tar...
@ verbose
Verbose operations (debugging).
VKeyCode
Virtual key code following UTF16 specification.
Definition KeyEvent.hpp:45
std::shared_ptr< Window > WindowRef
Definition Event.hpp:36
@ VK_ESCAPE
Constant for the ESCAPE function key.
Definition KeyEvent.hpp:129
@ VK_RIGHT
Constant for the cursor- or numerical-pad right arrow key.
Definition KeyEvent.hpp:461
@ VK_DOWN
Constant for the cursor- or numerical pad down arrow key.
Definition KeyEvent.hpp:464
@ VK_UP
Constant for the cursor- or numerical-pad up arrow key.
Definition KeyEvent.hpp:458
@ VK_LEFT
Constant for the cursor- or numerical-pad left arrow key.
Definition KeyEvent.hpp:455
@ VK_PAUSE
Constant for the PAUSE function key.
Definition KeyEvent.hpp:115
Matrix4< float > Mat4f
Definition mat4f.hpp:1973
Vector2I< int > Vec2i
Definition vec2i.hpp:328
Ray3F< float > Ray3f
Definition vec3f.hpp:502
constexpr jau::math::Vec3f getEulerAngleOrientation(const jau::math::Vec3f &eulerRotation) noexcept
Returns an orientation vector for given eurler X/Y/Z angles in radians.
Vector3F< float > Vec3f
Definition vec3f.hpp:436
int fprintf_td(const uint64_t elapsed_ms, FILE *stream, const char *format,...) noexcept
Convenient fprintf() invocation, prepending the given elapsed_ms timestamp.
Definition debug.cpp:270
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.