Visual Computing Library  devel
Loading...
Searching...
No Matches
abstract_viewer_drawer.h
1/*****************************************************************************
2 * VCLib *
3 * Visual Computing Library *
4 * *
5 * Copyright(C) 2021-2025 *
6 * Visual Computing Lab *
7 * ISTI - Italian National Research Council *
8 * *
9 * All rights reserved. *
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the Mozilla Public License Version 2.0 as published *
13 * by the Mozilla Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 * This program is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
19 * Mozilla Public License Version 2.0 *
20 * (https://www.mozilla.org/en-US/MPL/2.0/) for more details. *
21 ****************************************************************************/
22
23#ifndef VCL_RENDER_DRAWERS_ABSTRACT_VIEWER_DRAWER_H
24#define VCL_RENDER_DRAWERS_ABSTRACT_VIEWER_DRAWER_H
25
26#include <vclib/render/concepts/view_projection_event_drawer.h>
27#include <vclib/render/drawable/drawable_object_vector.h>
28#include <vclib/render/drawers/event_drawer.h>
29#include <vclib/render/read_buffer_types.h>
30#include <vclib/space/core/color.h>
31
32#include <memory>
33
34namespace vcl {
35
44template<typename ViewProjEventDrawer>
45class AbstractViewerDrawer : public ViewProjEventDrawer
46{
47 using Base = ViewProjEventDrawer;
48 using DRA = ViewProjEventDrawer::DRA;
49
50 bool mReadRequested = false;
51 bool mPBRMode = false;
52
53 // the default id for the viewer drawer is 0
54 uint mId = 0;
55
56protected:
57 // the list of drawable objects
58 // it could be owned by the viewer, or it could be shared with other
59 // objects (e.g. the window that contains the viewer along with other
60 // widgets)
61 std::shared_ptr<DrawableObjectVector> mDrawList =
62 std::make_shared<DrawableObjectVector>();
63
64 // the drawer id
65 uint& id() { return mId; }
66
67public:
68 AbstractViewerDrawer(uint width = 1024, uint height = 768) :
69 Base(width, height)
70 {
71 static_assert(
73 "AbstractViewerDrawer requires a ViewProjectionEventDrawer as a "
74 "base class");
75 }
76
77 ~AbstractViewerDrawer() = default;
78
79 const DrawableObjectVector& drawableObjectVector() const
80 {
81 return *mDrawList;
82 }
83
84 void setDrawableObjectVector(const std::shared_ptr<DrawableObjectVector>& v)
85 {
86 mDrawList = v;
87
88 for (auto obj : *mDrawList) {
89 obj->init();
90 }
91 fitScene();
92 }
93
94 uint pushDrawableObject(const DrawableObject& obj)
95 {
96 mDrawList->pushBack(obj);
97 mDrawList->back()->init();
98 return mDrawList->size() - 1;
99 }
100
101 uint pushDrawableObject(DrawableObject&& obj)
102 {
103 mDrawList->pushBack(std::move(obj));
104 mDrawList->back()->init();
105 return mDrawList->size() - 1;
106 }
107
108 void fitScene()
109 {
111 float sceneRadius = 1;
112
113 Box3d bb = mDrawList->boundingBox();
114
115 if (!bb.isNull()) {
116 sceneCenter = bb.center().cast<float>();
118 }
119
120 Base::fitScene(sceneCenter, sceneRadius);
121 }
122
123 bool isPBREnabled() const { return mPBRMode; }
124
125 void setPBR(bool enable) { mPBRMode = enable; }
126
127 void enablePBR() { setPBR(true); }
128
129 void disablePBR() { setPBR(false); }
130
131 void fitView()
132 {
133 Point3f sceneCenter = mDrawList->center().cast<float>();
134
135 Base::fitView(sceneCenter);
136 }
137
138 // events
139 void onInit(uint) override
140 {
141 DRA::DRW::setCanvasDefaultClearColor(derived(), Color::DarkGray);
142 }
143
144 void onKeyPress(Key::Enum key, const KeyModifiers& modifiers) override
145 {
146 Base::onKeyPress(key, modifiers);
147
148 switch (key) {
149 case Key::S:
150 if (modifiers[KeyModifier::CONTROL])
151 DRA::DRW::screenshot(derived(), "viewer_screenshot.png");
152 break;
153
154 default: break;
155 }
156 }
157
158protected:
159 void readDepthRequest(double x, double y, bool homogeneousNDC = true)
160 {
161 using ReadData = ReadBufferTypes::ReadData;
162 using FloatData = ReadBufferTypes::FloatData;
163 using MatrixType = Base::MatrixType;
164
165 if (mReadRequested)
166 return;
167
168 // get point
169 const Point2d p(x, y);
170
171 // create the callback
172 const auto proj = Base::projectionMatrix();
173 const auto view = Base::viewMatrix();
174 // viewport
175 auto size = DRA::DRW::canvasSize(derived());
176
177 const Point4f vp = {.0f, .0f, float(size.x()), float(size.y())};
178
179 auto callback = [=, this](const ReadData& dt) {
180 const auto& data = std::get<FloatData>(dt);
181 assert(data.size() == 1);
182 const float depth = data[0];
183
184 mReadRequested = false;
185
186 // if the depth is 1.0, the point is not in the scene
187 if (depth == 1.0f) {
188 return;
189 }
190
191 // unproject the point
192 const Point3f p2d(p.x(), vp[3] - p.y(), depth);
193 auto unproj =
194 unproject(p2d, MatrixType(proj * view), vp, homogeneousNDC);
195
196 this->focus(unproj);
197 derived()->update();
198 };
199
200 mReadRequested =
201 DRA::DRW::readDepth(derived(), Point2i(p.x(), p.y()), callback);
202 if (mReadRequested)
203 derived()->update();
204 }
205
206 void readIdRequest(double x, double y, std::function<void(uint)> idCallback)
207 {
208 using ReadData = ReadBufferTypes::ReadData;
209
210 if (mReadRequested)
211 return;
212
213 // get point
214 const Point2d p(x, y);
215
216 // create the callback
217 auto callback = [=, this](const ReadData& dt) {
218 const auto& data = std::get<ReadBufferTypes::ByteData>(dt);
219 assert(data.size() == 4);
220 // TODO: check how to do this properly
221 const uint id = *(uint32_t*) &data[0];
222
223 mReadRequested = false;
224
225 idCallback(id);
226 derived()->update();
227 };
228
229 mReadRequested =
230 DRA::DRW::readId(derived(), Point2i(p.x(), p.y()), callback);
231 if (mReadRequested)
232 derived()->update();
233 }
234
235private:
236 auto* derived() { return static_cast<DRA*>(this); }
237
238 const auto* derived() const { return static_cast<const DRA*>(this); }
239};
240
241} // namespace vcl
242
243#endif // VCL_RENDER_DRAWERS_ABSTRACT_VIEWER_DRAWER_H
The AbstractViewerDrawer class is a base class for all viewer drawers implementations.
Definition abstract_viewer_drawer.h:46
A class representing a box in N-dimensional space.
Definition box.h:46
auto diagonal() const
Calculates the diagonal length of the box.
Definition box.h:246
PointT center() const
Calculates the center point of the box.
Definition box.h:259
bool isNull() const
Checks whether the box is null or not.
Definition box.h:133
Definition drawable_object_vector.h:36
The DrawableObject class is the base class for all the objects that can be drawn in a 3D viewer.
Definition drawable_object.h:57
The Point class represents an N-dimensional point containing N scalar values.
Definition point.h:55
Definition view_projection_event_drawer.h:32
Point2< int > Point2i
A convenience alias for a 2-dimensional Point with integer components.
Definition point.h:707